<commit_before>use std::time::Duration;

use actix_codec::{AsyncRead, AsyncWrite};
use actix_connector::{Resolver, TcpConnector};
use actix_service::{Service, ServiceExt};
use actix_utils::timeout::{TimeoutError, TimeoutService};
use trust_dns_resolver::config::{ResolverConfig, ResolverOpts};

use super::connect::Connect;
use super::connection::Connection;
use super::error::ConnectorError;
use super::pool::{ConnectionPool, Protocol};

#[cfg(feature = "ssl")]
use openssl::ssl::SslConnector;

#[cfg(not(feature = "ssl"))]
type SslConnector = ();

/// Http client connector builde instance.
/// `Connector` type uses builder-like pattern for connector service construction.
pub struct Connector {
    resolver: Resolver<Connect>,
    timeout: Duration,
    conn_lifetime: Duration,
    conn_keep_alive: Duration,
    disconnect_timeout: Duration,
    limit: usize,
    #[allow(dead_code)]
    connector: SslConnector,
}

impl Default for Connector {
    fn default() -> Connector {
        let connector = {
            #[cfg(feature = "ssl")]
            {
                use log::error;
                use openssl::ssl::{SslConnector, SslMethod};

                let mut ssl = SslConnector::builder(SslMethod::tls()).unwrap();
                let _ = ssl
                    .set_alpn_protos(b"\x02h2\x08http/1.1")
                    .map_err(|e| error!("Can not set alpn protocol: {:?}", e));
                ssl.build()
            }
            #[cfg(not(feature = "ssl"))]
            {}
        };

        Connector {
            connector,
            resolver: Resolver::default(),
            timeout: Duration::from_secs(1),
            conn_lifetime: Duration::from_secs(75),
            conn_keep_alive: Duration::from_secs(15),
            disconnect_timeout: Duration::from_millis(3000),
            limit: 100,
        }
    }
}

impl Connector {
    /// Use custom resolver.
    pub fn resolver(mut self, resolver: Resolver<Connect>) -> Self {
        self.resolver = resolver;;
        self
    }

    /// Use custom resolver configuration.
    pub fn resolver_config(mut self, cfg: ResolverConfig, opts: ResolverOpts) -> Self {
        self.resolver = Resolver::new(cfg, opts);
        self
    }

    /// Connection timeout, i.e. max time to connect to remote host including dns name resolution.
    /// Set to 1 second by default.
    pub fn timeout(mut self, timeout: Duration) -> Self {
        self.timeout = timeout;
        self
    }

    #[cfg(feature = "ssl")]
    /// Use custom `SslConnector` instance.
    pub fn ssl(mut self, connector: SslConnector) -> Self {
        self.connector = connector;
        self
    }

    /// Set total number of simultaneous connections per type of scheme.
    ///
    /// If limit is 0, the connector has no limit.
    /// The default limit size is 100.
    pub fn limit(mut self, limit: usize) -> Self {
        self.limit = limit;
        self
    }

    /// Set keep-alive period for opened connection.
    ///
    /// Keep-alive period is the period between connection usage. If
    /// the delay between repeated usages of the same connection
    /// exceeds this period, the connection is closed.
    /// Default keep-alive period is 15 seconds.
    pub fn conn_keep_alive(mut self, dur: Duration) -> Self {
        self.conn_keep_alive = dur;
        self
    }

    /// Set max lifetime period for connection.
    ///
    /// Connection lifetime is max lifetime of any opened connection
    /// until it is closed regardless of keep-alive period.
    /// Default lifetime period is 75 seconds.
    pub fn conn_lifetime(mut self, dur: Duration) -> Self {
        self.conn_lifetime = dur;
        self
    }

    /// Set server connection disconnect timeout in milliseconds.
    ///
    /// Defines a timeout for disconnect connection. If a disconnect procedure does not complete
    /// within this time, the socket get dropped. This timeout affects only secure connections.
    ///
    /// To disable timeout set value to 0.
    ///
    /// By default disconnect timeout is set to 3000 milliseconds.
    pub fn disconnect_timeout(mut self, dur: Duration) -> Self {
        self.disconnect_timeout = dur;
        self
    }

    /// Finish configuration process and create connector service.
    pub fn service(
        self,
    ) -> impl Service<Connect, Response = impl Connection, Error = ConnectorError> + Clone
    {
        #[cfg(not(feature = "ssl"))]
        {
            let connector = TimeoutService::new(
                self.timeout,
                self.resolver.map_err(ConnectorError::from).and_then(
                    TcpConnector::default()
                        .from_err()
                        .map(|(msg, io)| (msg, io, Protocol::Http1)),
                ),
            )
            .map_err(|e| match e {
                TimeoutError::Service(e) => e,
                TimeoutError::Timeout => ConnectorError::Timeout,
            });

            connect_impl::InnerConnector {
                tcp_pool: ConnectionPool::new(
                    connector,
                    self.conn_lifetime,
                    self.conn_keep_alive,
                    None,
                    self.limit,
                ),
            }
        }
        #[cfg(feature = "ssl")]
        {
            const H2: &[u8] = b"h2";
            use actix_connector::ssl::OpensslConnector;

            let ssl_service = TimeoutService::new(
                self.timeout,
                self.resolver
                    .clone()
                    .map_err(ConnectorError::from)
                    .and_then(TcpConnector::default().from_err())
                    .and_then(
                        OpensslConnector::service(self.connector)
                            .map_err(ConnectorError::from)
                            .map(|(msg, io)| {
                                let h2 = io
                                    .get_ref()
                                    .ssl()
                                    .selected_alpn_protocol()
                                    .map(|protos| protos.windows(2).any(|w| w == H2))
                                    .unwrap_or(false);
                                if h2 {
                                    (msg, io, Protocol::Http2)
                                } else {
                                    (msg, io, Protocol::Http1)
                                }
                            }),
                    ),
            )
            .map_err(|e| match e {
                TimeoutError::Service(e) => e,
                TimeoutError::Timeout => ConnectorError::Timeout,
            });

            let tcp_service = TimeoutService::new(
                self.timeout,
                self.resolver.map_err(ConnectorError::from).and_then(
                    TcpConnector::default()
                        .from_err()
                        .map(|(msg, io)| (msg, io, Protocol::Http1)),
                ),
            )
            .map_err(|e| match e {
                TimeoutError::Service(e) => e,
                TimeoutError::Timeout => ConnectorError::Timeout,
            });

            connect_impl::InnerConnector {
                tcp_pool: ConnectionPool::new(
                    tcp_service,
                    self.conn_lifetime,
                    self.conn_keep_alive,
                    None,
                    self.limit,
                ),
                ssl_pool: ConnectionPool::new(
                    ssl_service,
                    self.conn_lifetime,
                    self.conn_keep_alive,
                    Some(self.disconnect_timeout),
                    self.limit,
                ),
            }
        }
    }
}

#[cfg(not(feature = "ssl"))]
mod connect_impl {
    use futures::future::{err, Either, FutureResult};
    use futures::Poll;

    use super::*;
    use crate::client::connection::IoConnection;

    pub(crate) struct InnerConnector<T, Io>
    where
        Io: AsyncRead + AsyncWrite + 'static,
        T: Service<
            Request = Connect,
            Response = (Connect, Io, Protocol),
            Error = ConnectorError,
        >,
    {
        pub(crate) tcp_pool: ConnectionPool<T, Io>,
    }

    impl<T, Io> Clone for InnerConnector<T, Io>
    where
        Io: AsyncRead + AsyncWrite + 'static,
        T: Service<
                Request = Connect,
                Response = (Connect, Io, Protocol),
                Error = ConnectorError,
            > + Clone,
    {
        fn clone(&self) -> Self {
            InnerConnector {
                tcp_pool: self.tcp_pool.clone(),
            }
        }
    }

    impl<T, Io> Service for InnerConnector<T, Io>
    where
        Io: AsyncRead + AsyncWrite + 'static,
        T: Service<
            Request = Connect,
            Response = (Connect, Io, Protocol),
            Error = ConnectorError,
        >,
    {
        type Request = Connect;
        type Response = IoConnection<Io>;
        type Error = ConnectorError;
        type Future = Either<
            <ConnectionPool<T, Io> as Service>::Future,
            FutureResult<IoConnection<Io>, ConnectorError>,
        >;

        fn poll_ready(&mut self) -> Poll<(), Self::Error> {
            self.tcp_pool.poll_ready()
        }

        fn call(&mut self, req: Connect) -> Self::Future {
            if req.is_secure() {
                Either::B(err(ConnectorError::SslIsNotSupported))
            } else if let Err(e) = req.validate() {
                Either::B(err(e))
            } else {
                Either::A(self.tcp_pool.call(req))
            }
        }
    }
}

#[cfg(feature = "ssl")]
mod connect_impl {
    use std::marker::PhantomData;

    use futures::future::{err, Either, FutureResult};
    use futures::{Async, Future, Poll};

    use super::*;
    use crate::client::connection::EitherConnection;

    pub(crate) struct InnerConnector<T1, T2, Io1, Io2>
    where
        Io1: AsyncRead + AsyncWrite + 'static,
        Io2: AsyncRead + AsyncWrite + 'static,
        T1: Service<
            Connect,
            Response = (Connect, Io1, Protocol),
            Error = ConnectorError,
        >,
        T2: Service<
            Connect,
            Response = (Connect, Io2, Protocol),
            Error = ConnectorError,
        >,
    {
        pub(crate) tcp_pool: ConnectionPool<T1, Io1>,
        pub(crate) ssl_pool: ConnectionPool<T2, Io2>,
    }

    impl<T1, T2, Io1, Io2> Clone for InnerConnector<T1, T2, Io1, Io2>
    where
        Io1: AsyncRead + AsyncWrite + 'static,
        Io2: AsyncRead + AsyncWrite + 'static,
        T1: Service<
                Connect,
                Response = (Connect, Io1, Protocol),
                Error = ConnectorError,
            > + Clone,
        T2: Service<
                Connect,
                Response = (Connect, Io2, Protocol),
                Error = ConnectorError,
            > + Clone,
    {
        fn clone(&self) -> Self {
            InnerConnector {
                tcp_pool: self.tcp_pool.clone(),
                ssl_pool: self.ssl_pool.clone(),
            }
        }
    }

    impl<T1, T2, Io1, Io2> Service<Connect> for InnerConnector<T1, T2, Io1, Io2>
    where
        Io1: AsyncRead + AsyncWrite + 'static,
        Io2: AsyncRead + AsyncWrite + 'static,
        T1: Service<
            Connect,
            Response = (Connect, Io1, Protocol),
            Error = ConnectorError,
        >,
        T2: Service<
            Connect,
            Response = (Connect, Io2, Protocol),
            Error = ConnectorError,
        >,
    {
        type Response = EitherConnection<Io1, Io2>;
        type Error = ConnectorError;
        type Future = Either<
            FutureResult<Self::Response, Self::Error>,
            Either<
                InnerConnectorResponseA<T1, Io1, Io2>,
                InnerConnectorResponseB<T2, Io1, Io2>,
            >,
        >;

        fn poll_ready(&mut self) -> Poll<(), Self::Error> {
            self.tcp_pool.poll_ready()
        }

        fn call(&mut self, req: Connect) -> Self::Future {
            if let Err(e) = req.validate() {
                Either::A(err(e))
            } else if req.is_secure() {
                Either::B(Either::B(InnerConnectorResponseB {
                    fut: self.ssl_pool.call(req),
                    _t: PhantomData,
                }))
            } else {
                Either::B(Either::A(InnerConnectorResponseA {
                    fut: self.tcp_pool.call(req),
                    _t: PhantomData,
                }))
            }
        }
    }

    pub(crate) struct InnerConnectorResponseA<T, Io1, Io2>
    where
        Io1: AsyncRead + AsyncWrite + 'static,
        T: Service<Connect, Response = (Connect, Io1, Protocol), Error = ConnectorError>,
    {
        fut: <ConnectionPool<T, Io1> as Service<Connect>>::Future,
        _t: PhantomData<Io2>,
    }

    impl<T, Io1, Io2> Future for InnerConnectorResponseA<T, Io1, Io2>
    where
        T: Service<Connect, Response = (Connect, Io1, Protocol), Error = ConnectorError>,
        Io1: AsyncRead + AsyncWrite + 'static,
        Io2: AsyncRead + AsyncWrite + 'static,
    {
        type Item = EitherConnection<Io1, Io2>;
        type Error = ConnectorError;

        fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
            match self.fut.poll()? {
                Async::NotReady => Ok(Async::NotReady),
                Async::Ready(res) => Ok(Async::Ready(EitherConnection::A(res))),
            }
        }
    }

    pub(crate) struct InnerConnectorResponseB<T, Io1, Io2>
    where
        Io2: AsyncRead + AsyncWrite + 'static,
        T: Service<Connect, Response = (Connect, Io2, Protocol), Error = ConnectorError>,
    {
        fut: <ConnectionPool<T, Io2> as Service<Connect>>::Future,
        _t: PhantomData<Io1>,
    }

    impl<T, Io1, Io2> Future for InnerConnectorResponseB<T, Io1, Io2>
    where
        T: Service<Connect, Response = (Connect, Io2, Protocol), Error = ConnectorError>,
        Io1: AsyncRead + AsyncWrite + 'static,
        Io2: AsyncRead + AsyncWrite + 'static,
    {
        type Item = EitherConnection<Io1, Io2>;
        type Error = ConnectorError;

        fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
            match self.fut.poll()? {
                Async::NotReady => Ok(Async::NotReady),
                Async::Ready(res) => Ok(Async::Ready(EitherConnection::B(res))),
            }
        }
    }
}
<commit_msg>fix non ssl code<commit_after>use std::time::Duration;

use actix_codec::{AsyncRead, AsyncWrite};
use actix_connector::{Resolver, TcpConnector};
use actix_service::{Service, ServiceExt};
use actix_utils::timeout::{TimeoutError, TimeoutService};
use trust_dns_resolver::config::{ResolverConfig, ResolverOpts};

use super::connect::Connect;
use super::connection::Connection;
use super::error::ConnectorError;
use super::pool::{ConnectionPool, Protocol};

#[cfg(feature = "ssl")]
use openssl::ssl::SslConnector;

#[cfg(not(feature = "ssl"))]
type SslConnector = ();

/// Http client connector builde instance.
/// `Connector` type uses builder-like pattern for connector service construction.
pub struct Connector {
    resolver: Resolver<Connect>,
    timeout: Duration,
    conn_lifetime: Duration,
    conn_keep_alive: Duration,
    disconnect_timeout: Duration,
    limit: usize,
    #[allow(dead_code)]
    connector: SslConnector,
}

impl Default for Connector {
    fn default() -> Connector {
        let connector = {
            #[cfg(feature = "ssl")]
            {
                use log::error;
                use openssl::ssl::{SslConnector, SslMethod};

                let mut ssl = SslConnector::builder(SslMethod::tls()).unwrap();
                let _ = ssl
                    .set_alpn_protos(b"\x02h2\x08http/1.1")
                    .map_err(|e| error!("Can not set alpn protocol: {:?}", e));
                ssl.build()
            }
            #[cfg(not(feature = "ssl"))]
            {}
        };

        Connector {
            connector,
            resolver: Resolver::default(),
            timeout: Duration::from_secs(1),
            conn_lifetime: Duration::from_secs(75),
            conn_keep_alive: Duration::from_secs(15),
            disconnect_timeout: Duration::from_millis(3000),
            limit: 100,
        }
    }
}

impl Connector {
    /// Use custom resolver.
    pub fn resolver(mut self, resolver: Resolver<Connect>) -> Self {
        self.resolver = resolver;;
        self
    }

    /// Use custom resolver configuration.
    pub fn resolver_config(mut self, cfg: ResolverConfig, opts: ResolverOpts) -> Self {
        self.resolver = Resolver::new(cfg, opts);
        self
    }

    /// Connection timeout, i.e. max time to connect to remote host including dns name resolution.
    /// Set to 1 second by default.
    pub fn timeout(mut self, timeout: Duration) -> Self {
        self.timeout = timeout;
        self
    }

    #[cfg(feature = "ssl")]
    /// Use custom `SslConnector` instance.
    pub fn ssl(mut self, connector: SslConnector) -> Self {
        self.connector = connector;
        self
    }

    /// Set total number of simultaneous connections per type of scheme.
    ///
    /// If limit is 0, the connector has no limit.
    /// The default limit size is 100.
    pub fn limit(mut self, limit: usize) -> Self {
        self.limit = limit;
        self
    }

    /// Set keep-alive period for opened connection.
    ///
    /// Keep-alive period is the period between connection usage. If
    /// the delay between repeated usages of the same connection
    /// exceeds this period, the connection is closed.
    /// Default keep-alive period is 15 seconds.
    pub fn conn_keep_alive(mut self, dur: Duration) -> Self {
        self.conn_keep_alive = dur;
        self
    }

    /// Set max lifetime period for connection.
    ///
    /// Connection lifetime is max lifetime of any opened connection
    /// until it is closed regardless of keep-alive period.
    /// Default lifetime period is 75 seconds.
    pub fn conn_lifetime(mut self, dur: Duration) -> Self {
        self.conn_lifetime = dur;
        self
    }

    /// Set server connection disconnect timeout in milliseconds.
    ///
    /// Defines a timeout for disconnect connection. If a disconnect procedure does not complete
    /// within this time, the socket get dropped. This timeout affects only secure connections.
    ///
    /// To disable timeout set value to 0.
    ///
    /// By default disconnect timeout is set to 3000 milliseconds.
    pub fn disconnect_timeout(mut self, dur: Duration) -> Self {
        self.disconnect_timeout = dur;
        self
    }

    /// Finish configuration process and create connector service.
    pub fn service(
        self,
    ) -> impl Service<Connect, Response = impl Connection, Error = ConnectorError> + Clone
    {
        #[cfg(not(feature = "ssl"))]
        {
            let connector = TimeoutService::new(
                self.timeout,
                self.resolver.map_err(ConnectorError::from).and_then(
                    TcpConnector::default()
                        .from_err()
                        .map(|(msg, io)| (msg, io, Protocol::Http1)),
                ),
            )
            .map_err(|e| match e {
                TimeoutError::Service(e) => e,
                TimeoutError::Timeout => ConnectorError::Timeout,
            });

            connect_impl::InnerConnector {
                tcp_pool: ConnectionPool::new(
                    connector,
                    self.conn_lifetime,
                    self.conn_keep_alive,
                    None,
                    self.limit,
                ),
            }
        }
        #[cfg(feature = "ssl")]
        {
            const H2: &[u8] = b"h2";
            use actix_connector::ssl::OpensslConnector;

            let ssl_service = TimeoutService::new(
                self.timeout,
                self.resolver
                    .clone()
                    .map_err(ConnectorError::from)
                    .and_then(TcpConnector::default().from_err())
                    .and_then(
                        OpensslConnector::service(self.connector)
                            .map_err(ConnectorError::from)
                            .map(|(msg, io)| {
                                let h2 = io
                                    .get_ref()
                                    .ssl()
                                    .selected_alpn_protocol()
                                    .map(|protos| protos.windows(2).any(|w| w == H2))
                                    .unwrap_or(false);
                                if h2 {
                                    (msg, io, Protocol::Http2)
                                } else {
                                    (msg, io, Protocol::Http1)
                                }
                            }),
                    ),
            )
            .map_err(|e| match e {
                TimeoutError::Service(e) => e,
                TimeoutError::Timeout => ConnectorError::Timeout,
            });

            let tcp_service = TimeoutService::new(
                self.timeout,
                self.resolver.map_err(ConnectorError::from).and_then(
                    TcpConnector::default()
                        .from_err()
                        .map(|(msg, io)| (msg, io, Protocol::Http1)),
                ),
            )
            .map_err(|e| match e {
                TimeoutError::Service(e) => e,
                TimeoutError::Timeout => ConnectorError::Timeout,
            });

            connect_impl::InnerConnector {
                tcp_pool: ConnectionPool::new(
                    tcp_service,
                    self.conn_lifetime,
                    self.conn_keep_alive,
                    None,
                    self.limit,
                ),
                ssl_pool: ConnectionPool::new(
                    ssl_service,
                    self.conn_lifetime,
                    self.conn_keep_alive,
                    Some(self.disconnect_timeout),
                    self.limit,
                ),
            }
        }
    }
}

#[cfg(not(feature = "ssl"))]
mod connect_impl {
    use futures::future::{err, Either, FutureResult};
    use futures::Poll;

    use super::*;
    use crate::client::connection::IoConnection;

    pub(crate) struct InnerConnector<T, Io>
    where
        Io: AsyncRead + AsyncWrite + 'static,
        T: Service<Connect, Response = (Connect, Io, Protocol), Error = ConnectorError>,
    {
        pub(crate) tcp_pool: ConnectionPool<T, Io>,
    }

    impl<T, Io> Clone for InnerConnector<T, Io>
    where
        Io: AsyncRead + AsyncWrite + 'static,
        T: Service<Connect, Response = (Connect, Io, Protocol), Error = ConnectorError>
            + Clone,
    {
        fn clone(&self) -> Self {
            InnerConnector {
                tcp_pool: self.tcp_pool.clone(),
            }
        }
    }

    impl<T, Io> Service<Connect> for InnerConnector<T, Io>
    where
        Io: AsyncRead + AsyncWrite + 'static,
        T: Service<Connect, Response = (Connect, Io, Protocol), Error = ConnectorError>,
    {
        type Response = IoConnection<Io>;
        type Error = ConnectorError;
        type Future = Either<
            <ConnectionPool<T, Io> as Service<Connect>>::Future,
            FutureResult<IoConnection<Io>, ConnectorError>,
        >;

        fn poll_ready(&mut self) -> Poll<(), Self::Error> {
            self.tcp_pool.poll_ready()
        }

        fn call(&mut self, req: Connect) -> Self::Future {
            if req.is_secure() {
                Either::B(err(ConnectorError::SslIsNotSupported))
            } else if let Err(e) = req.validate() {
                Either::B(err(e))
            } else {
                Either::A(self.tcp_pool.call(req))
            }
        }
    }
}

#[cfg(feature = "ssl")]
mod connect_impl {
    use std::marker::PhantomData;

    use futures::future::{err, Either, FutureResult};
    use futures::{Async, Future, Poll};

    use super::*;
    use crate::client::connection::EitherConnection;

    pub(crate) struct InnerConnector<T1, T2, Io1, Io2>
    where
        Io1: AsyncRead + AsyncWrite + 'static,
        Io2: AsyncRead + AsyncWrite + 'static,
        T1: Service<
            Connect,
            Response = (Connect, Io1, Protocol),
            Error = ConnectorError,
        >,
        T2: Service<
            Connect,
            Response = (Connect, Io2, Protocol),
            Error = ConnectorError,
        >,
    {
        pub(crate) tcp_pool: ConnectionPool<T1, Io1>,
        pub(crate) ssl_pool: ConnectionPool<T2, Io2>,
    }

    impl<T1, T2, Io1, Io2> Clone for InnerConnector<T1, T2, Io1, Io2>
    where
        Io1: AsyncRead + AsyncWrite + 'static,
        Io2: AsyncRead + AsyncWrite + 'static,
        T1: Service<
                Connect,
                Response = (Connect, Io1, Protocol),
                Error = ConnectorError,
            > + Clone,
        T2: Service<
                Connect,
                Response = (Connect, Io2, Protocol),
                Error = ConnectorError,
            > + Clone,
    {
        fn clone(&self) -> Self {
            InnerConnector {
                tcp_pool: self.tcp_pool.clone(),
                ssl_pool: self.ssl_pool.clone(),
            }
        }
    }

    impl<T1, T2, Io1, Io2> Service<Connect> for InnerConnector<T1, T2, Io1, Io2>
    where
        Io1: AsyncRead + AsyncWrite + 'static,
        Io2: AsyncRead + AsyncWrite + 'static,
        T1: Service<
            Connect,
            Response = (Connect, Io1, Protocol),
            Error = ConnectorError,
        >,
        T2: Service<
            Connect,
            Response = (Connect, Io2, Protocol),
            Error = ConnectorError,
        >,
    {
        type Response = EitherConnection<Io1, Io2>;
        type Error = ConnectorError;
        type Future = Either<
            FutureResult<Self::Response, Self::Error>,
            Either<
                InnerConnectorResponseA<T1, Io1, Io2>,
                InnerConnectorResponseB<T2, Io1, Io2>,
            >,
        >;

        fn poll_ready(&mut self) -> Poll<(), Self::Error> {
            self.tcp_pool.poll_ready()
        }

        fn call(&mut self, req: Connect) -> Self::Future {
            if let Err(e) = req.validate() {
                Either::A(err(e))
            } else if req.is_secure() {
                Either::B(Either::B(InnerConnectorResponseB {
                    fut: self.ssl_pool.call(req),
                    _t: PhantomData,
                }))
            } else {
                Either::B(Either::A(InnerConnectorResponseA {
                    fut: self.tcp_pool.call(req),
                    _t: PhantomData,
                }))
            }
        }
    }

    pub(crate) struct InnerConnectorResponseA<T, Io1, Io2>
    where
        Io1: AsyncRead + AsyncWrite + 'static,
        T: Service<Connect, Response = (Connect, Io1, Protocol), Error = ConnectorError>,
    {
        fut: <ConnectionPool<T, Io1> as Service<Connect>>::Future,
        _t: PhantomData<Io2>,
    }

    impl<T, Io1, Io2> Future for InnerConnectorResponseA<T, Io1, Io2>
    where
        T: Service<Connect, Response = (Connect, Io1, Protocol), Error = ConnectorError>,
        Io1: AsyncRead + AsyncWrite + 'static,
        Io2: AsyncRead + AsyncWrite + 'static,
    {
        type Item = EitherConnection<Io1, Io2>;
        type Error = ConnectorError;

        fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
            match self.fut.poll()? {
                Async::NotReady => Ok(Async::NotReady),
                Async::Ready(res) => Ok(Async::Ready(EitherConnection::A(res))),
            }
        }
    }

    pub(crate) struct InnerConnectorResponseB<T, Io1, Io2>
    where
        Io2: AsyncRead + AsyncWrite + 'static,
        T: Service<Connect, Response = (Connect, Io2, Protocol), Error = ConnectorError>,
    {
        fut: <ConnectionPool<T, Io2> as Service<Connect>>::Future,
        _t: PhantomData<Io1>,
    }

    impl<T, Io1, Io2> Future for InnerConnectorResponseB<T, Io1, Io2>
    where
        T: Service<Connect, Response = (Connect, Io2, Protocol), Error = ConnectorError>,
        Io1: AsyncRead + AsyncWrite + 'static,
        Io2: AsyncRead + AsyncWrite + 'static,
    {
        type Item = EitherConnection<Io1, Io2>;
        type Error = ConnectorError;

        fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
            match self.fut.poll()? {
                Async::NotReady => Ok(Async::NotReady),
                Async::Ready(res) => Ok(Async::Ready(EitherConnection::B(res))),
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate chrono;

use flowgger::Decoder;
use flowgger::config::Config;
use flowgger::record::{Record, Pri, StructuredData};
use self::chrono::DateTime;

#[derive(Clone)]
pub struct RFC5424;

impl Decoder for RFC5424 {
    fn new(config: &Config) -> RFC5424 {
        let _ = config;
        RFC5424
    }

    fn decode(&self, line: &str) -> Result<Record, &'static str> {
        let (bom, line) = match BOM::parse(line, "<") {
            Ok(bom_line) => bom_line,
            Err(err) => return Err(err)
        };
        let mut parts = line.splitn(7, ' ');
        let pri_version = try!(parse_pri_version(try!(parts.next().ok_or("Missing priority and version"))));
        let ts = try!(parse_ts(try!(parts.next().ok_or("Missing timestamp"))));
        let hostname = try!(parts.next().ok_or("Missing hostname"));
        let appname = try!(parts.next().ok_or("Missing application name"));
        let procid = try!(parts.next().ok_or("Missing process id"));
        let msgid = try!(parts.next().ok_or("Missing message id"));
        let (sd, msg) = try!(parse_data(try!(parts.next().ok_or("Missing message data"))));
        let record = Record {
            pri: Some(pri_version),
            ts: ts,
            hostname: hostname.to_owned(),
            appname: Some(appname.to_owned()),
            procid: Some(procid.to_owned()),
            msgid: Some(msgid.to_owned()),
            sd: sd,
            msg: msg
        };
        Ok(record)
    }
}

impl Pri {
    fn new(encoded: u8) -> Pri {
        Pri {
            facility: encoded >> 3,
            severity: encoded & 7
        }
    }
}

enum BOM {
    NONE,
    UTF8
}

impl BOM {
    fn parse<'a>(line: &'a str, sep: &str) -> Result<(BOM, &'a str), &'static str> {
        if line.starts_with("\u{feff}") {
            Ok((BOM::UTF8, &line[3..]))
        } else if line.starts_with(sep) {
            Ok((BOM::NONE, line))
        } else {
            Err("Unsupported BOM")
        }
    }
}

fn parse_pri_version(line: &str) -> Result<Pri, &'static str> {
    if ! line.starts_with("<") {
        return Err("The priority should be inside brackets")
    }
    let mut parts = line[1..].splitn(2, '>');
    let pri: u8 = try!(try!(parts.next().ok_or("Empty priority")).parse().or(Err("Invalid priority")));
    let version = try!(parts.next().ok_or("Missing version"));
    if version != "1" {
        return Err("Unsupported version");
    }
    Ok(Pri::new(pri))
}

fn rfc3339_to_unix(rfc3339: &str) -> Result<i64, &'static str> {
    match DateTime::parse_from_rfc3339(rfc3339) {
        Ok(date) => Ok(date.timestamp()),
        Err(_) => Err("Unable to parse the date")
    }
}

fn parse_ts(line: &str) -> Result<i64, &'static str> {
    rfc3339_to_unix(line)
}

fn unescape_sd_value(value: &str) -> String {
    let mut res = "".to_owned();
    let mut esc = false;

    for c in value.chars() {
        match (c, esc) {
            ('\\', false) => esc = true,
            (_, false) => res.push(c),
            ('"', true) | ('\\', true) | (']', true) => {
                res.push(c);
                esc = false;
            }
            (_, true) => {
                res.push('\\');
                res.push(c);
                esc = false;
            }
        }
    }
    res
}

fn parse_msg(line: &str, offset: usize) -> Option<String> {
    if offset > line.len() {
        None
    } else {
        match line[offset..].trim() {
            "" => None,
            m @ _ => Some(m.to_owned())
        }
    }
}

fn parse_data(line: &str) -> Result<(Option<StructuredData>, Option<String>), &'static str> {
    match try!(line.chars().next().ok_or("Short message")) {
        '-' => {
            return Ok((None, parse_msg(line, 1)));
        }
        '[' => { }
        _ => return Err("Short message")
    };
    let mut parts = line[1..].splitn(2, ' ');
    let sd_id = try!(parts.next().ok_or("Missing structured data id"));
    let sd = try!(parts.next().ok_or("Missing structured data"));
    let mut in_name = false;
    let mut in_value = false;
    let mut name_start = 0;
    let mut value_start = 0;
    let mut name: Option<&str> = None;
    let mut esc = false;
    let mut after_sd: Option<usize> = None;
    let mut sd_res = StructuredData::new(sd_id);

    for (i, c) in sd.char_indices() {
        let is_sd_name = match c as u32 {
            32 | 34 | 61 | 93 => false,
            33 ... 126 => true,
            _ => false
        };
        match (c, esc, is_sd_name, in_name, name.is_some(), in_value) {
            (' ', false, _, false, false, _) => { /* contextless spaces */ }
            (']', false, _, false, false, _) => {
                after_sd = Some(i + 1);
                break;
            }
            (_, false, true, false, false, _) => {
                in_name = true;
                name_start = i;
            }
            (_, _, true, true, false, _) => { /* name */ }
            ('=', false, _, true, _, _) => {
                name = Some(&sd[name_start .. i]);
                in_name = false;
            }
            ('"', false, _, _, true, false) => {
                in_value = true;
                value_start = i + 1;
            }
            ('\\', false, _, _, _, true) => esc = true,
            ('"', false, _, _, _, true) => {
                in_value = false;
                let value = unescape_sd_value(&sd[value_start .. i]);
                let pair = (format!("_{}", name.unwrap()), value);
                sd_res.pairs.push(pair);
                name = None;
            }
            (_, _, _, _, _, true) => esc = false,
            _ => return Err("Format error in the structured data")
        }
    }
    match after_sd {
        None => Err("Missing ] after structured data"),
        Some(offset) => Ok((Some(sd_res), parse_msg(sd, offset)))
    }
}
/*
pub struct Record {
    pub pri: Option<Pri>,
    pub ts: i64,
    pub hostname: String,
    pub appname: Option<String>,
    pub procid: Option<String>,
    pub msgid: Option<String>,
    pub sd: Option<StructuredData>,
    pub msg: Option<String>
}
*/
#[test]
fn test_rfc5424() {
    let msg = r#"<23>1 2015-08-05T15:53:45.637824Z testhostname appname 69 42 [origin@123 software="te\st sc\"ript" swVersion="0.0.1"] test message"#;
    let res = RFC5424.decode(msg).unwrap();
    let pri = res.pri.unwrap();
    assert!(pri.facility == 2);
    assert!(pri.severity == 7);
    assert!(res.ts == 1438790025);
    assert!(res.hostname == "testhostname");
    assert!(res.appname == Some("appname".to_owned()));
    assert!(res.procid == Some("69".to_owned()));
    assert!(res.msgid == Some("42".to_owned()));
    assert!(res.msg == Some("test message".to_owned()));
    let sd = res.sd.unwrap();
    assert!(sd.sd_id == "origin@123");
    let pairs = sd.pairs;
    assert!(pairs.iter().cloned().any(|(k, v)| k == "_software" && v == "te\\st sc\"ript"));
    assert!(pairs.iter().cloned().any(|(k, v)| k == "_swVersion" && v == "0.0.1"));
}
<commit_msg>Tolerate some bogus entries<commit_after>extern crate chrono;

use flowgger::Decoder;
use flowgger::config::Config;
use flowgger::record::{Record, Pri, StructuredData};
use self::chrono::DateTime;

#[derive(Clone)]
pub struct RFC5424;

impl Decoder for RFC5424 {
    fn new(config: &Config) -> RFC5424 {
        let _ = config;
        RFC5424
    }

    fn decode(&self, line: &str) -> Result<Record, &'static str> {
        let (bom, line) = match BOM::parse(line, "<") {
            Ok(bom_line) => bom_line,
            Err(err) => return Err(err)
        };
        let mut parts = line.splitn(7, ' ');
        let pri_version = try!(parse_pri_version(try!(parts.next().ok_or("Missing priority and version"))));
        let ts = try!(parse_ts(try!(parts.next().ok_or("Missing timestamp"))));
        let hostname = try!(parts.next().ok_or("Missing hostname"));
        let appname = try!(parts.next().ok_or("Missing application name"));
        let procid = try!(parts.next().ok_or("Missing process id"));
        let msgid = try!(parts.next().ok_or("Missing message id"));
        let (sd, msg) = try!(parse_data(try!(parts.next().ok_or("Missing message data"))));
        let record = Record {
            pri: Some(pri_version),
            ts: ts,
            hostname: hostname.to_owned(),
            appname: Some(appname.to_owned()),
            procid: Some(procid.to_owned()),
            msgid: Some(msgid.to_owned()),
            sd: sd,
            msg: msg
        };
        Ok(record)
    }
}

impl Pri {
    fn new(encoded: u8) -> Pri {
        Pri {
            facility: encoded >> 3,
            severity: encoded & 7
        }
    }
}

enum BOM {
    NONE,
    UTF8
}

impl BOM {
    fn parse<'a>(line: &'a str, sep: &str) -> Result<(BOM, &'a str), &'static str> {
        if line.starts_with("\u{feff}") {
            Ok((BOM::UTF8, &line[3..]))
        } else if line.starts_with(sep) {
            Ok((BOM::NONE, line))
        } else {
            Err("Unsupported BOM")
        }
    }
}

fn parse_pri_version(line: &str) -> Result<Pri, &'static str> {
    if ! line.starts_with("<") {
        return Err("The priority should be inside brackets")
    }
    let mut parts = line[1..].splitn(2, '>');
    let pri: u8 = try!(try!(parts.next().ok_or("Empty priority")).parse().or(Err("Invalid priority")));
    let version = try!(parts.next().ok_or("Missing version"));
    if version != "1" {
        return Err("Unsupported version");
    }
    Ok(Pri::new(pri))
}

fn rfc3339_to_unix(rfc3339: &str) -> Result<i64, &'static str> {
    match DateTime::parse_from_rfc3339(rfc3339) {
        Ok(date) => Ok(date.timestamp()),
        Err(_) => Err("Unable to parse the date")
    }
}

fn parse_ts(line: &str) -> Result<i64, &'static str> {
    rfc3339_to_unix(line)
}

fn unescape_sd_value(value: &str) -> String {
    let mut res = "".to_owned();
    let mut esc = false;

    for c in value.chars() {
        match (c, esc) {
            ('\\', false) => esc = true,
            (_, false) => res.push(c),
            ('"', true) | ('\\', true) | (']', true) => {
                res.push(c);
                esc = false;
            }
            (_, true) => {
                res.push('\\');
                res.push(c);
                esc = false;
            }
        }
    }
    res
}

fn parse_msg(line: &str, offset: usize) -> Option<String> {
    if offset > line.len() {
        None
    } else {
        match line[offset..].trim() {
            "" => None,
            m @ _ => Some(m.to_owned())
        }
    }
}

fn parse_data(line: &str) -> Result<(Option<StructuredData>, Option<String>), &'static str> {
    match try!(line.chars().next().ok_or("Short message")) {
        '-' => {
            return Ok((None, parse_msg(line, 1)));
        }
        '[' => { }
        _ => return Err("Short message")
    };
    let mut parts = line[1..].splitn(2, ' ');
    let sd_id = try!(parts.next().ok_or("Missing structured data id"));
    let sd = try!(parts.next().ok_or("Missing structured data"));
    let mut in_name = false;
    let mut in_value = false;
    let mut name_start = 0;
    let mut value_start = 0;
    let mut name: Option<&str> = None;
    let mut esc = false;
    let mut after_sd: Option<usize> = None;
    let mut sd_res = StructuredData::new(sd_id);

    for (i, c) in sd.char_indices() {
        let is_sd_name = match c as u32 {
            32 | 34 | 61 | 93 => false,
            33 ... 126 => true,
            _ => false
        };
        match (c, esc, is_sd_name, in_name, name.is_some(), in_value) {
            (' ', false, _, false, false, _) => { /* contextless spaces */ }
            (']', false, _, false, false, _) => {
                after_sd = Some(i + 1);
                break;
            }
            (_, false, true, false, false, _) => {
                in_name = true;
                name_start = i;
            }
            (_, _, true, true, false, _) => { /* name */ }
            ('=', false, _, true, _, _) => {
                name = Some(&sd[name_start .. i]);
                in_name = false;
            }
            ('"', false, _, _, true, false) => {
                in_value = true;
                value_start = i + 1;
            }
            ('\\', false, _, _, _, true) => esc = true,
            ('"', false, _, _, _, true) => {
                in_value = false;
                let value = unescape_sd_value(&sd[value_start .. i]);
                let pair = (format!("_{}", name.unwrap()), value);
                sd_res.pairs.push(pair);
                name = None;
            }
            (_, _, _, _, _, true) => esc = false,
            ('"', false, _, false, false, _)  => { /* tolerate bogus entries with extra " */ },
            _ => return Err("Format error in the structured data")
        }
    }
    match after_sd {
        None => Err("Missing ] after structured data"),
        Some(offset) => Ok((Some(sd_res), parse_msg(sd, offset)))
    }
}
/*
pub struct Record {
    pub pri: Option<Pri>,
    pub ts: i64,
    pub hostname: String,
    pub appname: Option<String>,
    pub procid: Option<String>,
    pub msgid: Option<String>,
    pub sd: Option<StructuredData>,
    pub msg: Option<String>
}
*/
#[test]
fn test_rfc5424() {
    let msg = r#"<23>1 2015-08-05T15:53:45.637824Z testhostname appname 69 42 [origin@123 software="te\st sc\"ript" swVersion="0.0.1"] test message"#;
    let res = RFC5424.decode(msg).unwrap();
    let pri = res.pri.unwrap();
    assert!(pri.facility == 2);
    assert!(pri.severity == 7);
    assert!(res.ts == 1438790025);
    assert!(res.hostname == "testhostname");
    assert!(res.appname == Some("appname".to_owned()));
    assert!(res.procid == Some("69".to_owned()));
    assert!(res.msgid == Some("42".to_owned()));
    assert!(res.msg == Some("test message".to_owned()));
    let sd = res.sd.unwrap();
    assert!(sd.sd_id == "origin@123");
    let pairs = sd.pairs;
    assert!(pairs.iter().cloned().any(|(k, v)| k == "_software" && v == "te\\st sc\"ript"));
    assert!(pairs.iter().cloned().any(|(k, v)| k == "_swVersion" && v == "0.0.1"));
}
<|endoftext|>


<commit_before>use std::path::*;
use std::io::{Result, Write};

use env::Env;
use file_saver::*;
use library;
use nameutil::*;
use super::functions;
use super::statics;
use super::super::general;

pub fn generate(env: &Env) {
    println!("generating sys for {}", env.config.library_name);

    let path =  PathBuf::from(&env.config.target_path)
        .join(file_name_sys(&env.config.library_name, "lib"));
    println!("Generating file {:?}", path);

    save_to_file(path, &mut |w| generate_lib(w, env));
}

fn generate_lib<W: Write>(w: &mut W, env: &Env) -> Result<()>{
    try!(general::start_comments(w, &env.config));
    try!(statics::begin(w));

    let ns_id = library::MAIN_NAMESPACE;
    let classes = prepare_classes(env, ns_id);
    let interfaces = prepare_interfaces(env, ns_id);

    try!(generate_classes_structs(w, &classes));
    try!(generate_interfaces_structs(w, &interfaces));

    try!(statics::before_func(w));

    try!(writeln!(w, ""));
    try!(writeln!(w, "extern \"C\" {{"));
    try!(functions::generate_classes_funcs(w, env, &classes));

    //TODO: other functions
    try!(writeln!(w, "\n}}"));

    Ok(())
}

fn prepare_classes(env: &Env, ns_id: u16) -> Vec<&library::Class> {
    let ns = env.library.namespace(ns_id);
    let mut vec: Vec<&library::Class> = Vec::with_capacity(ns.types.len());
    for id in 0..ns.types.len() {
        let tid = library::TypeId { ns_id: ns_id, id: id as u32 };
        if let &library::Type::Class(ref klass) = env.library.type_(tid) {
            vec.push(klass);
        }
    }
    vec.sort_by(|ref klass1, ref klass2| klass1.glib_type_name.cmp(&klass2.glib_type_name));
    vec
}

fn generate_classes_structs<W: Write>(w: &mut W, classes: &Vec<&library::Class>) -> Result<()> {
    try!(writeln!(w, ""));
    for klass in classes {
        try!(writeln!(w, "#[repr(C)]\npub struct {};", klass.glib_type_name));
    }

    Ok(())
}

fn prepare_interfaces(env: &Env, ns_id: u16) -> Vec<&library::Interface> {
    let ns = env.library.namespace(ns_id);
    let mut vec: Vec<&library::Interface> = Vec::with_capacity(ns.types.len());
    for id in 0..ns.types.len() {
        let tid = library::TypeId { ns_id: ns_id, id: id as u32 };
        if let &library::Type::Interface(ref interface) = env.library.type_(tid) {
            vec.push(interface);
        }
    }
    vec.sort_by(|ref interface1, ref interface2| interface1.glib_type_name.cmp(&interface2.glib_type_name));
    vec
}

fn generate_interfaces_structs<W: Write>(w: &mut W, interfaces: &Vec<&library::Interface>) -> Result<()> {
    try!(writeln!(w, ""));
    for interface in interfaces {
        try!(writeln!(w, "#[repr(C)]\npub struct {};", interface.glib_type_name));
    }

    Ok(())
}
<commit_msg>Refactoring types iteration<commit_after>use std::path::*;
use std::io::{Result, Write};

use env::Env;
use file_saver::*;
use library;
use nameutil::*;
use super::functions;
use super::statics;
use super::super::general;

pub fn generate(env: &Env) {
    println!("generating sys for {}", env.config.library_name);

    let path =  PathBuf::from(&env.config.target_path)
        .join(file_name_sys(&env.config.library_name, "lib"));
    println!("Generating file {:?}", path);

    save_to_file(path, &mut |w| generate_lib(w, env));
}

fn generate_lib<W: Write>(w: &mut W, env: &Env) -> Result<()>{
    try!(general::start_comments(w, &env.config));
    try!(statics::begin(w));

    let ns = env.library.namespace(library::MAIN_NAMESPACE);
    let classes = prepare_classes(ns);

    try!(generate_classes_structs(w, &classes));
    try!(generate_interfaces_structs(w, &prepare_interfaces(ns)));

    try!(statics::before_func(w));

    try!(writeln!(w, ""));
    try!(writeln!(w, "extern \"C\" {{"));
    try!(functions::generate_classes_funcs(w, env, &classes));

    //TODO: other functions
    try!(writeln!(w, "\n}}"));

    Ok(())
}

fn prepare_classes(ns: &library::Namespace) -> Vec<&library::Class> {
    let mut vec: Vec<&library::Class> = Vec::with_capacity(ns.types.len());
    for typ in &ns.types {
        if let &Some(library::Type::Class(ref klass)) = typ {
            vec.push(klass);
        }
    }
    vec.sort_by(|ref klass1, ref klass2| klass1.glib_type_name.cmp(&klass2.glib_type_name));
    vec
}

fn generate_classes_structs<W: Write>(w: &mut W, classes: &Vec<&library::Class>) -> Result<()> {
    try!(writeln!(w, ""));
    for klass in classes {
        try!(writeln!(w, "#[repr(C)]\npub struct {};", klass.glib_type_name));
    }

    Ok(())
}

fn prepare_interfaces(ns: &library::Namespace) -> Vec<&library::Interface> {
    let mut vec: Vec<&library::Interface> = Vec::with_capacity(ns.types.len());
    for typ in &ns.types {
        if let &Some(library::Type::Interface(ref interface)) = typ {
            vec.push(interface);
        }
    }
    vec.sort_by(|ref interface1, ref interface2| interface1.glib_type_name.cmp(&interface2.glib_type_name));
    vec
}

fn generate_interfaces_structs<W: Write>(w: &mut W, interfaces: &Vec<&library::Interface>) -> Result<()> {
    try!(writeln!(w, ""));
    for interface in interfaces {
        try!(writeln!(w, "#[repr(C)]\npub struct {};", interface.glib_type_name));
    }

    Ok(())
}
<|endoftext|>


<commit_before>use cgmath::Point2;
use gfx::{Factory, format::Rgba8, handle::ShaderResourceView, Resources, texture::{AaMode, Kind, Mipmap, Size}};
use gfx_app::ColorFormat;
use hud::font::draw_text;
use image;
use rusttype::Font;
use std::collections::HashMap;
use std::io::Cursor;

#[derive(Debug, Clone)]
pub struct Texture<R> where R: Resources {
  pub raw: ShaderResourceView<R, [f32; 4]>,
  pub size: Point2<i32>,
}

impl<R> Texture<R> where R: Resources {
  pub fn new(raw: ShaderResourceView<R, [f32; 4]>, size: Option<Point2<i32>>) -> Texture<R> {
    Texture {
      raw,
      size: size.map_or(Point2::new(1, 1), |e| e),
    }
  }
}

pub fn load_texture<R, F>(factory: &mut F, data: &[u8]) -> ShaderResourceView<R, [f32; 4]> where R: Resources, F: Factory<R> {
  let img = image::load(Cursor::new(data), image::PNG).unwrap().to_rgba();
  let (width, height) = img.dimensions();
  let kind = Kind::D2(width as Size, height as Size, AaMode::Single);
  match factory.create_texture_immutable_u8::<Rgba8>(kind, Mipmap::Provided, &[&img]) {
    Ok(val) => val.1,
    Err(e) => panic!("Couldn't load texture {:?}", e)
  }
}

pub fn load_raw_texture<R, F>(factory: &mut F, data: &[u8], size: Point2<i32>) -> ShaderResourceView<R, [f32; 4]>
                              where R: Resources, F: Factory<R> {
  let kind = Kind::D2(size.x as Size, size.y as Size, AaMode::Single);
  let mipmap = Mipmap::Provided;
  match factory
    .create_texture_immutable_u8::<ColorFormat>(kind, mipmap, &[data]) {
    Ok(val) => val.1,
    Err(e) => panic!("Couldn't load texture {:?}", e)
  }
}

pub fn text_texture<'a, R, F>(factory: &mut F,
                              font: &Font,
                              texts: &[&str],
                              texture_cache: &'a mut HashMap<String, Texture<R>>) -> &'a mut HashMap<String, Texture<R>>
                              where R: Resources, F: Factory<R> {
  let text_texture_height = 100.0;
  texts.iter().for_each(|text| {
    let (texture_size, texture_data) = draw_text(&font, text_texture_height, text);
    let texture = load_raw_texture(factory, &texture_data.as_slice(), texture_size);
    let texture_element = Texture::new(texture, None);
    texture_cache.insert(text.to_string(), texture_element.clone());
  });
  texture_cache
}
<commit_msg>Fix "load_raw_texture" error message<commit_after>use cgmath::Point2;
use gfx::{Factory, format::Rgba8, handle::ShaderResourceView, Resources, texture::{AaMode, Kind, Mipmap, Size}};
use gfx_app::ColorFormat;
use hud::font::draw_text;
use image;
use rusttype::Font;
use std::collections::HashMap;
use std::io::Cursor;

#[derive(Debug, Clone)]
pub struct Texture<R> where R: Resources {
  pub raw: ShaderResourceView<R, [f32; 4]>,
  pub size: Point2<i32>,
}

impl<R> Texture<R> where R: Resources {
  pub fn new(raw: ShaderResourceView<R, [f32; 4]>, size: Option<Point2<i32>>) -> Texture<R> {
    Texture {
      raw,
      size: size.map_or(Point2::new(1, 1), |e| e),
    }
  }
}

pub fn load_texture<R, F>(factory: &mut F, data: &[u8]) -> ShaderResourceView<R, [f32; 4]> where R: Resources, F: Factory<R> {
  let img = image::load(Cursor::new(data), image::PNG).unwrap().to_rgba();
  let (width, height) = img.dimensions();
  let kind = Kind::D2(width as Size, height as Size, AaMode::Single);
  match factory.create_texture_immutable_u8::<Rgba8>(kind, Mipmap::Provided, &[&img]) {
    Ok(val) => val.1,
    Err(e) => panic!("Couldn't load texture {:?}", e)
  }
}

pub fn load_raw_texture<R, F>(factory: &mut F, data: &[u8], size: Point2<i32>) -> ShaderResourceView<R, [f32; 4]>
                              where R: Resources, F: Factory<R> {
  let kind = Kind::D2(size.x as Size, size.y as Size, AaMode::Single);
  let mipmap = Mipmap::Provided;
  match factory
    .create_texture_immutable_u8::<ColorFormat>(kind, mipmap, &[data]) {
    Ok(val) => val.1,
    Err(e) => panic!("Couldn't load raw texture {:?}", e)
  }
}

pub fn text_texture<'a, R, F>(factory: &mut F,
                              font: &Font,
                              texts: &[&str],
                              texture_cache: &'a mut HashMap<String, Texture<R>>) -> &'a mut HashMap<String, Texture<R>>
                              where R: Resources, F: Factory<R> {
  let text_texture_height = 100.0;
  texts.iter().for_each(|text| {
    let (texture_size, texture_data) = draw_text(&font, text_texture_height, text);
    let texture = load_raw_texture(factory, &texture_data.as_slice(), texture_size);
    let texture_element = Texture::new(texture, None);
    texture_cache.insert(text.to_string(), texture_element.clone());
  });
  texture_cache
}
<|endoftext|>


<commit_before>extern crate piston_window;

use piston_window::Transformed;

use piston_window as pw;

fn main() {
    let window: pw::PistonWindow = pw::WindowSettings::new("rrthozopsi", [600, 600])
        .exit_on_esc(true)
        .build()
        .unwrap();

	let mut rotation: f64 = 0.0;
    for w in window {
		match w.event {
			Some(pw::Event::Update(pw::UpdateArgs { dt })) => { rotation += 3.0 * dt; }
			_ => {}
		}

		w.draw_2d(|context, graphics| {
			pw::clear([0.0, 0.0, 0.0, 1.0], graphics);

			let red = [1.0, 0.0, 0.0, 1.0];
			let square = pw::rectangle::square(0.0, 0.0, 100.0);
			let center = context.transform.trans(300.0, 300.0);
			pw::rectangle(red, square, center.rot_rad(rotation).trans(-50.0, -50.0), graphics);
		});
    }
}
<commit_msg>Game struct<commit_after>extern crate piston_window;

use piston_window::Transformed;

use piston_window as pw;

struct Game {
    rotation: f64
}

impl Game {
    fn new() -> Game {
        Game { rotation : 0.0 }
    }

    fn on_update(&mut self, args: pw::UpdateArgs) {
        self.rotation += 3.0 * args.dt;
    }

    fn on_draw(&mut self, args: pw::RenderArgs, window: pw::PistonWindow) {
        window.draw_2d(|context, graphics| {
            pw::clear([0.0, 0.0, 0.0, 1.0], graphics);

            let red = [1.0, 0.0, 0.0, 1.0];
            let square = pw::rectangle::square(0.0, 0.0, 100.0);
            let center = context.transform.trans((args.width / 2) as f64, (args.height / 2) as f64);
            pw::rectangle(red, square, center.rot_rad(self.rotation).trans(-50.0, -50.0), graphics);
        });
    }
}

fn main() {
    let window: pw::PistonWindow = pw::WindowSettings::new("rrthozopsi", [600, 600])
        .exit_on_esc(true)
        .build()
        .unwrap();

	let mut game = Game::new();

    for w in window {
		match w.event {
			Some(pw::Event::Update(args)) => { game.on_update(args); }
			Some(pw::Event::Render(args)) => { game.on_draw(args, w); }
			_ => {}
		}
    }
}
<|endoftext|>


<commit_before>// rsbegin.o and rsend.o are the so called "compiler runtime startup objects".
// They contain code needed to correctly initialize the compiler runtime.
//
// When an executable or dylib image is linked, all user code and libraries are
// "sandwiched" between these two object files, so code or data from rsbegin.o
// become first in the respective sections of the image, whereas code and data
// from rsend.o become the last ones. This effect can be used to place symbols
// at the beginning or at the end of a section, as well as to insert any required
// headers or footers.
//
// Note that the actual module entry point is located in the C runtime startup
// object (usually called `crtX.o), which then invokes initialization callbacks
// of other runtime components (registered via yet another special image section).

#![feature(no_core, lang_items, optin_builtin_traits)]
#![crate_type = "rlib"]
#![no_core]
#![allow(non_camel_case_types)]

#[lang = "sized"]
trait Sized {}
#[lang = "sync"]
auto trait Sync {}
#[lang = "copy"]
trait Copy {}
#[lang = "freeze"]
auto trait Freeze {}

#[lang = "drop_in_place"]
#[inline]
#[allow(unconditional_recursion)]
pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
    drop_in_place(to_drop);
}

#[cfg(all(target_os = "windows", target_arch = "x86", target_env = "gnu"))]
pub mod eh_frames {
    #[no_mangle]
    #[link_section = ".eh_frame"]
    // Marks beginning of the stack frame unwind info section
    pub static __EH_FRAME_BEGIN__: [u8; 0] = [];

    // Scratch space for unwinder's internal book-keeping.
    // This is defined as `struct object` in $GCC/libgcc/unwind-dw2-fde.h.
    static mut OBJ: [isize; 6] = [0; 6];

    macro_rules! impl_copy {
        ($($t:ty)*) => {
            $(
                impl ::Copy for $t {}
            )*
        }
    }

    impl_copy! {
        usize u8 u16 u32 u64 u128
        isize i8 i16 i32 i64 i128
        f32 f64
        bool char
    }

    // Unwind info registration/deregistration routines.
    // See the docs of `unwind` module in libstd.
    extern "C" {
        fn rust_eh_register_frames(eh_frame_begin: *const u8, object: *mut u8);
        fn rust_eh_unregister_frames(eh_frame_begin: *const u8, object: *mut u8);
    }

    unsafe fn init() {
        // register unwind info on module startup
        rust_eh_register_frames(&__EH_FRAME_BEGIN__ as *const u8, &mut OBJ as *mut _ as *mut u8);
    }

    unsafe fn uninit() {
        // unregister on shutdown
        rust_eh_unregister_frames(&__EH_FRAME_BEGIN__ as *const u8, &mut OBJ as *mut _ as *mut u8);
    }

    // MSVC-specific init/uninit routine registration
    pub mod ms_init {
        // .CRT$X?? sections are roughly analogous to ELF's .init_array and .fini_array,
        // except that they exploit the fact that linker will sort them alphabitically,
        // so e.g., sections with names between .CRT$XIA and .CRT$XIZ are guaranteed to be
        // placed between those two, without requiring any ordering of objects on the linker
        // command line.
        // Note that ordering of same-named sections from different objects is not guaranteed.
        // Since .CRT$XIA contains init array's header symbol, which must always come first,
        // we place our initialization callback into .CRT$XIB.

        #[link_section = ".CRT$XIB"] // .CRT$XI? : C initialization callbacks
        pub static P_INIT: unsafe fn() = super::init;

        #[link_section = ".CRT$XTY"] // .CRT$XT? : C termination callbacks
        pub static P_UNINIT: unsafe fn() = super::uninit;
    }
}
<commit_msg>Fix MinGW termination callbacks not being invoked<commit_after>// rsbegin.o and rsend.o are the so called "compiler runtime startup objects".
// They contain code needed to correctly initialize the compiler runtime.
//
// When an executable or dylib image is linked, all user code and libraries are
// "sandwiched" between these two object files, so code or data from rsbegin.o
// become first in the respective sections of the image, whereas code and data
// from rsend.o become the last ones. This effect can be used to place symbols
// at the beginning or at the end of a section, as well as to insert any required
// headers or footers.
//
// Note that the actual module entry point is located in the C runtime startup
// object (usually called `crtX.o), which then invokes initialization callbacks
// of other runtime components (registered via yet another special image section).

#![feature(no_core, lang_items, optin_builtin_traits)]
#![crate_type = "rlib"]
#![no_core]
#![allow(non_camel_case_types)]

#[lang = "sized"]
trait Sized {}
#[lang = "sync"]
auto trait Sync {}
#[lang = "copy"]
trait Copy {}
#[lang = "freeze"]
auto trait Freeze {}

#[lang = "drop_in_place"]
#[inline]
#[allow(unconditional_recursion)]
pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
    drop_in_place(to_drop);
}

#[cfg(all(target_os = "windows", target_arch = "x86", target_env = "gnu"))]
pub mod eh_frames {
    #[no_mangle]
    #[link_section = ".eh_frame"]
    // Marks beginning of the stack frame unwind info section
    pub static __EH_FRAME_BEGIN__: [u8; 0] = [];

    // Scratch space for unwinder's internal book-keeping.
    // This is defined as `struct object` in $GCC/libgcc/unwind-dw2-fde.h.
    static mut OBJ: [isize; 6] = [0; 6];

    macro_rules! impl_copy {
        ($($t:ty)*) => {
            $(
                impl ::Copy for $t {}
            )*
        }
    }

    impl_copy! {
        usize u8 u16 u32 u64 u128
        isize i8 i16 i32 i64 i128
        f32 f64
        bool char
    }

    // Unwind info registration/deregistration routines.
    // See the docs of libpanic_unwind.
    extern "C" {
        fn rust_eh_register_frames(eh_frame_begin: *const u8, object: *mut u8);
        fn rust_eh_unregister_frames(eh_frame_begin: *const u8, object: *mut u8);
    }

    unsafe extern "C" fn init() {
        // register unwind info on module startup
        rust_eh_register_frames(&__EH_FRAME_BEGIN__ as *const u8, &mut OBJ as *mut _ as *mut u8);
    }

    unsafe extern "C" fn uninit() {
        // unregister on shutdown
        rust_eh_unregister_frames(&__EH_FRAME_BEGIN__ as *const u8, &mut OBJ as *mut _ as *mut u8);
    }

    // MinGW-specific init/uninit routine registration
    pub mod mingw_init {
        // MinGW's startup objects (crt0.o / dllcrt0.o) will invoke global constructors in the
        // .ctors and .dtors sections on startup and exit. In the case of DLLs, this is done when
        // the DLL is loaded and unloaded.
        //
        // The linker will sort the sections, which ensures that our callbacks are located at the
        // end of the list. Since constructors are run in reverse order, this ensures that our
        // callbacks are the first and last ones executed.

        #[link_section = ".ctors.65535"] // .ctors.* : C initialization callbacks
        pub static P_INIT: unsafe extern "C" fn() = super::init;

        #[link_section = ".dtors.65535"] // .dtors.* : C termination callbacks
        pub static P_UNINIT: unsafe extern "C" fn() = super::uninit;
    }
}
<|endoftext|>


<commit_before>#[doc = "Generic pass for performing an operation on all descriptions"];

export mk_pass;

fn mk_pass(op: fn~(str) -> str) -> pass {
    fn~(srv: astsrv::srv, doc: doc::cratedoc) -> doc::cratedoc {
        run(srv, doc, op)
    }
}

type op = fn~(str) -> str;

fn run(
    _srv: astsrv::srv,
    doc: doc::cratedoc,
    op: op
) -> doc::cratedoc {
    let fold = fold::fold({
        fold_mod: fold_mod,
        fold_const: fold_const,
        fold_fn: fold_fn
        with *fold::default_seq_fold(op)
    });
    fold.fold_crate(fold, doc)
}

fn maybe_apply_op(op: op, s: option<str>) -> option<str> {
    option::map(s) {|s| op(s) }
}

fn fold_mod(fold: fold::fold<op>, doc: doc::moddoc) -> doc::moddoc {
    let doc = fold::default_seq_fold_mod(fold, doc);

    ~{
        brief: maybe_apply_op(fold.ctxt, doc.brief),
        desc: maybe_apply_op(fold.ctxt, doc.desc)
        with *doc
    }
}

fn fold_const(fold: fold::fold<op>, doc: doc::constdoc) -> doc::constdoc {
    let doc = fold::default_seq_fold_const(fold, doc);

    ~{
        brief: maybe_apply_op(fold.ctxt, doc.brief),
        desc: maybe_apply_op(fold.ctxt, doc.desc)
        with *doc
    }
}

fn fold_fn(fold: fold::fold<op>, doc: doc::fndoc) -> doc::fndoc {
    let doc = fold::default_seq_fold_fn(fold, doc);

    ~{
        brief: maybe_apply_op(fold.ctxt, doc.brief),
        desc: maybe_apply_op(fold.ctxt, doc.desc),
        args: vec::map(doc.args) {|doc|
            ~{
                desc: maybe_apply_op(fold.ctxt, doc.desc)
                with *doc
            }
        },
        return: {
            desc: maybe_apply_op(fold.ctxt, doc.return.desc)
            with doc.return
        },
        failure: maybe_apply_op(fold.ctxt, doc.failure)
        with *doc
    }
}
<commit_msg>rustdoc: Apply general string ops to enum docs<commit_after>#[doc = "Generic pass for performing an operation on all descriptions"];

export mk_pass;

fn mk_pass(op: fn~(str) -> str) -> pass {
    fn~(srv: astsrv::srv, doc: doc::cratedoc) -> doc::cratedoc {
        run(srv, doc, op)
    }
}

type op = fn~(str) -> str;

fn run(
    _srv: astsrv::srv,
    doc: doc::cratedoc,
    op: op
) -> doc::cratedoc {
    let fold = fold::fold({
        fold_mod: fold_mod,
        fold_const: fold_const,
        fold_fn: fold_fn,
        fold_enum: fold_enum
        with *fold::default_seq_fold(op)
    });
    fold.fold_crate(fold, doc)
}

fn maybe_apply_op(op: op, s: option<str>) -> option<str> {
    option::map(s) {|s| op(s) }
}

fn fold_mod(fold: fold::fold<op>, doc: doc::moddoc) -> doc::moddoc {
    let doc = fold::default_seq_fold_mod(fold, doc);

    ~{
        brief: maybe_apply_op(fold.ctxt, doc.brief),
        desc: maybe_apply_op(fold.ctxt, doc.desc)
        with *doc
    }
}

fn fold_const(fold: fold::fold<op>, doc: doc::constdoc) -> doc::constdoc {
    let doc = fold::default_seq_fold_const(fold, doc);

    ~{
        brief: maybe_apply_op(fold.ctxt, doc.brief),
        desc: maybe_apply_op(fold.ctxt, doc.desc)
        with *doc
    }
}

fn fold_fn(fold: fold::fold<op>, doc: doc::fndoc) -> doc::fndoc {
    let doc = fold::default_seq_fold_fn(fold, doc);

    ~{
        brief: maybe_apply_op(fold.ctxt, doc.brief),
        desc: maybe_apply_op(fold.ctxt, doc.desc),
        args: vec::map(doc.args) {|doc|
            ~{
                desc: maybe_apply_op(fold.ctxt, doc.desc)
                with *doc
            }
        },
        return: {
            desc: maybe_apply_op(fold.ctxt, doc.return.desc)
            with doc.return
        },
        failure: maybe_apply_op(fold.ctxt, doc.failure)
        with *doc
    }
}

fn fold_enum(fold: fold::fold<op>, doc: doc::enumdoc) -> doc::enumdoc {
    ~{
        brief: maybe_apply_op(fold.ctxt, doc.brief),
        desc: maybe_apply_op(fold.ctxt, doc.desc),
        variants: vec::map(doc.variants) {|variant|
            ~{
                desc: maybe_apply_op(fold.ctxt, variant.desc)
                with *variant
            }
        }
        with *doc
    }
}

#[test]
fn should_execute_op_on_enum_brief() {
    let source = "#[doc(brief = \" a \")] enum a { b }";
    let srv = astsrv::mk_srv_from_str(source);
    let doc = extract::from_srv(srv, "");
    let doc = attr_pass::mk_pass()(srv, doc);
    let doc = mk_pass(str::trim)(srv, doc);
    assert doc.topmod.enums[0].brief == some("a");
}

#[test]
fn should_execute_op_on_enum_desc() {
    let source = "#[doc(desc = \" a \")] enum a { b }";
    let srv = astsrv::mk_srv_from_str(source);
    let doc = extract::from_srv(srv, "");
    let doc = attr_pass::mk_pass()(srv, doc);
    let doc = mk_pass(str::trim)(srv, doc);
    assert doc.topmod.enums[0].desc == some("a");
}

#[test]
fn should_execute_op_on_variant_desc() {
    let source = "enum a { #[doc = \" a \"] b }";
    let srv = astsrv::mk_srv_from_str(source);
    let doc = extract::from_srv(srv, "");
    let doc = attr_pass::mk_pass()(srv, doc);
    let doc = mk_pass(str::trim)(srv, doc);
    assert doc.topmod.enums[0].variants[0].desc == some("a");
}<|endoftext|>


<commit_before>use object::read::archive::ArchiveFile;
use object::read::macho::{FatArch, FatHeader};
use object::{Object, ObjectComdat, ObjectSection, ObjectSymbol};
use std::{env, fs, process};

fn main() {
    let arg_len = env::args().len();
    if arg_len <= 1 {
        eprintln!("Usage: {} <file> ...", env::args().next().unwrap());
        process::exit(1);
    }

    for file_path in env::args().skip(1) {
        if arg_len > 2 {
            println!();
            println!("{}:", file_path);
        }

        let file = match fs::File::open(&file_path) {
            Ok(file) => file,
            Err(err) => {
                println!("Failed to open file '{}': {}", file_path, err,);
                continue;
            }
        };
        let file = match unsafe { memmap::Mmap::map(&file) } {
            Ok(mmap) => mmap,
            Err(err) => {
                println!("Failed to map file '{}': {}", file_path, err,);
                continue;
            }
        };

        if let Ok(archive) = ArchiveFile::parse(&*file) {
            println!("Format: Archive (kind: {:?})", archive.kind());
            for member in archive.members() {
                if let Ok(member) = member {
                    println!();
                    println!("{}:", String::from_utf8_lossy(member.name()));
                    dump_object(member.data());
                }
            }
        } else if let Ok(arches) = FatHeader::parse_arch32(&*file) {
            println!("Format: Mach-O Fat 32");
            for arch in arches {
                println!();
                println!("Fat Arch: {:?}", arch.architecture());
                if let Ok(data) = arch.data(&*file) {
                    dump_object(data);
                }
            }
        } else if let Ok(arches) = FatHeader::parse_arch64(&*file) {
            println!("Format: Mach-O Fat 64");
            for arch in arches {
                println!();
                println!("Fat Arch: {:?}", arch.architecture());
                if let Ok(data) = arch.data(&*file) {
                    dump_object(data);
                }
            }
        } else {
            dump_object(&*file);
        }
    }
}

fn dump_object(data: &[u8]) {
    let file = match object::File::parse(data) {
        Ok(file) => file,
        Err(err) => {
            println!("Failed to parse file: {}", err);
            return;
        }
    };
    println!(
        "Format: {:?} {:?}-endian {}-bit",
        file.format(),
        file.endianness(),
        if file.is_64() { "64" } else { "32" }
    );
    println!("Architecture: {:?}", file.architecture());
    match file.mach_uuid() {
        Ok(Some(uuid)) => println!("Mach UUID: {:x?}", uuid),
        Ok(None) => {}
        Err(e) => println!("Failed to parse Mach UUID: {}", e),
    }
    match file.build_id() {
        Ok(Some(build_id)) => println!("Build ID: {:x?}", build_id),
        Ok(None) => {}
        Err(e) => println!("Failed to parse build ID: {}", e),
    }
    match file.gnu_debuglink() {
        Ok(Some((filename, crc))) => println!(
            "GNU debug link: {} CRC: {:08x}",
            String::from_utf8_lossy(filename),
            crc,
        ),
        Ok(None) => {}
        Err(e) => println!("Failed to parse GNU debug link: {}", e),
    }

    for segment in file.segments() {
        println!("{:?}", segment);
    }

    for section in file.sections() {
        println!("{}: {:?}", section.index().0, section);
    }

    for comdat in file.comdats() {
        print!("{:?} Sections:", comdat);
        for section in comdat.sections() {
            print!(" {}", section.0);
        }
        println!();
    }

    for symbol in file.symbols() {
        println!("{}: {:?}", symbol.index().0, symbol);
    }

    for section in file.sections() {
        if section.relocations().next().is_some() {
            println!(
                "\n{} relocations",
                section.name().unwrap_or("<invalid name>")
            );
            for relocation in section.relocations() {
                println!("{:?}", relocation);
            }
        }
    }
}
<commit_msg>objdump: print ELF flags<commit_after>use object::read::archive::ArchiveFile;
use object::read::macho::{FatArch, FatHeader};
use object::{Object, ObjectComdat, ObjectSection, ObjectSymbol};
use std::{env, fs, process};

fn main() {
    let arg_len = env::args().len();
    if arg_len <= 1 {
        eprintln!("Usage: {} <file> ...", env::args().next().unwrap());
        process::exit(1);
    }

    for file_path in env::args().skip(1) {
        if arg_len > 2 {
            println!();
            println!("{}:", file_path);
        }

        let file = match fs::File::open(&file_path) {
            Ok(file) => file,
            Err(err) => {
                println!("Failed to open file '{}': {}", file_path, err,);
                continue;
            }
        };
        let file = match unsafe { memmap::Mmap::map(&file) } {
            Ok(mmap) => mmap,
            Err(err) => {
                println!("Failed to map file '{}': {}", file_path, err,);
                continue;
            }
        };

        if let Ok(archive) = ArchiveFile::parse(&*file) {
            println!("Format: Archive (kind: {:?})", archive.kind());
            for member in archive.members() {
                if let Ok(member) = member {
                    println!();
                    println!("{}:", String::from_utf8_lossy(member.name()));
                    dump_object(member.data());
                }
            }
        } else if let Ok(arches) = FatHeader::parse_arch32(&*file) {
            println!("Format: Mach-O Fat 32");
            for arch in arches {
                println!();
                println!("Fat Arch: {:?}", arch.architecture());
                if let Ok(data) = arch.data(&*file) {
                    dump_object(data);
                }
            }
        } else if let Ok(arches) = FatHeader::parse_arch64(&*file) {
            println!("Format: Mach-O Fat 64");
            for arch in arches {
                println!();
                println!("Fat Arch: {:?}", arch.architecture());
                if let Ok(data) = arch.data(&*file) {
                    dump_object(data);
                }
            }
        } else {
            dump_object(&*file);
        }
    }
}

fn dump_object(data: &[u8]) {
    let file = match object::File::parse(data) {
        Ok(file) => file,
        Err(err) => {
            println!("Failed to parse file: {}", err);
            return;
        }
    };
    println!(
        "Format: {:?} {:?}-endian {}-bit",
        file.format(),
        file.endianness(),
        if file.is_64() { "64" } else { "32" }
    );
    println!("Architecture: {:?}", file.architecture());
    println!("Flags: {:?}", file.flags());

    match file.mach_uuid() {
        Ok(Some(uuid)) => println!("Mach UUID: {:x?}", uuid),
        Ok(None) => {}
        Err(e) => println!("Failed to parse Mach UUID: {}", e),
    }
    match file.build_id() {
        Ok(Some(build_id)) => println!("Build ID: {:x?}", build_id),
        Ok(None) => {}
        Err(e) => println!("Failed to parse build ID: {}", e),
    }
    match file.gnu_debuglink() {
        Ok(Some((filename, crc))) => println!(
            "GNU debug link: {} CRC: {:08x}",
            String::from_utf8_lossy(filename),
            crc,
        ),
        Ok(None) => {}
        Err(e) => println!("Failed to parse GNU debug link: {}", e),
    }

    for segment in file.segments() {
        println!("{:?}", segment);
    }

    for section in file.sections() {
        println!("{}: {:?}", section.index().0, section);
    }

    for comdat in file.comdats() {
        print!("{:?} Sections:", comdat);
        for section in comdat.sections() {
            print!(" {}", section.0);
        }
        println!();
    }

    for symbol in file.symbols() {
        println!("{}: {:?}", symbol.index().0, symbol);
    }

    for section in file.sections() {
        if section.relocations().next().is_some() {
            println!(
                "\n{} relocations",
                section.name().unwrap_or("<invalid name>")
            );
            for relocation in section.relocations() {
                println!("{:?}", relocation);
            }
        }
    }
}
<|endoftext|>


<commit_before>//! Loop movement balance analysis.
//!
//! This analysis determines, for the body of a loop, whether its net movement is an exact
//! amount, an unknown amount in a given direction, or unknown altogether. This is used by the
//! bound checking analysis when it encounters loops.

use std::collections::HashMap;
use peephole::{Statement, Program};

/// The body of a loop is a boxed slice of `Statement`s.
pub type LoopBody = Box<[Statement]>;

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
/// The net movement of a loop.
pub enum LoopBalance {
    /// The exact movement of one iteration.
    Exact(isize),
    /// May move right but not left.
    RightOnly,
    /// May move left but not right.
    LeftOnly,
    /// Net movement may be either direction.
    Unknown,
}

/// An index to a loop.
///
/// This is represented as the address of the first instruction of the loop.
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
struct LoopIndex(usize);

/// The computed net movement for each loop.
#[derive(Debug)]
pub struct LoopBalanceMap(HashMap<LoopIndex, LoopBalance>);

impl LoopBalance {
    /// Is the loop body exactly balanced between right and left?
    pub fn is_balanced(self) -> bool {
        self == LoopBalance::Exact(0)
    }

    /// Does the loop move net right (if at all)?
    pub fn is_right_only(self) -> bool {
        use self::LoopBalance::*;

        match self {
            Exact(disp) => disp >= 0,
            RightOnly   => true,
            LeftOnly    => false,
            Unknown     => false,
        }
    }

    /// Does the loop move net left (if at all)?
    pub fn is_left_only(self) -> bool {
        use self::LoopBalance::*;

        match self {
            Exact(disp) => disp <= 0,
            LeftOnly    => true,
            RightOnly   => false,
            Unknown     => false,
        }
    }
}

impl LoopIndex {
    /// Gets the loop index from a boxed loop.
    fn from_loop_body(body: &LoopBody) -> Self {
        LoopIndex(body.as_ptr() as usize)
    }
}

impl LoopBalanceMap {
    /// Initializes the map for the given program.
    pub fn new(program: &Program) -> Self {
        let mut result = LoopBalanceMap(HashMap::new());

        for statement in program {
            match *statement {
                Statement::Instr(_) => (),
                Statement::Loop(ref body) => {
                    result.analyze_loop(body);
                }
            }
        }

        result
    }

    /// Gets the balance of the given loop body.
    pub fn get(&self, body: &LoopBody) -> LoopBalance {
        *self.0.get(&LoopIndex::from_loop_body(body)).unwrap_or(&LoopBalance::Unknown)
    }

    /// Performs the analysis for the given loop body and any sub-loops.
    ///
    /// Stores the result of the analysis in `self`.
    fn analyze_loop(&mut self, body: &LoopBody) -> LoopBalance {
        use peephole::Statement::*;
        use common::Instruction::*;
        use self::LoopBalance::*;

        let mut net = Exact(0);

        for statement in &**body {
            match *statement {
                Instr(Right(count)) => net = match net {
                    Exact(disp) => Exact(disp + count as isize),
                    RightOnly   => RightOnly,
                    _           => Unknown,
                },

                Instr(Left(count)) => net = match net {
                    Exact(disp) => Exact(disp - count as isize),
                    LeftOnly    => LeftOnly,
                    _           => Unknown,
                },

                Instr(Add(_)) | Instr(In) | Instr(Out) => (),

                Instr(JumpZero(_)) | Instr(JumpNotZero(_)) =>
                    panic!("unexpected jump instruction"),

                Instr(SetZero) | Instr(OffsetAddRight(_)) | Instr(OffsetAddLeft(_)) => (),

                Instr(FindZeroRight(_)) =>
                    net = if net.is_right_only() { RightOnly } else { Unknown },

                Instr(FindZeroLeft(_)) =>
                    net = if net.is_left_only() { LeftOnly } else { Unknown },

                Loop(ref body) => {
                    let body = self.analyze_loop(body);

                    net = match net {
                        Exact(disp) if body.is_balanced()                   => Exact(disp),
                        _ if net.is_right_only() && body.is_right_only()    => RightOnly,
                        _ if net.is_left_only() && body.is_left_only()      => LeftOnly,
                        _                                                   => Unknown,
                    }
                }
            }
        }

        self.0.insert(LoopIndex::from_loop_body(body), net);

        net
    }
}
<commit_msg>Clippy clean.<commit_after>//! Loop movement balance analysis.
//!
//! This analysis determines, for the body of a loop, whether its net movement is an exact
//! amount, an unknown amount in a given direction, or unknown altogether. This is used by the
//! bound checking analysis when it encounters loops.

use std::collections::HashMap;
use peephole::{Statement, Program};

/// The body of a loop is a boxed slice of `Statement`s.
pub type LoopBody = Box<[Statement]>;

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
/// The net movement of a loop.
pub enum LoopBalance {
    /// The exact movement of one iteration.
    Exact(isize),
    /// May move right but not left.
    RightOnly,
    /// May move left but not right.
    LeftOnly,
    /// Net movement may be either direction.
    Unknown,
}

/// An index to a loop.
///
/// This is represented as the address of the first instruction of the loop.
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
struct LoopIndex(usize);

/// The computed net movement for each loop.
#[derive(Debug)]
pub struct LoopBalanceMap(HashMap<LoopIndex, LoopBalance>);

impl LoopBalance {
    /// Is the loop body exactly balanced between right and left?
    pub fn is_balanced(self) -> bool {
        self == LoopBalance::Exact(0)
    }

    /// Does the loop move net right (if at all)?
    pub fn is_right_only(self) -> bool {
        use self::LoopBalance::*;

        match self {
            Exact(disp)         => disp >= 0,
            RightOnly           => true,
            LeftOnly | Unknown  => false,
        }
    }

    /// Does the loop move net left (if at all)?
    pub fn is_left_only(self) -> bool {
        use self::LoopBalance::*;

        match self {
            Exact(disp)         => disp <= 0,
            LeftOnly            => true,
            RightOnly | Unknown => false,
        }
    }
}

impl LoopIndex {
    /// Gets the loop index from a boxed loop.
    fn from_loop_body(body: &LoopBody) -> Self {
        LoopIndex(body.as_ptr() as usize)
    }
}

impl LoopBalanceMap {
    /// Initializes the map for the given program.
    pub fn new(program: &Program) -> Self {
        let mut result = LoopBalanceMap(HashMap::new());

        for statement in program {
            match *statement {
                Statement::Instr(_) => (),
                Statement::Loop(ref body) => {
                    result.analyze_loop(body);
                }
            }
        }

        result
    }

    /// Gets the balance of the given loop body.
    pub fn get(&self, body: &LoopBody) -> LoopBalance {
        *self.0.get(&LoopIndex::from_loop_body(body)).unwrap_or(&LoopBalance::Unknown)
    }

    /// Performs the analysis for the given loop body and any sub-loops.
    ///
    /// Stores the result of the analysis in `self`.
    fn analyze_loop(&mut self, body: &LoopBody) -> LoopBalance {
        use peephole::Statement::*;
        use common::Instruction::*;
        use self::LoopBalance::*;

        let mut net = Exact(0);

        for statement in &**body {
            match *statement {
                Instr(Right(count)) => net = match net {
                    Exact(disp) => Exact(disp + count as isize),
                    RightOnly   => RightOnly,
                    _           => Unknown,
                },

                Instr(Left(count)) => net = match net {
                    Exact(disp) => Exact(disp - count as isize),
                    LeftOnly    => LeftOnly,
                    _           => Unknown,
                },

                Instr(Add(_)) | Instr(In) | Instr(Out) |
                Instr(SetZero) | Instr(OffsetAddRight(_)) | Instr(OffsetAddLeft(_)) => (),

                Instr(JumpZero(_)) | Instr(JumpNotZero(_)) =>
                    panic!("unexpected jump instruction"),

                Instr(FindZeroRight(_)) =>
                    net = if net.is_right_only() { RightOnly } else { Unknown },

                Instr(FindZeroLeft(_)) =>
                    net = if net.is_left_only() { LeftOnly } else { Unknown },

                Loop(ref body) => {
                    let body = self.analyze_loop(body);

                    net = match net {
                        Exact(disp) if body.is_balanced()                   => Exact(disp),
                        _ if net.is_right_only() && body.is_right_only()    => RightOnly,
                        _ if net.is_left_only() && body.is_left_only()      => LeftOnly,
                        _                                                   => Unknown,
                    }
                }
            }
        }

        self.0.insert(LoopIndex::from_loop_body(body), net);

        net
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate dimensioned;

make_units!{
    Fruit, Unitless, one;
    base {
        Apple, apple, a;
        Banana, banana, b;
        Cucumber, cuke, c;
        Mango, mango, m;
        Watermelon, watermelon, w;
    }
    derived {
    }
}

fn main() {
    let fruit_salad = apple * banana * mango * mango * watermelon;
    println!("Mmmm, delicious: {}", fruit_salad);
}
<commit_msg>Example tweak<commit_after>#[macro_use]
extern crate dimensioned;

make_units!{
    Fruit, Unitless, one;
    base {
        Apple, apple, a;
        Banana, banana, b;
        Cucumber, cuke, c;
        Mango, mango, m;
        Watermelon, watermelon, w;
    }
    derived {
    }
}

fn main() {
    let fruit_salad = apple * banana * mango * mango * watermelon;
    // prints "Mmmm, delicious: 1 a*b*m^2*w":
    println!("Mmmm, delicious: {}", fruit_salad);
}
<|endoftext|>


<commit_before>extern crate minifb;

const WIDTH: usize = 1280;
const HEIGHT: usize = 720;

fn main() {
    let mut noise;
    let mut carry;
    let mut seed = 0xbeefu32;

    let mut buffer: [u32; WIDTH * HEIGHT] = [0; WIDTH * HEIGHT];

    if !(minifb::open("TestWindow", WIDTH, HEIGHT)) {
        return;
    }

    while minifb::update(&buffer) {
        for i in buffer.iter_mut() {
            noise = seed;
            noise >>= 3;
            noise ^= seed;
            carry = noise & 1;
            noise >>= 1;
            seed >>= 1;
            seed |= carry << 30;
            noise &= 0xFF;
            *i = (noise << 16) | (noise << 8) | noise;
        }
    }

    minifb::close();
}
<commit_msg>Updated Noise Example<commit_after>extern crate minifb;

const WIDTH: usize = 640;
const HEIGHT: usize = 360;

fn main() {
    let mut noise;
    let mut carry;
    let mut seed = 0xbeefu32;

    let mut buffer: [u32; WIDTH * HEIGHT] = [0; WIDTH * HEIGHT];

    if !(minifb::open("Noise Test - Press ESC to exit", WIDTH, HEIGHT)) {
        return;
    }

    while minifb::update(&buffer) {
        for i in buffer.iter_mut() {
            noise = seed;
            noise >>= 3;
            noise ^= seed;
            carry = noise & 1;
            noise >>= 1;
            seed >>= 1;
            seed |= carry << 30;
            noise &= 0xFF;
            *i = (noise << 16) | (noise << 8) | noise;
        }
    }

    minifb::close();
}
<|endoftext|>


<commit_before>use std::ascii::AsciiExt;

pub fn camel_case(name: &str) -> String {
    let mut s = String::new();
    let mut last = ' ';
    for c in name.chars() {
        if !c.is_alphanumeric() {
            last = c;
            continue;
        }
        if !c.is_ascii() {
            last = c;
            continue;
        }
        if (!last.is_alphabetic() && c.is_alphabetic()) || (last.is_lowercase() && c.is_uppercase()) {
            s.push(c.to_ascii_uppercase());
        } else {
            s.push(c.to_ascii_lowercase());
        }
        last = c;
    }
    s
}

pub fn snake_case(name: &str) -> String {
    let mut s = String::new();
    let mut last = 'A';
    for c in name.chars() {
        if !c.is_alphanumeric() {
            last = c;
            continue;
        }
        if !c.is_ascii() {
            last = c;
            continue;
        }
        if (!last.is_alphabetic() && c.is_alphabetic()) || (last.is_lowercase() && c.is_uppercase()) {
            s.push('_');
        }
        s.push(c.to_ascii_lowercase());
        last = c;
    }
    s
}

pub fn type_case(name: &str) -> String {
    let s = camel_case(name);
    uppercase_first_letter(&s)
}

// from http://stackoverflow.com/questions/38406793/.../38406885
fn uppercase_first_letter(s: &str) -> String {
    let mut c = s.chars();
    match c.next() {
        None => String::new(),
        Some(f) => f.to_uppercase().collect::<String>() + c.as_str(),
    }
}

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

    #[test]
    fn test_camel_case() {
        assert_eq!("FooBar", &camel_case("FooBar"));
        assert_eq!("FooBar", &camel_case("fooBar"));
        assert_eq!("FooBar", &camel_case("foo bar"));
        assert_eq!("FooBar", &camel_case("foo_bar"));
        assert_eq!("FooBar", &camel_case("FOO_BAR"));
    }

    #[test]
    fn test_snake_case() {
        assert_eq!("foo_bar", &snake_case("FooBar"));
        assert_eq!("foo_bar", &snake_case("fooBar"));
        assert_eq!("foo_bar", &snake_case("foo bar"));
        assert_eq!("foo_bar", &snake_case("foo_bar"));
        assert_eq!("foo_bar", &snake_case("FOO_BAR"));
    }
}
<commit_msg>Minor fixes to type and field naming<commit_after>use std::ascii::AsciiExt;

pub fn camel_case(name: &str) -> String {
    let mut s = String::new();
    let mut last = ' ';
    for c in name.chars().skip_while(|c| !(c.is_alphanumeric() && c.is_ascii())) {
        if !c.is_alphanumeric() {
            last = c;
            continue;
        }
        if !c.is_ascii() {
            last = c;
            continue;
        }
        if (!last.is_alphabetic() && c.is_alphabetic()) || (last.is_lowercase() && c.is_uppercase()) {
            s.push(c.to_ascii_uppercase());
        } else {
            s.push(c.to_ascii_lowercase());
        }
        last = c;
    }
    s
}

pub fn snake_case(name: &str) -> String {
    let mut s = String::new();
    let mut last = 'A';
    for c in name.chars().skip_while(|c| !(c.is_alphanumeric() && c.is_ascii())) {
        if !c.is_alphanumeric() {
            last = c;
            continue;
        }
        if !c.is_ascii() {
            last = c;
            continue;
        }
        if (!last.is_alphabetic() && c.is_alphabetic()) || (last.is_lowercase() && c.is_uppercase()) {
            s.push('_');
        }
        s.push(c.to_ascii_lowercase());
        last = c;
    }
    s
}

pub fn type_case(name: &str) -> String {
    let s = camel_case(name);
    uppercase_first_letter(&s)
}

// from http://stackoverflow.com/questions/38406793/.../38406885
fn uppercase_first_letter(s: &str) -> String {
    let mut c = s.chars();
    match c.next() {
        None => String::new(),
        Some(f) => f.to_uppercase().collect::<String>() + c.as_str(),
    }
}

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

    #[test]
    fn test_camel_case() {
        assert_eq!("FooBar", &camel_case("FooBar"));
        assert_eq!("FooBar", &camel_case("fooBar"));
        assert_eq!("FooBar", &camel_case("foo bar"));
        assert_eq!("FooBar", &camel_case("foo_bar"));
        assert_eq!("FooBar", &camel_case("_foo_bar"));
        assert_eq!("FooBar", &camel_case("åfoo_bar"));
        assert_eq!("FooBar", &camel_case("foåo_bar"));
        assert_eq!("FooBar", &camel_case("FOO_BAR"));
    }

    #[test]
    fn test_snake_case() {
        assert_eq!("foo_bar", &snake_case("FooBar"));
        assert_eq!("foo_bar", &snake_case("fooBar"));
        assert_eq!("foo_bar", &snake_case("foo bar"));
        assert_eq!("foo_bar", &snake_case("foo_bar"));
        assert_eq!("foo_bar", &snake_case("_foo_bar"));
        assert_eq!("foo_bar", &snake_case("åfoo_bar"));
        assert_eq!("foo_bar", &snake_case("foåo_bar"));
        assert_eq!("foo_bar", &snake_case("FOO_BAR"));
    }
}
<|endoftext|>