<commit_before>//! Http client request
use std::{fmt, io, str};
use std::rc::Rc;
use std::cell::UnsafeCell;

use base64;
use rand;
use bytes::Bytes;
use cookie::Cookie;
use http::{HttpTryFrom, StatusCode, Error as HttpError};
use http::header::{self, HeaderName, HeaderValue};
use sha1::Sha1;
use futures::{Async, Future, Poll, Stream};
use futures::unsync::mpsc::{unbounded, UnboundedSender};
use byteorder::{ByteOrder, NetworkEndian};

use actix::prelude::*;

use body::{Body, Binary};
use error::UrlParseError;
use payload::PayloadHelper;
use httpmessage::HttpMessage;

use client::{ClientRequest, ClientRequestBuilder, ClientResponse,
             ClientConnector, SendRequest, SendRequestError,
             HttpResponseParserError};

use super::{Message, WsError};
use super::frame::Frame;
use super::proto::{CloseCode, OpCode};

/// Websocket client error
#[derive(Fail, Debug)]
pub enum WsClientError {
    #[fail(display="Invalid url")]
    InvalidUrl,
    #[fail(display="Invalid response status")]
    InvalidResponseStatus,
    #[fail(display="Invalid upgrade header")]
    InvalidUpgradeHeader,
    #[fail(display="Invalid connection header")]
    InvalidConnectionHeader,
    #[fail(display="Invalid challenge response")]
    InvalidChallengeResponse,
    #[fail(display="Http parsing error")]
    Http(HttpError),
    #[fail(display="Url parsing error")]
    Url(UrlParseError),
    #[fail(display="Response parsing error")]
    ResponseParseError(HttpResponseParserError),
    #[fail(display="{}", _0)]
    SendRequest(SendRequestError),
    #[fail(display="{}", _0)]
    Protocol(#[cause] WsError),
    #[fail(display="{}", _0)]
    Io(io::Error),
    #[fail(display="Disconnected")]
    Disconnected,
}

impl From<HttpError> for WsClientError {
    fn from(err: HttpError) -> WsClientError {
        WsClientError::Http(err)
    }
}

impl From<UrlParseError> for WsClientError {
    fn from(err: UrlParseError) -> WsClientError {
        WsClientError::Url(err)
    }
}

impl From<SendRequestError> for WsClientError {
    fn from(err: SendRequestError) -> WsClientError {
        WsClientError::SendRequest(err)
    }
}

impl From<WsError> for WsClientError {
    fn from(err: WsError) -> WsClientError {
        WsClientError::Protocol(err)
    }
}

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

impl From<HttpResponseParserError> for WsClientError {
    fn from(err: HttpResponseParserError) -> WsClientError {
        WsClientError::ResponseParseError(err)
    }
}

/// `WebSocket` client
///
/// Example of `WebSocket` client usage is available in
/// [websocket example](
/// https://github.com/actix/actix-web/blob/master/examples/websocket/src/client.rs#L24)
pub struct WsClient {
    request: ClientRequestBuilder,
    err: Option<WsClientError>,
    http_err: Option<HttpError>,
    origin: Option<HeaderValue>,
    protocols: Option<String>,
    conn: Addr<Unsync, ClientConnector>,
    max_size: usize,
}

impl WsClient {

    /// Create new websocket connection
    pub fn new<S: AsRef<str>>(uri: S) -> WsClient {
        WsClient::with_connector(uri, ClientConnector::from_registry())
    }

    /// Create new websocket connection with custom `ClientConnector`
    pub fn with_connector<S: AsRef<str>>(uri: S, conn: Addr<Unsync, ClientConnector>) -> WsClient {
        let mut cl = WsClient {
            request: ClientRequest::build(),
            err: None,
            http_err: None,
            origin: None,
            protocols: None,
            max_size: 65_536,
            conn,
        };
        cl.request.uri(uri.as_ref());
        cl
    }

    /// Set supported websocket protocols
    pub fn protocols<U, V>(mut self, protos: U) -> Self
        where U: IntoIterator<Item=V> + 'static,
              V: AsRef<str>
    {
        let mut protos = protos.into_iter()
            .fold(String::new(), |acc, s| {acc + s.as_ref() + ","});
        protos.pop();
        self.protocols = Some(protos);
        self
    }

    /// Set cookie for handshake request
    pub fn cookie(mut self, cookie: Cookie) -> Self {
        self.request.cookie(cookie);
        self
    }

    /// Set request Origin
    pub fn origin<V>(mut self, origin: V) -> Self
        where HeaderValue: HttpTryFrom<V>
    {
        match HeaderValue::try_from(origin) {
            Ok(value) => self.origin = Some(value),
            Err(e) => self.http_err = Some(e.into()),
        }
        self
    }

    /// Set max frame size
    ///
    /// By default max size is set to 64kb
    pub fn max_frame_size(mut self, size: usize) -> Self {
        self.max_size = size;
        self
    }

    /// Set request header
    pub fn header<K, V>(mut self, key: K, value: V) -> Self
        where HeaderName: HttpTryFrom<K>, HeaderValue: HttpTryFrom<V>
    {
        self.request.header(key, value);
        self
    }

    /// Connect to websocket server and do ws handshake
    pub fn connect(&mut self) -> WsClientHandshake {
        if let Some(e) = self.err.take() {
            WsClientHandshake::error(e)
        }
        else if let Some(e) = self.http_err.take() {
            WsClientHandshake::error(e.into())
        } else {
            // origin
            if let Some(origin) = self.origin.take() {
                self.request.set_header(header::ORIGIN, origin);
            }

            self.request.upgrade();
            self.request.set_header(header::UPGRADE, "websocket");
            self.request.set_header(header::CONNECTION, "upgrade");
            self.request.set_header("SEC-WEBSOCKET-VERSION", "13");
            self.request.with_connector(self.conn.clone());

            if let Some(protocols) = self.protocols.take() {
                self.request.set_header("SEC-WEBSOCKET-PROTOCOL", protocols.as_str());
            }
            let request = match self.request.finish() {
                Ok(req) => req,
                Err(err) => return WsClientHandshake::error(err.into()),
            };

            if request.uri().host().is_none() {
                return WsClientHandshake::error(WsClientError::InvalidUrl)
            }
            if let Some(scheme) = request.uri().scheme_part() {
                if scheme != "http" && scheme != "https" && scheme != "ws" && scheme != "wss" {
                    return WsClientHandshake::error(WsClientError::InvalidUrl)
                }
            } else {
                return WsClientHandshake::error(WsClientError::InvalidUrl)
            }

            // start handshake
            WsClientHandshake::new(request, self.max_size)
        }
    }
}

struct WsInner {
    tx: UnboundedSender<Bytes>,
    rx: PayloadHelper<ClientResponse>,
    closed: bool,
}

pub struct WsClientHandshake {
    request: Option<SendRequest>,
    tx: Option<UnboundedSender<Bytes>>,
    key: String,
    error: Option<WsClientError>,
    max_size: usize,
}

impl WsClientHandshake {
    fn new(mut request: ClientRequest, max_size: usize) -> WsClientHandshake
    {
        // Generate a random key for the `Sec-WebSocket-Key` header.
        // a base64-encoded (see Section 4 of [RFC4648]) value that,
        // when decoded, is 16 bytes in length (RFC 6455)
        let sec_key: [u8; 16] = rand::random();
        let key = base64::encode(&sec_key);

        request.headers_mut().insert(
            HeaderName::try_from("SEC-WEBSOCKET-KEY").unwrap(),
            HeaderValue::try_from(key.as_str()).unwrap());

        let (tx, rx) = unbounded();
        request.set_body(Body::Streaming(
            Box::new(rx.map_err(|_| io::Error::new(
                io::ErrorKind::Other, "disconnected").into()))));

        WsClientHandshake {
            key,
            max_size,
            request: Some(request.send()),
            tx: Some(tx),
            error: None,
        }
    }

    fn error(err: WsClientError) -> WsClientHandshake {
        WsClientHandshake {
            key: String::new(),
            request: None,
            tx: None,
            error: Some(err),
            max_size: 0
        }
    }
}

impl Future for WsClientHandshake {
    type Item = (WsClientReader, WsClientWriter);
    type Error = WsClientError;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        if let Some(err) = self.error.take() {
            return Err(err)
        }

        let resp = match self.request.as_mut().unwrap().poll()? {
            Async::Ready(response) => {
                self.request.take();
                response
            },
            Async::NotReady => return Ok(Async::NotReady)
        };

        // verify response
        if resp.status() != StatusCode::SWITCHING_PROTOCOLS {
            return Err(WsClientError::InvalidResponseStatus)
        }
        // Check for "UPGRADE" to websocket header
        let has_hdr = if let Some(hdr) = resp.headers().get(header::UPGRADE) {
            if let Ok(s) = hdr.to_str() {
                s.to_lowercase().contains("websocket")
            } else {
                false
            }
        } else {
            false
        };
        if !has_hdr {
            return Err(WsClientError::InvalidUpgradeHeader)
        }
        // Check for "CONNECTION" header
        let has_hdr = if let Some(conn) = resp.headers().get(header::CONNECTION) {
            if let Ok(s) = conn.to_str() {
                s.to_lowercase().contains("upgrade")
            } else { false }
        } else { false };
        if !has_hdr {
            return Err(WsClientError::InvalidConnectionHeader)
        }

        let match_key = if let Some(key) = resp.headers().get(
            HeaderName::try_from("SEC-WEBSOCKET-ACCEPT").unwrap())
        {
            // field is constructed by concatenating /key/
            // with the string "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" (RFC 6455)
            const WS_GUID: &[u8] = b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
            let mut sha1 = Sha1::new();
            sha1.update(self.key.as_ref());
            sha1.update(WS_GUID);
            key.as_bytes() == base64::encode(&sha1.digest().bytes()).as_bytes()
        } else {
            false
        };
        if !match_key {
            return Err(WsClientError::InvalidChallengeResponse)
        }

        let inner = WsInner {
            tx: self.tx.take().unwrap(),
            rx: PayloadHelper::new(resp),
            closed: false,
        };

        let inner = Rc::new(UnsafeCell::new(inner));
        Ok(Async::Ready(
            (WsClientReader{inner: Rc::clone(&inner), max_size: self.max_size},
             WsClientWriter{inner})))
    }
}

pub struct WsClientReader {
    inner: Rc<UnsafeCell<WsInner>>,
    max_size: usize,
}

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

impl WsClientReader {
    #[inline]
    fn as_mut(&mut self) -> &mut WsInner {
        unsafe{ &mut *self.inner.get() }
    }
}

impl Stream for WsClientReader {
    type Item = Message;
    type Error = WsError;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        let max_size = self.max_size;
        let inner = self.as_mut();
        if inner.closed {
            return Ok(Async::Ready(None))
        }

        // read
        match Frame::parse(&mut inner.rx, false, max_size) {
            Ok(Async::Ready(Some(frame))) => {
                let (finished, opcode, payload) = frame.unpack();

                // continuation is not supported
                if !finished {
                    inner.closed = true;
                    return Err(WsError::NoContinuation)
                }

                match opcode {
                    OpCode::Continue => unimplemented!(),
                    OpCode::Bad => {
                        inner.closed = true;
                        Err(WsError::BadOpCode)
                    },
                    OpCode::Close => {
                        inner.closed = true;
                        let code = NetworkEndian::read_uint(payload.as_ref(), 2) as u16;
                        Ok(Async::Ready(Some(Message::Close(CloseCode::from(code)))))
                    },
                    OpCode::Ping =>
                        Ok(Async::Ready(Some(
                            Message::Ping(
                                String::from_utf8_lossy(payload.as_ref()).into())))),
                    OpCode::Pong =>
                        Ok(Async::Ready(Some(
                            Message::Pong(
                                String::from_utf8_lossy(payload.as_ref()).into())))),
                    OpCode::Binary =>
                        Ok(Async::Ready(Some(Message::Binary(payload)))),
                    OpCode::Text => {
                        let tmp = Vec::from(payload.as_ref());
                        match String::from_utf8(tmp) {
                            Ok(s) =>
                                Ok(Async::Ready(Some(Message::Text(s)))),
                            Err(_) => {
                                inner.closed = true;
                                Err(WsError::BadEncoding)
                            }
                        }
                    }
                }
            }
            Ok(Async::Ready(None)) => Ok(Async::Ready(None)),
            Ok(Async::NotReady) => Ok(Async::NotReady),
            Err(e) => {
                inner.closed = true;
                Err(e)
            }
        }
    }
}

pub struct WsClientWriter {
    inner: Rc<UnsafeCell<WsInner>>
}

impl WsClientWriter {
    #[inline]
    fn as_mut(&mut self) -> &mut WsInner {
        unsafe{ &mut *self.inner.get() }
    }
}

impl WsClientWriter {

    /// Write payload
    #[inline]
    fn write(&mut self, mut data: Binary) {
        if !self.as_mut().closed {
            let _ = self.as_mut().tx.unbounded_send(data.take());
        } else {
            warn!("Trying to write to disconnected response");
        }
    }

    /// Send text frame
    #[inline]
    pub fn text<T: Into<String>>(&mut self, text: T) {
        self.write(Frame::message(text.into(), OpCode::Text, true, true));
    }

    /// Send binary frame
    #[inline]
    pub fn binary<B: Into<Binary>>(&mut self, data: B) {
        self.write(Frame::message(data, OpCode::Binary, true, true));
    }

    /// Send ping frame
    #[inline]
    pub fn ping(&mut self, message: &str) {
        self.write(Frame::message(Vec::from(message), OpCode::Ping, true, true));
    }

    /// Send pong frame
    #[inline]
    pub fn pong(&mut self, message: &str) {
        self.write(Frame::message(Vec::from(message), OpCode::Pong, true, true));
    }

    /// Send close frame
    #[inline]
    pub fn close(&mut self, code: CloseCode, reason: &str) {
        self.write(Frame::close(code, reason, true));
    }
}
<commit_msg>add ws error tracing<commit_after>//! Http client request
use std::{fmt, io, str};
use std::rc::Rc;
use std::cell::UnsafeCell;

use base64;
use rand;
use bytes::Bytes;
use cookie::Cookie;
use http::{HttpTryFrom, StatusCode, Error as HttpError};
use http::header::{self, HeaderName, HeaderValue};
use sha1::Sha1;
use futures::{Async, Future, Poll, Stream};
use futures::unsync::mpsc::{unbounded, UnboundedSender};
use byteorder::{ByteOrder, NetworkEndian};

use actix::prelude::*;

use body::{Body, Binary};
use error::UrlParseError;
use payload::PayloadHelper;
use httpmessage::HttpMessage;

use client::{ClientRequest, ClientRequestBuilder, ClientResponse,
             ClientConnector, SendRequest, SendRequestError,
             HttpResponseParserError};

use super::{Message, WsError};
use super::frame::Frame;
use super::proto::{CloseCode, OpCode};

/// Websocket client error
#[derive(Fail, Debug)]
pub enum WsClientError {
    #[fail(display="Invalid url")]
    InvalidUrl,
    #[fail(display="Invalid response status")]
    InvalidResponseStatus(StatusCode),
    #[fail(display="Invalid upgrade header")]
    InvalidUpgradeHeader,
    #[fail(display="Invalid connection header")]
    InvalidConnectionHeader(HeaderValue),
    #[fail(display="Missing CONNECTION header")]
    MissingConnectionHeader,
    #[fail(display="Missing SEC-WEBSOCKET-ACCEPT header")]
    MissingWebSocketAcceptHeader,
    #[fail(display="Invalid challenge response")]
    InvalidChallengeResponse(String, HeaderValue),
    #[fail(display="Http parsing error")]
    Http(HttpError),
    #[fail(display="Url parsing error")]
    Url(UrlParseError),
    #[fail(display="Response parsing error")]
    ResponseParseError(HttpResponseParserError),
    #[fail(display="{}", _0)]
    SendRequest(SendRequestError),
    #[fail(display="{}", _0)]
    Protocol(#[cause] WsError),
    #[fail(display="{}", _0)]
    Io(io::Error),
    #[fail(display="Disconnected")]
    Disconnected,
}

impl From<HttpError> for WsClientError {
    fn from(err: HttpError) -> WsClientError {
        WsClientError::Http(err)
    }
}

impl From<UrlParseError> for WsClientError {
    fn from(err: UrlParseError) -> WsClientError {
        WsClientError::Url(err)
    }
}

impl From<SendRequestError> for WsClientError {
    fn from(err: SendRequestError) -> WsClientError {
        WsClientError::SendRequest(err)
    }
}

impl From<WsError> for WsClientError {
    fn from(err: WsError) -> WsClientError {
        WsClientError::Protocol(err)
    }
}

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

impl From<HttpResponseParserError> for WsClientError {
    fn from(err: HttpResponseParserError) -> WsClientError {
        WsClientError::ResponseParseError(err)
    }
}

/// `WebSocket` client
///
/// Example of `WebSocket` client usage is available in
/// [websocket example](
/// https://github.com/actix/actix-web/blob/master/examples/websocket/src/client.rs#L24)
pub struct WsClient {
    request: ClientRequestBuilder,
    err: Option<WsClientError>,
    http_err: Option<HttpError>,
    origin: Option<HeaderValue>,
    protocols: Option<String>,
    conn: Addr<Unsync, ClientConnector>,
    max_size: usize,
}

impl WsClient {

    /// Create new websocket connection
    pub fn new<S: AsRef<str>>(uri: S) -> WsClient {
        WsClient::with_connector(uri, ClientConnector::from_registry())
    }

    /// Create new websocket connection with custom `ClientConnector`
    pub fn with_connector<S: AsRef<str>>(uri: S, conn: Addr<Unsync, ClientConnector>) -> WsClient {
        let mut cl = WsClient {
            request: ClientRequest::build(),
            err: None,
            http_err: None,
            origin: None,
            protocols: None,
            max_size: 65_536,
            conn,
        };
        cl.request.uri(uri.as_ref());
        cl
    }

    /// Set supported websocket protocols
    pub fn protocols<U, V>(mut self, protos: U) -> Self
        where U: IntoIterator<Item=V> + 'static,
              V: AsRef<str>
    {
        let mut protos = protos.into_iter()
            .fold(String::new(), |acc, s| {acc + s.as_ref() + ","});
        protos.pop();
        self.protocols = Some(protos);
        self
    }

    /// Set cookie for handshake request
    pub fn cookie(mut self, cookie: Cookie) -> Self {
        self.request.cookie(cookie);
        self
    }

    /// Set request Origin
    pub fn origin<V>(mut self, origin: V) -> Self
        where HeaderValue: HttpTryFrom<V>
    {
        match HeaderValue::try_from(origin) {
            Ok(value) => self.origin = Some(value),
            Err(e) => self.http_err = Some(e.into()),
        }
        self
    }

    /// Set max frame size
    ///
    /// By default max size is set to 64kb
    pub fn max_frame_size(mut self, size: usize) -> Self {
        self.max_size = size;
        self
    }

    /// Set request header
    pub fn header<K, V>(mut self, key: K, value: V) -> Self
        where HeaderName: HttpTryFrom<K>, HeaderValue: HttpTryFrom<V>
    {
        self.request.header(key, value);
        self
    }

    /// Connect to websocket server and do ws handshake
    pub fn connect(&mut self) -> WsClientHandshake {
        if let Some(e) = self.err.take() {
            WsClientHandshake::error(e)
        }
        else if let Some(e) = self.http_err.take() {
            WsClientHandshake::error(e.into())
        } else {
            // origin
            if let Some(origin) = self.origin.take() {
                self.request.set_header(header::ORIGIN, origin);
            }

            self.request.upgrade();
            self.request.set_header(header::UPGRADE, "websocket");
            self.request.set_header(header::CONNECTION, "upgrade");
            self.request.set_header("SEC-WEBSOCKET-VERSION", "13");
            self.request.with_connector(self.conn.clone());

            if let Some(protocols) = self.protocols.take() {
                self.request.set_header("SEC-WEBSOCKET-PROTOCOL", protocols.as_str());
            }
            let request = match self.request.finish() {
                Ok(req) => req,
                Err(err) => return WsClientHandshake::error(err.into()),
            };

            if request.uri().host().is_none() {
                return WsClientHandshake::error(WsClientError::InvalidUrl)
            }
            if let Some(scheme) = request.uri().scheme_part() {
                if scheme != "http" && scheme != "https" && scheme != "ws" && scheme != "wss" {
                    return WsClientHandshake::error(WsClientError::InvalidUrl)
                }
            } else {
                return WsClientHandshake::error(WsClientError::InvalidUrl)
            }

            // start handshake
            WsClientHandshake::new(request, self.max_size)
        }
    }
}

struct WsInner {
    tx: UnboundedSender<Bytes>,
    rx: PayloadHelper<ClientResponse>,
    closed: bool,
}

pub struct WsClientHandshake {
    request: Option<SendRequest>,
    tx: Option<UnboundedSender<Bytes>>,
    key: String,
    error: Option<WsClientError>,
    max_size: usize,
}

impl WsClientHandshake {
    fn new(mut request: ClientRequest, max_size: usize) -> WsClientHandshake
    {
        // Generate a random key for the `Sec-WebSocket-Key` header.
        // a base64-encoded (see Section 4 of [RFC4648]) value that,
        // when decoded, is 16 bytes in length (RFC 6455)
        let sec_key: [u8; 16] = rand::random();
        let key = base64::encode(&sec_key);

        request.headers_mut().insert(
            HeaderName::try_from("SEC-WEBSOCKET-KEY").unwrap(),
            HeaderValue::try_from(key.as_str()).unwrap());

        let (tx, rx) = unbounded();
        request.set_body(Body::Streaming(
            Box::new(rx.map_err(|_| io::Error::new(
                io::ErrorKind::Other, "disconnected").into()))));

        WsClientHandshake {
            key,
            max_size,
            request: Some(request.send()),
            tx: Some(tx),
            error: None,
        }
    }

    fn error(err: WsClientError) -> WsClientHandshake {
        WsClientHandshake {
            key: String::new(),
            request: None,
            tx: None,
            error: Some(err),
            max_size: 0
        }
    }
}

impl Future for WsClientHandshake {
    type Item = (WsClientReader, WsClientWriter);
    type Error = WsClientError;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        if let Some(err) = self.error.take() {
            return Err(err)
        }

        let resp = match self.request.as_mut().unwrap().poll()? {
            Async::Ready(response) => {
                self.request.take();
                response
            },
            Async::NotReady => return Ok(Async::NotReady)
        };

        // verify response
        if resp.status() != StatusCode::SWITCHING_PROTOCOLS {
            return Err(WsClientError::InvalidResponseStatus(resp.status()))
        }
        // Check for "UPGRADE" to websocket header
        let has_hdr = if let Some(hdr) = resp.headers().get(header::UPGRADE) {
            if let Ok(s) = hdr.to_str() {
                s.to_lowercase().contains("websocket")
            } else {
                false
            }
        } else {
            false
        };
        if !has_hdr {
            trace!("Invalid upgrade header");
            return Err(WsClientError::InvalidUpgradeHeader)
        }
        // Check for "CONNECTION" header
        if let Some(conn) = resp.headers().get(header::CONNECTION) {
            if let Ok(s) = conn.to_str() {
                if !s.to_lowercase().contains("upgrade") {
                    trace!("Invalid connection header: {}", s);
                    return Err(WsClientError::InvalidConnectionHeader(conn.clone()))
                }
            } else {
                trace!("Invalid connection header: {:?}", conn);
                return Err(WsClientError::InvalidConnectionHeader(conn.clone()))
            }
        } else {
            trace!("Missing connection header");
            return Err(WsClientError::MissingConnectionHeader)
        }

        if let Some(key) = resp.headers().get(
            HeaderName::try_from("SEC-WEBSOCKET-ACCEPT").unwrap())
        {
            // field is constructed by concatenating /key/
            // with the string "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" (RFC 6455)
            const WS_GUID: &[u8] = b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
            let mut sha1 = Sha1::new();
            sha1.update(self.key.as_ref());
            sha1.update(WS_GUID);
            let encoded = base64::encode(&sha1.digest().bytes());
            if key.as_bytes() != encoded.as_bytes() {
                trace!(
                    "Invalid challenge response: expected: {} received: {:?}",
                    encoded, key);
                return Err(WsClientError::InvalidChallengeResponse(encoded, key.clone()));
            }
        } else {
            trace!("Missing SEC-WEBSOCKET-ACCEPT header");
            return Err(WsClientError::MissingWebSocketAcceptHeader)
        };

        let inner = WsInner {
            tx: self.tx.take().unwrap(),
            rx: PayloadHelper::new(resp),
            closed: false,
        };

        let inner = Rc::new(UnsafeCell::new(inner));
        Ok(Async::Ready(
            (WsClientReader{inner: Rc::clone(&inner), max_size: self.max_size},
             WsClientWriter{inner})))
    }
}

pub struct WsClientReader {
    inner: Rc<UnsafeCell<WsInner>>,
    max_size: usize,
}

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

impl WsClientReader {
    #[inline]
    fn as_mut(&mut self) -> &mut WsInner {
        unsafe{ &mut *self.inner.get() }
    }
}

impl Stream for WsClientReader {
    type Item = Message;
    type Error = WsError;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        let max_size = self.max_size;
        let inner = self.as_mut();
        if inner.closed {
            return Ok(Async::Ready(None))
        }

        // read
        match Frame::parse(&mut inner.rx, false, max_size) {
            Ok(Async::Ready(Some(frame))) => {
                let (finished, opcode, payload) = frame.unpack();

                // continuation is not supported
                if !finished {
                    inner.closed = true;
                    return Err(WsError::NoContinuation)
                }

                match opcode {
                    OpCode::Continue => unimplemented!(),
                    OpCode::Bad => {
                        inner.closed = true;
                        Err(WsError::BadOpCode)
                    },
                    OpCode::Close => {
                        inner.closed = true;
                        let code = NetworkEndian::read_uint(payload.as_ref(), 2) as u16;
                        Ok(Async::Ready(Some(Message::Close(CloseCode::from(code)))))
                    },
                    OpCode::Ping =>
                        Ok(Async::Ready(Some(
                            Message::Ping(
                                String::from_utf8_lossy(payload.as_ref()).into())))),
                    OpCode::Pong =>
                        Ok(Async::Ready(Some(
                            Message::Pong(
                                String::from_utf8_lossy(payload.as_ref()).into())))),
                    OpCode::Binary =>
                        Ok(Async::Ready(Some(Message::Binary(payload)))),
                    OpCode::Text => {
                        let tmp = Vec::from(payload.as_ref());
                        match String::from_utf8(tmp) {
                            Ok(s) =>
                                Ok(Async::Ready(Some(Message::Text(s)))),
                            Err(_) => {
                                inner.closed = true;
                                Err(WsError::BadEncoding)
                            }
                        }
                    }
                }
            }
            Ok(Async::Ready(None)) => Ok(Async::Ready(None)),
            Ok(Async::NotReady) => Ok(Async::NotReady),
            Err(e) => {
                inner.closed = true;
                Err(e)
            }
        }
    }
}

pub struct WsClientWriter {
    inner: Rc<UnsafeCell<WsInner>>
}

impl WsClientWriter {
    #[inline]
    fn as_mut(&mut self) -> &mut WsInner {
        unsafe{ &mut *self.inner.get() }
    }
}

impl WsClientWriter {

    /// Write payload
    #[inline]
    fn write(&mut self, mut data: Binary) {
        if !self.as_mut().closed {
            let _ = self.as_mut().tx.unbounded_send(data.take());
        } else {
            warn!("Trying to write to disconnected response");
        }
    }

    /// Send text frame
    #[inline]
    pub fn text<T: Into<String>>(&mut self, text: T) {
        self.write(Frame::message(text.into(), OpCode::Text, true, true));
    }

    /// Send binary frame
    #[inline]
    pub fn binary<B: Into<Binary>>(&mut self, data: B) {
        self.write(Frame::message(data, OpCode::Binary, true, true));
    }

    /// Send ping frame
    #[inline]
    pub fn ping(&mut self, message: &str) {
        self.write(Frame::message(Vec::from(message), OpCode::Ping, true, true));
    }

    /// Send pong frame
    #[inline]
    pub fn pong(&mut self, message: &str) {
        self.write(Frame::message(Vec::from(message), OpCode::Pong, true, true));
    }

    /// Send close frame
    #[inline]
    pub fn close(&mut self, code: CloseCode, reason: &str) {
        self.write(Frame::close(code, reason, true));
    }
}
<|endoftext|>


<commit_before>use engine::EngineData;
use image_convert::{image_to_surface, frame_to_surface};
use scene::SceneName;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::pixels::{Color, PixelFormatEnum};
use sdl2::rect::{Rect, Point};
use sdl2::render::{WindowCanvas, Texture, TextureCreator};
use sdl2::surface::Surface;
use sdl2::video::WindowContext;
use sdl2_engine_helpers::scene::{Scene, BoxedScene, SceneChangeEvent};
use std::fs::File;
use std::io::Result;
use std::path::Path;

use uorustlibs::anim::{AnimReader, AnimGroup,};

pub struct AnimScene<'a> {
    reader: Result<AnimReader<File>>,
    index: u32,
    texture_creator: &'a TextureCreator<WindowContext>,
    textures: Vec<Texture<'a>>,
    exiting: bool,
    current_frame: usize,
}

impl<'a> AnimScene<'a> {
    pub fn new<'b>(engine_data: &mut EngineData<'b>, texture_creator: &'a TextureCreator<WindowContext>) -> BoxedScene<'a, Event, SceneName, EngineData<'b>> {
        let reader = AnimReader::new(&Path::new("./assets/anim.idx"), &Path::new("./assets/Anim.mul"));  //FIXME: Multiple anim muls!
        let mut scene = Box::new(AnimScene {
            reader: reader,
            index: 110,
            textures: vec![],
            exiting: false,
            texture_creator,
            current_frame: 0,
        });
        scene.create_slice(engine_data);

        scene
    }

    fn create_slice(&mut self, engine_data: &mut EngineData) {
        let offset = 100;
        let anim = match self.reader {
            Ok(ref mut reader) => {
                reader.read(self.index).or_else(|_| Err("Invalid anim"))
            },
            _ => Err("No reader")
        };
        match anim {
            Ok(anim) => {
                self.textures = anim.to_frames().enumerate().map(|(idx, frame)| {
                    let mut dest = Surface::new(1024, 768, PixelFormatEnum::RGBA8888).unwrap();
                    dest.fill_rect(None, Color::RGB(0, 0, 0)).unwrap();
                    let surface = frame_to_surface(&frame);
                    surface.blit(None, &mut dest, Some(Rect::new(0, 0, surface.width(), surface.height()))).expect("Could not blit surface");

                    engine_data.text_renderer.draw_text(&mut dest, &Point::new(9, offset as i32 + surface.height() as i32 + 16), &format!("{}", self.index));
                    engine_data.text_renderer.draw_text(&mut dest, &Point::new(9, offset as i32 + surface.height() as i32 + 32), &format!("{} / {}", idx, anim.frame_count));
                    self.texture_creator.create_texture_from_surface(&dest).unwrap()
                }).collect::<_>();
            },
            Err(e) => {
                let mut dest = Surface::new(1024, 768, PixelFormatEnum::RGBA8888).unwrap();
                dest.fill_rect(None, Color::RGB(0, 0, 0)).unwrap();
                engine_data.text_renderer.draw_text(&mut dest, &Point::new(0, 0), e);
                self.textures = vec![self.texture_creator.create_texture_from_surface(&dest).unwrap()];
            }
        }
        self.current_frame = 0;
    }
}

impl<'a, 'b> Scene<Event, SceneName, EngineData<'b>> for AnimScene<'a> {
    fn render(&self, renderer: &mut WindowCanvas, _engine_data: &EngineData, _tick: u64) {
        renderer.clear();
        if self.textures.len() > 0 {
            renderer.copy(&self.textures[self.current_frame], None, None).unwrap();
        }
        renderer.present();
    }

    fn handle_event(&mut self, event: &Event, engine_data: &mut EngineData, _tick: u64) {
        match *event {
            Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                self.exiting = true;
            },
            Event::KeyDown { keycode: Some(Keycode::Left), .. } => {
                if self.index > 0 {
                    self.index -= 1;
                    self.create_slice(engine_data);
                }
            },
            Event::KeyDown { keycode: Some(Keycode::Right), .. } => {
                self.index += 1;
                self.create_slice(engine_data);
            },
             _ => ()
        }
    }

    fn think(&mut self, _engine_data: &mut EngineData, tick: u64) -> Option<SceneChangeEvent<SceneName>> {
        if self.exiting {
            return Some(SceneChangeEvent::PopScene);
        }

        self.current_frame += 1;
        if self.current_frame >= self.textures.len() {
            self.current_frame = 0;
        }

        None
    }
}
<commit_msg>Tabbing through anim<commit_after>use engine::EngineData;
use image_convert::{image_to_surface, frame_to_surface};
use scene::SceneName;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::pixels::{Color, PixelFormatEnum};
use sdl2::rect::{Rect, Point};
use sdl2::render::{WindowCanvas, Texture, TextureCreator};
use sdl2::surface::Surface;
use sdl2::video::WindowContext;
use sdl2_engine_helpers::scene::{Scene, BoxedScene, SceneChangeEvent};
use std::fs::File;
use std::io::Result;
use std::path::Path;

use uorustlibs::anim::{AnimReader, AnimGroup,};

pub struct AnimScene<'a> {
    reader: Result<AnimReader<File>>,
    index: u32,
    texture_creator: &'a TextureCreator<WindowContext>,
    textures: Vec<Texture<'a>>,
    exiting: bool,
    current_frame: usize,
}

impl<'a> AnimScene<'a> {
    pub fn new<'b>(engine_data: &mut EngineData<'b>, texture_creator: &'a TextureCreator<WindowContext>) -> BoxedScene<'a, Event, SceneName, EngineData<'b>> {
        let reader = AnimReader::new(&Path::new("./assets/anim.idx"), &Path::new("./assets/Anim.mul"));  //FIXME: Multiple anim muls!
        let mut scene = Box::new(AnimScene {
            reader: reader,
            index: 110,
            textures: vec![],
            exiting: false,
            texture_creator,
            current_frame: 0,
        });
        scene.create_slice(engine_data);

        scene
    }

    fn create_slice(&mut self, engine_data: &mut EngineData) {
        let offset = 100;
        let anim = match self.reader {
            Ok(ref mut reader) => {
                reader.read(self.index).or_else(|_| Err("Invalid anim"))
            },
            _ => Err("No reader")
        };
        match anim {
            Ok(anim) => {
                self.textures = anim.to_frames().enumerate().map(|(idx, frame)| {
                    let mut dest = Surface::new(1024, 768, PixelFormatEnum::RGBA8888).unwrap();
                    dest.fill_rect(None, Color::RGB(0, 0, 0)).unwrap();
                    let surface = frame_to_surface(&frame);
                    surface.blit(None, &mut dest, Some(Rect::new(0, 0, surface.width(), surface.height()))).expect("Could not blit surface");

                    engine_data.text_renderer.draw_text(&mut dest, &Point::new(9, offset as i32 + surface.height() as i32 + 16), &format!("{}", self.index));
                    engine_data.text_renderer.draw_text(&mut dest, &Point::new(9, offset as i32 + surface.height() as i32 + 32), &format!("{} / {}", idx, anim.frame_count));
                    self.texture_creator.create_texture_from_surface(&dest).unwrap()
                }).collect::<_>();
            },
            Err(e) => {
                let mut dest = Surface::new(1024, 768, PixelFormatEnum::RGBA8888).unwrap();
                dest.fill_rect(None, Color::RGB(0, 0, 0)).unwrap();
                engine_data.text_renderer.draw_text(&mut dest, &Point::new(0, 0), e);
                self.textures = vec![self.texture_creator.create_texture_from_surface(&dest).unwrap()];
            }
        }
        self.current_frame = 0;
    }
}

impl<'a, 'b> Scene<Event, SceneName, EngineData<'b>> for AnimScene<'a> {
    fn render(&self, renderer: &mut WindowCanvas, _engine_data: &EngineData, _tick: u64) {
        renderer.clear();
        if self.textures.len() > 0 {
            renderer.copy(&self.textures[self.current_frame], None, None).unwrap();
        }
        renderer.present();
    }

    fn handle_event(&mut self, event: &Event, engine_data: &mut EngineData, _tick: u64) {
        match *event {
            Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                self.exiting = true;
            },
            Event::KeyDown { keycode: Some(Keycode::Left), .. } => {
                if self.index > 0 {
                    self.index -= 1;
                    self.create_slice(engine_data);
                }
            },
            Event::KeyDown { keycode: Some(Keycode::Right), .. } => {
                self.index += 1;
                self.create_slice(engine_data);
            },
            Event::KeyDown { keycode: Some(Keycode::Comma), .. } => {
                if self.index >= 10 {
                    self.index -= 10;
                    self.create_slice(engine_data);
                }
            },
            Event::KeyDown { keycode: Some(Keycode::Period), .. } => {
                self.index += 10;
                self.create_slice(engine_data);
            },
             _ => ()
        }
    }

    fn think(&mut self, _engine_data: &mut EngineData, tick: u64) -> Option<SceneChangeEvent<SceneName>> {
        if self.exiting {
            return Some(SceneChangeEvent::PopScene);
        }

        if tick % 2 == 0 {
            self.current_frame += 1;
            if self.current_frame >= self.textures.len() {
                self.current_frame = 0;
            }
        }

        None
    }
}
<|endoftext|>


<commit_before>#![feature(alloc)]
#![feature(const_fn)]
#![feature(heap_api)]
#![feature(libc)]
#![feature(raw)]
extern crate alloc;
#[macro_use] extern crate itertools;
extern crate libc;
extern crate rand;
extern crate rustc_serialize;
extern crate uuid;

extern crate util;

//pub mod dataset;
pub mod err;
pub mod func;
pub mod input;
pub mod mm;
pub mod page;
pub mod plugin;
pub mod session;
pub mod str;
pub mod types;
pub mod platform;

mod memtable;
mod random_table;

pub mod storage {
  pub use memtable::*;
	pub use random_table::*;
}<commit_msg>Enabled common::dataset.<commit_after>#![feature(alloc)]
#![feature(const_fn)]
#![feature(heap_api)]
#![feature(libc)]
#![feature(raw)]
extern crate alloc;
#[macro_use] extern crate itertools;
extern crate libc;
extern crate rand;
extern crate rustc_serialize;
extern crate uuid;

extern crate util;

pub mod dataset;
pub mod err;
pub mod func;
pub mod input;
pub mod mm;
pub mod page;
pub mod plugin;
pub mod session;
pub mod str;
pub mod types;
pub mod platform;

mod memtable;
mod random_table;

pub mod storage {
  pub use memtable::*;
	pub use random_table::*;
}<|endoftext|>


<commit_before>use message::{Message, PatternId};
use MiliSec;
use state::State;

#[derive(Clone, Debug)]
pub struct Conditions {
    pub timeout: MiliSec,
    pub renew_timeout: Option<MiliSec>,
    pub first_opens: Option<bool>,
    pub last_closes: Option<bool>,
    pub max_size: Option<usize>,
    pub patterns: Vec<PatternId>
}

impl Conditions {
    fn new(timeout: MiliSec) -> Conditions {
        Conditions {
            timeout: timeout,
            renew_timeout: None,
            first_opens: None,
            last_closes: None,
            max_size: None,
            patterns: Vec::new()
        }
    }

    pub fn is_opening(&self, message: &Message) -> bool {
        self.first_opens.map_or(true, |first_message_opens_the_context| {
            if first_message_opens_the_context {
                self.patterns.first().unwrap() == message.uuid()
            } else {
                true
            }
        })
    }

    pub fn is_closing(&self, state: &State) -> bool {
        self.is_max_size_reached(state) || self.is_closing_message(state) || self.is_any_timer_expired(state)
    }

    fn is_max_size_reached(&self, state: &State) -> bool {
        self.max_size.map_or(false, |max_size| state.messages().len() >= max_size)
    }

    fn is_closing_message(&self, state: &State) -> bool {
        self.last_closes.map_or(false, |last_message_closes_the_context| {
            if last_message_closes_the_context {
                self.patterns.last().unwrap() == state.messages().last().unwrap().uuid()
            } else {
                false
            }
        })
    }

    fn is_any_timer_expired(&self, state: &State) -> bool {
        self.is_timeout_expired(state) || self.is_renew_timeout_expired(state)
    }

    fn is_timeout_expired(&self, state: &State) -> bool {
        state.elapsed_time() >= self.timeout
    }

    fn is_renew_timeout_expired(&self, state: &State) -> bool {
        self.renew_timeout.map_or(false, |renew_timeout| {
            state.elapsed_time_since_last_message() >= renew_timeout
        })
    }
}

pub struct Builder {
    conditions: Conditions
}

impl Builder {
    pub fn new(timeout: MiliSec) -> Builder {
        Builder{
            conditions: Conditions::new(timeout)
        }
    }

    pub fn renew_timeout(&mut self, timeout: MiliSec) -> &mut Builder {
        self.conditions.renew_timeout = Some(timeout);
        self
    }

    pub fn first_opens(&mut self, first_opens: bool) -> &mut Builder {
        self.conditions.first_opens = Some(first_opens);
        self
    }

    pub fn last_closes(&mut self, last_closes: bool) -> &mut Builder {
        self.conditions.last_closes = Some(last_closes);
        self
    }
    pub fn max_size(&mut self, max_size: usize) -> &mut Builder {
        self.conditions.max_size = Some(max_size);
        self
    }

    pub fn patterns(&mut self, patterns: Vec<PatternId>) -> &mut Builder {
        self.conditions.patterns = patterns;
        self
    }

    pub fn build(&mut self) -> Conditions {
        self.conditions.clone()
    }
}

#[cfg(test)]
mod test {
    use std::rc::Rc;

    use message;
    use message::{PatternId};
    use state::State;
    use super::Builder;

    #[test]
    fn test_given_condition_when_an_opening_message_is_received_then_the_state_becomes_opened() {
        let timeout = 100;
        let msg_id1 = "11eaf6f8-0640-460f-aee2-a72d2f2ab258".to_string();
        let msg_id2 = "21eaf6f8-0640-460f-aee2-a72d2f2ab258".to_string();
        let patterns = vec![
            PatternId::Uuid(msg_id1.clone()),
        ];
        let condition = Builder::new(timeout).patterns(patterns).first_opens(true).build();
        let msg_which_should_not_be_ignored = message::Builder::new(&msg_id1).build();
        let msg_which_should_be_ignored = message::Builder::new(&msg_id2).build();
        assert_false!(condition.is_opening(&msg_which_should_be_ignored));
        assert_true!(condition.is_opening(&msg_which_should_not_be_ignored));
    }

    #[test]
    fn test_given_condition_when_a_closing_message_is_received_then_the_state_becomes_closed() {
        let timeout = 100;
        let msg_id1 = "11eaf6f8-0640-460f-aee2-a72d2f2ab258".to_string();
        let msg_id2 = "21eaf6f8-0640-460f-aee2-a72d2f2ab258".to_string();
        let patterns = vec![
            PatternId::Uuid(msg_id1.clone()),
            PatternId::Uuid(msg_id2.clone()),
        ];
        let mut state = State::new();
        let condition = Builder::new(timeout).patterns(patterns).last_closes(true).build();
        let msg_1 = message::Builder::new(&msg_id1).build();
        let msg_closing = Rc::new(message::Builder::new(&msg_id2).build());
        assert_true!(condition.is_opening(&msg_1));
        state.open();
        state.add_message(msg_closing);
        assert_true!(condition.is_closing(&mut state));
    }
}
<commit_msg>Conditions: refactor is_opening()<commit_after>use message::{Message, PatternId};
use MiliSec;
use state::State;

const FIRST_OPENS_DEFAULT: bool = false;

#[derive(Clone, Debug)]
pub struct Conditions {
    pub timeout: MiliSec,
    pub renew_timeout: Option<MiliSec>,
    pub first_opens: Option<bool>,
    pub last_closes: Option<bool>,
    pub max_size: Option<usize>,
    pub patterns: Vec<PatternId>
}

impl Conditions {
    fn new(timeout: MiliSec) -> Conditions {
        Conditions {
            timeout: timeout,
            renew_timeout: None,
            first_opens: None,
            last_closes: None,
            max_size: None,
            patterns: Vec::new()
        }
    }

    pub fn is_opening(&self, message: &Message) -> bool {
        if self.first_opens.unwrap_or(FIRST_OPENS_DEFAULT) {
            self.patterns.first().unwrap() == message.uuid()
        } else {
            true
        }
    }

    pub fn is_closing(&self, state: &State) -> bool {
        self.is_max_size_reached(state) || self.is_closing_message(state) || self.is_any_timer_expired(state)
    }

    fn is_max_size_reached(&self, state: &State) -> bool {
        self.max_size.map_or(false, |max_size| state.messages().len() >= max_size)
    }

    fn is_closing_message(&self, state: &State) -> bool {
        self.last_closes.map_or(false, |last_message_closes_the_context| {
            if last_message_closes_the_context {
                self.patterns.last().unwrap() == state.messages().last().unwrap().uuid()
            } else {
                false
            }
        })
    }

    fn is_any_timer_expired(&self, state: &State) -> bool {
        self.is_timeout_expired(state) || self.is_renew_timeout_expired(state)
    }

    fn is_timeout_expired(&self, state: &State) -> bool {
        state.elapsed_time() >= self.timeout
    }

    fn is_renew_timeout_expired(&self, state: &State) -> bool {
        self.renew_timeout.map_or(false, |renew_timeout| {
            state.elapsed_time_since_last_message() >= renew_timeout
        })
    }
}

pub struct Builder {
    conditions: Conditions
}

impl Builder {
    pub fn new(timeout: MiliSec) -> Builder {
        Builder{
            conditions: Conditions::new(timeout)
        }
    }

    pub fn renew_timeout(&mut self, timeout: MiliSec) -> &mut Builder {
        self.conditions.renew_timeout = Some(timeout);
        self
    }

    pub fn first_opens(&mut self, first_opens: bool) -> &mut Builder {
        self.conditions.first_opens = Some(first_opens);
        self
    }

    pub fn last_closes(&mut self, last_closes: bool) -> &mut Builder {
        self.conditions.last_closes = Some(last_closes);
        self
    }
    pub fn max_size(&mut self, max_size: usize) -> &mut Builder {
        self.conditions.max_size = Some(max_size);
        self
    }

    pub fn patterns(&mut self, patterns: Vec<PatternId>) -> &mut Builder {
        self.conditions.patterns = patterns;
        self
    }

    pub fn build(&mut self) -> Conditions {
        self.conditions.clone()
    }
}

#[cfg(test)]
mod test {
    use std::rc::Rc;

    use message;
    use message::{PatternId};
    use state::State;
    use super::Builder;

    #[test]
    fn test_given_condition_when_an_opening_message_is_received_then_the_state_becomes_opened() {
        let timeout = 100;
        let msg_id1 = "11eaf6f8-0640-460f-aee2-a72d2f2ab258".to_string();
        let msg_id2 = "21eaf6f8-0640-460f-aee2-a72d2f2ab258".to_string();
        let patterns = vec![
            PatternId::Uuid(msg_id1.clone()),
        ];
        let condition = Builder::new(timeout).patterns(patterns).first_opens(true).build();
        let msg_which_should_not_be_ignored = message::Builder::new(&msg_id1).build();
        let msg_which_should_be_ignored = message::Builder::new(&msg_id2).build();
        assert_false!(condition.is_opening(&msg_which_should_be_ignored));
        assert_true!(condition.is_opening(&msg_which_should_not_be_ignored));
    }

    #[test]
    fn test_given_condition_when_a_closing_message_is_received_then_the_state_becomes_closed() {
        let timeout = 100;
        let msg_id1 = "11eaf6f8-0640-460f-aee2-a72d2f2ab258".to_string();
        let msg_id2 = "21eaf6f8-0640-460f-aee2-a72d2f2ab258".to_string();
        let patterns = vec![
            PatternId::Uuid(msg_id1.clone()),
            PatternId::Uuid(msg_id2.clone()),
        ];
        let mut state = State::new();
        let condition = Builder::new(timeout).patterns(patterns).last_closes(true).build();
        let msg_1 = message::Builder::new(&msg_id1).build();
        let msg_closing = Rc::new(message::Builder::new(&msg_id2).build());
        assert_true!(condition.is_opening(&msg_1));
        state.open();
        state.add_message(msg_closing);
        assert_true!(condition.is_closing(&mut state));
    }
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

use std::io::{Read, Write};

use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};

use super::{ReadError, WriteError};

/// A Fleetspeak client communication message.
///
/// This structure represents incoming or outgoing message objects delivered by
/// Fleetspeak. This is a simplified version of the underlying Protocol Buffers
/// message that exposes too much irrelevant fields and makes the protocol easy
/// to misuse.
pub struct Message {
    /// A name of the server-side service that sent or should receive the data.
    pub service: String,
    /// An optional message type that can be used by the server-side service.
    pub kind: Option<String>,
    /// The data to sent to the specified service.
    pub data: Vec<u8>,
}

/// Executes the handshake procedure.
///
/// The handshake procedure consists of writing and reading magic numbers from
/// the connection buffers. This validates that the communication between the
/// Fleetspeak client and the service daemon is working as expected.
///
/// All Fleetspeak connection buffers are required to perform the handshake
/// before they became usable for sending and receiving messages.
pub fn handshake<R, W>(input: &mut R, output: &mut W) -> std::io::Result<()>
where
    R: Read,
    W: Write,
{
    write_magic(output)?;
    output.flush()?;
    read_magic(input)?;

    Ok(())
}

/// Sends a heartbeat information through this connection.
///
/// All client services should heartbeat from time to time. Otherwise, from
/// the Fleetspeak perspective, the service is unresponsive and should be
/// restarted.
///
/// The exact frequency of the required heartbeat is defined in the service
/// configuration file.
pub fn heartbeat<W>(output: &mut W) -> Result<(), WriteError>
where
    W: Write,
{
    let mut msg = fleetspeak_proto::common::Message::new();
    msg.set_message_type(String::from("Heartbeat"));
    msg.mut_destination().set_service_name(String::from("system"));

    write_raw(output, msg)
}

/// Sends the startup information through this connection.
///
/// All clients are required to send this information on startup. If the
/// client does not receive this information quickly enough, the service
/// will be killed.
///
/// The `version` string should contain a self-reported version of the
/// service. This data is used primarily for statistics.
pub fn startup<W>(output: &mut W, version: &str) -> Result<(), WriteError>
where
    W: Write,
{
    use protobuf::Message as _;

    let mut data = fleetspeak_proto::channel::StartupData::new();
    data.set_pid(i64::from(std::process::id()));
    data.set_version(String::from(version));

    let mut msg = fleetspeak_proto::common::Message::new();
    msg.set_message_type(String::from("StartupData"));
    msg.mut_destination().set_service_name(String::from("system"));
    msg.mut_data().set_type_url(type_url(&data));
    msg.mut_data().set_value(data.write_to_bytes()?);

    write_raw(output, msg)
}

/// Sends the message to the Fleetspeak server through the output buffer.
///
/// The message is sent to the server-side `service` and tagged with the
/// `kind` type. Note that this message type is rather irrelevant for
/// Fleetspeak and it is up to the service what to do with this information.
pub fn send<W>(output: &mut W, message: Message) -> Result<(), WriteError>
where
    W: Write,
{
    let mut proto = fleetspeak_proto::common::Message::new();
    proto.set_message_type(message.kind.unwrap_or_else(String::new));
    proto.mut_destination().set_service_name(message.service);
    // TODO: Consider a way of providing the type URL of the data being sent.
    proto.mut_data().set_value(message.data);

    write_raw(output, proto)
}

/// Receives the message from the Fleetspeak server through the input buffer.
///
/// This function will block until there is a message to be read in the
/// input. Errors are reported in case of any I/O failure or if the read
/// message was malformed (e.g. it cannot be parsed to the expected type).
pub fn receive<R>(input: &mut R) -> Result<Message, ReadError>
where
    R: Read,
{
    let mut msg = read_raw(input)?;

    // While missing source address might not be consider a critical error
    // in most cases, for our own sanity we just disregard such messages.
    // Allowing such behaviour might indicate a more severe problem with
    // Fleetspeak and ignoring it simply masks the issue. This might be
    // reconsidered in the future.
    let service = if msg.has_source() {
        msg.take_source().take_service_name()
    } else {
        return Err(ReadError::malformed("missing source address"))
    };

    // It is not clear what is the best approach here. If there is no data,
    // should we error-out or return a default value? For the time being we
    // stick to the default approach, but if this proves to be not working
    // well in practice, it might be reconsidered.
    let mut data = if msg.has_data() {
        msg.take_data()
    } else {
        log::warn!(target: "fleetspeak", "empty message from '{}'", service);
        Default::default()
    };

    Ok(Message {
        service: service,
        kind: Some(msg.message_type),
        data: data.take_value(),
    })
}

/// Writes a raw Fleetspeak message to the output buffer.
///
/// This method does not perform any validation of the message being emitted
/// and assumes that all the required fields are present.
///
/// Note that this call will fail only if the message cannot be written to
/// the output or cannot be properly encoded but will succeed even if the
/// message is not what the server expects.
fn write_raw<W>(output: &mut W, msg: fleetspeak_proto::common::Message) -> Result<(), WriteError>
where
    W: Write,
{
    use protobuf::Message as _;

    output.write_u32::<LittleEndian>(msg.compute_size())?;
    msg.write_to_writer(output)?;
    write_magic(output)?;
    output.flush()?;

    Ok(())
}

/// Reads a raw Fleetspeeak message from the input buffer.
///
/// This function will block until there is a message to be read from the
/// input. It will fail in case of any I/O error or if the message cannot
/// be parsed as a Fleetspeak message.
fn read_raw<R>(input: &mut R) -> Result<fleetspeak_proto::common::Message, ReadError>
where
    R: Read,
{
    let len = input.read_u32::<LittleEndian>()? as usize;
    let mut buf = vec!(0; len);

    input.read_exact(&mut buf[..])?;
    read_magic(input)?;

    // TODO: This can be optimized with `protobuf::read_from_bytes`.
    Ok(protobuf::parse_from_bytes(&buf[..])?)
}

/// Writes the Fleetspeak magic to the output buffer.
fn write_magic<W>(output: &mut W) -> Result<(), WriteError>
where
    W: Write,
{
    output.write_u32::<LittleEndian>(MAGIC)?;

    Ok(())
}

/// Reads the Fleetspeak magic from the input buffer.
fn read_magic<R>(input: &mut R) -> Result<(), ReadError>
where
    R: Read,
{
    let magic = input.read_u32::<LittleEndian>()?;
    if magic != MAGIC {
        return Err(ReadError::Magic(magic));
    }

    Ok(())
}

const MAGIC: u32 = 0xf1ee1001;

/// Computes a type URL of the given Protocol Buffers message.
///
/// This function should probably be part of the `protobuf` package but for some
/// reason it is not and we have to implement it ourselves.
fn type_url<M: protobuf::Message>(message: &M) -> String {
    format!("{}/{}", TYPE_URL_PREFIX, message.descriptor().full_name())
}

const TYPE_URL_PREFIX: &'static str = "type.googleapis.com";

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

    #[test]
    fn handshake_good_magic() {
        let mut buf_in = [0; 1024];
        let mut buf_out = [0; 1024];

        let mut cur = Cursor::new(&mut buf_in[..]);
        assert!(cur.write_u32::<LittleEndian>(MAGIC).is_ok());

        let mut cur_in = Cursor::new(&mut buf_in[..]);
        let mut cur_out = Cursor::new(&mut buf_out[..]);
        assert!(handshake(&mut cur_in, &mut cur_out).is_ok());

        let mut cur = Cursor::new(&mut buf_out[..]);
        assert_eq!(cur.read_u32::<LittleEndian>().unwrap(), MAGIC);
    }

    #[test]
    fn handshake_bad_magic() {
        let mut buf_in = [0; 1024];
        let mut buf_out = [0; 1024];

        let mut cur = Cursor::new(&mut buf_in[..]);
        assert!(cur.write_u32::<LittleEndian>(0xf1ee1337).is_ok());

        let mut cur_in = Cursor::new(&mut buf_in[..]);
        let mut cur_out = Cursor::new(&mut buf_out[..]);
        assert!(handshake(&mut cur_in, &mut cur_out).is_err());
    }

    #[test]
    fn type_url_startup_data() {
        assert_eq! {
            type_url(&fleetspeak_proto::channel::StartupData::new()),
            "type.googleapis.com/fleetspeak.channel.StartupData"
        };
    }
}
<commit_msg>Use non-deprecated function for parsing messages.<commit_after>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

use std::io::{Read, Write};

use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};

use super::{ReadError, WriteError};

/// A Fleetspeak client communication message.
///
/// This structure represents incoming or outgoing message objects delivered by
/// Fleetspeak. This is a simplified version of the underlying Protocol Buffers
/// message that exposes too much irrelevant fields and makes the protocol easy
/// to misuse.
pub struct Message {
    /// A name of the server-side service that sent or should receive the data.
    pub service: String,
    /// An optional message type that can be used by the server-side service.
    pub kind: Option<String>,
    /// The data to sent to the specified service.
    pub data: Vec<u8>,
}

/// Executes the handshake procedure.
///
/// The handshake procedure consists of writing and reading magic numbers from
/// the connection buffers. This validates that the communication between the
/// Fleetspeak client and the service daemon is working as expected.
///
/// All Fleetspeak connection buffers are required to perform the handshake
/// before they became usable for sending and receiving messages.
pub fn handshake<R, W>(input: &mut R, output: &mut W) -> std::io::Result<()>
where
    R: Read,
    W: Write,
{
    write_magic(output)?;
    output.flush()?;
    read_magic(input)?;

    Ok(())
}

/// Sends a heartbeat information through this connection.
///
/// All client services should heartbeat from time to time. Otherwise, from
/// the Fleetspeak perspective, the service is unresponsive and should be
/// restarted.
///
/// The exact frequency of the required heartbeat is defined in the service
/// configuration file.
pub fn heartbeat<W>(output: &mut W) -> Result<(), WriteError>
where
    W: Write,
{
    let mut msg = fleetspeak_proto::common::Message::new();
    msg.set_message_type(String::from("Heartbeat"));
    msg.mut_destination().set_service_name(String::from("system"));

    write_raw(output, msg)
}

/// Sends the startup information through this connection.
///
/// All clients are required to send this information on startup. If the
/// client does not receive this information quickly enough, the service
/// will be killed.
///
/// The `version` string should contain a self-reported version of the
/// service. This data is used primarily for statistics.
pub fn startup<W>(output: &mut W, version: &str) -> Result<(), WriteError>
where
    W: Write,
{
    use protobuf::Message as _;

    let mut data = fleetspeak_proto::channel::StartupData::new();
    data.set_pid(i64::from(std::process::id()));
    data.set_version(String::from(version));

    let mut msg = fleetspeak_proto::common::Message::new();
    msg.set_message_type(String::from("StartupData"));
    msg.mut_destination().set_service_name(String::from("system"));
    msg.mut_data().set_type_url(type_url(&data));
    msg.mut_data().set_value(data.write_to_bytes()?);

    write_raw(output, msg)
}

/// Sends the message to the Fleetspeak server through the output buffer.
///
/// The message is sent to the server-side `service` and tagged with the
/// `kind` type. Note that this message type is rather irrelevant for
/// Fleetspeak and it is up to the service what to do with this information.
pub fn send<W>(output: &mut W, message: Message) -> Result<(), WriteError>
where
    W: Write,
{
    let mut proto = fleetspeak_proto::common::Message::new();
    proto.set_message_type(message.kind.unwrap_or_else(String::new));
    proto.mut_destination().set_service_name(message.service);
    // TODO: Consider a way of providing the type URL of the data being sent.
    proto.mut_data().set_value(message.data);

    write_raw(output, proto)
}

/// Receives the message from the Fleetspeak server through the input buffer.
///
/// This function will block until there is a message to be read in the
/// input. Errors are reported in case of any I/O failure or if the read
/// message was malformed (e.g. it cannot be parsed to the expected type).
pub fn receive<R>(input: &mut R) -> Result<Message, ReadError>
where
    R: Read,
{
    let mut msg = read_raw(input)?;

    // While missing source address might not be consider a critical error
    // in most cases, for our own sanity we just disregard such messages.
    // Allowing such behaviour might indicate a more severe problem with
    // Fleetspeak and ignoring it simply masks the issue. This might be
    // reconsidered in the future.
    let service = if msg.has_source() {
        msg.take_source().take_service_name()
    } else {
        return Err(ReadError::malformed("missing source address"))
    };

    // It is not clear what is the best approach here. If there is no data,
    // should we error-out or return a default value? For the time being we
    // stick to the default approach, but if this proves to be not working
    // well in practice, it might be reconsidered.
    let mut data = if msg.has_data() {
        msg.take_data()
    } else {
        log::warn!(target: "fleetspeak", "empty message from '{}'", service);
        Default::default()
    };

    Ok(Message {
        service: service,
        kind: Some(msg.message_type),
        data: data.take_value(),
    })
}

/// Writes a raw Fleetspeak message to the output buffer.
///
/// This method does not perform any validation of the message being emitted
/// and assumes that all the required fields are present.
///
/// Note that this call will fail only if the message cannot be written to
/// the output or cannot be properly encoded but will succeed even if the
/// message is not what the server expects.
fn write_raw<W>(output: &mut W, msg: fleetspeak_proto::common::Message) -> Result<(), WriteError>
where
    W: Write,
{
    use protobuf::Message as _;

    output.write_u32::<LittleEndian>(msg.compute_size())?;
    msg.write_to_writer(output)?;
    write_magic(output)?;
    output.flush()?;

    Ok(())
}

/// Reads a raw Fleetspeeak message from the input buffer.
///
/// This function will block until there is a message to be read from the
/// input. It will fail in case of any I/O error or if the message cannot
/// be parsed as a Fleetspeak message.
fn read_raw<R>(input: &mut R) -> Result<fleetspeak_proto::common::Message, ReadError>
where
    R: Read,
{
    let len = input.read_u32::<LittleEndian>()? as usize;
    let mut buf = vec!(0; len);

    input.read_exact(&mut buf[..])?;
    read_magic(input)?;

    Ok(protobuf::Message::parse_from_bytes(&buf[..])?)
}

/// Writes the Fleetspeak magic to the output buffer.
fn write_magic<W>(output: &mut W) -> Result<(), WriteError>
where
    W: Write,
{
    output.write_u32::<LittleEndian>(MAGIC)?;

    Ok(())
}

/// Reads the Fleetspeak magic from the input buffer.
fn read_magic<R>(input: &mut R) -> Result<(), ReadError>
where
    R: Read,
{
    let magic = input.read_u32::<LittleEndian>()?;
    if magic != MAGIC {
        return Err(ReadError::Magic(magic));
    }

    Ok(())
}

const MAGIC: u32 = 0xf1ee1001;

/// Computes a type URL of the given Protocol Buffers message.
///
/// This function should probably be part of the `protobuf` package but for some
/// reason it is not and we have to implement it ourselves.
fn type_url<M: protobuf::Message>(message: &M) -> String {
    format!("{}/{}", TYPE_URL_PREFIX, message.descriptor().full_name())
}

const TYPE_URL_PREFIX: &'static str = "type.googleapis.com";

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

    #[test]
    fn handshake_good_magic() {
        let mut buf_in = [0; 1024];
        let mut buf_out = [0; 1024];

        let mut cur = Cursor::new(&mut buf_in[..]);
        assert!(cur.write_u32::<LittleEndian>(MAGIC).is_ok());

        let mut cur_in = Cursor::new(&mut buf_in[..]);
        let mut cur_out = Cursor::new(&mut buf_out[..]);
        assert!(handshake(&mut cur_in, &mut cur_out).is_ok());

        let mut cur = Cursor::new(&mut buf_out[..]);
        assert_eq!(cur.read_u32::<LittleEndian>().unwrap(), MAGIC);
    }

    #[test]
    fn handshake_bad_magic() {
        let mut buf_in = [0; 1024];
        let mut buf_out = [0; 1024];

        let mut cur = Cursor::new(&mut buf_in[..]);
        assert!(cur.write_u32::<LittleEndian>(0xf1ee1337).is_ok());

        let mut cur_in = Cursor::new(&mut buf_in[..]);
        let mut cur_out = Cursor::new(&mut buf_out[..]);
        assert!(handshake(&mut cur_in, &mut cur_out).is_err());
    }

    #[test]
    fn type_url_startup_data() {
        assert_eq! {
            type_url(&fleetspeak_proto::channel::StartupData::new()),
            "type.googleapis.com/fleetspeak.channel.StartupData"
        };
    }
}
<|endoftext|>


<commit_before><commit_msg>表示もっとみやすくしたい<commit_after><|endoftext|>


<commit_before>//! Xml Attributes module
//!
//! Provides an iterator over attributes key/value pairs
use error::{Error, Result};

/// Iterator over attributes key/value pairs
pub struct Attributes<'a> {
    bytes: &'a [u8],
    position: usize,
    was_error: bool,
}

impl<'a> Attributes<'a> {
    /// creates a new attribute from a buffer
    ///
    /// pos represents current position of the iterator
    /// (starts after start element name)
    pub fn new(buf: &'a [u8], pos: usize) -> Attributes<'a> {
        Attributes {
            bytes: buf,
            position: pos,
            was_error: false,
        }
    }
}

impl<'a> Iterator for Attributes<'a> {
    type Item = Result<(&'a [u8], &'a [u8])>;
    fn next(&mut self) -> Option<Self::Item> {

        if self.was_error { return None; }

        let len = self.bytes.len();
        let p = self.position;
        if len == p { return None; }

        let mut iter = self.bytes[p..].iter().cloned().enumerate();

        let start_key = {
            let mut found_space = false;
            let start: usize;
            loop {
                match iter.next() {
                    Some((_, b' '))
                        | Some((_, b'\r'))
                        | Some((_, b'\n'))
                        | Some((_, b'\t')) => if !found_space { found_space = true; },
                    Some((i, _)) => if found_space {
                        start = i;
                        break;
                    },
                    None => {
                        self.position = len;
                        return None;
                    }
                }
            }
            start
        };

        let mut has_equal = false;
        let mut end_key = None;
        let mut start_val = None;
        let mut end_val = None;
        loop {
            match iter.next() {
                Some((i, b' '))
                    | Some((i, b'\r'))
                    | Some((i, b'\n'))
                    | Some((i, b'\t')) => {
                    if end_key.is_none() { end_key = Some(i); }
                },
                Some((i, b'=')) => {
                    if has_equal {
                        self.was_error = true;
                        return Some(Err(Error::Malformed("Got 2 '=' tokens".to_owned())));
                    }
                    has_equal = true;
                    if end_key.is_none() {
                        end_key = Some(i);
                    }
                },
                Some((i, b'"')) => {
                    if !has_equal {
                        self.was_error = true;
                        return Some(Err(Error::Malformed("Unexpected quote before '='".to_owned())));
                    }
                    if start_val.is_none() {
                        start_val = Some(i + 1);
                    } else if end_val.is_none() {
                        end_val = Some(i);
                        break;
                    }
                },
                None => {
                    self.position = len;
                    return None;
                }
                Some((_, _)) => (),
            }
        }
        self.position += end_val.unwrap() + 1;

        Some(Ok((&self.bytes[(p + start_key)..(p + end_key.unwrap())],
           &self.bytes[(p + start_val.unwrap())..(p + end_val.unwrap())])))
    }
}
<commit_msg>enable ' for attribute parsing<commit_after>//! Xml Attributes module
//!
//! Provides an iterator over attributes key/value pairs
use error::{Error, Result};

/// Iterator over attributes key/value pairs
pub struct Attributes<'a> {
    bytes: &'a [u8],
    position: usize,
    was_error: bool,
}

impl<'a> Attributes<'a> {
    /// creates a new attribute from a buffer
    ///
    /// pos represents current position of the iterator
    /// (starts after start element name)
    pub fn new(buf: &'a [u8], pos: usize) -> Attributes<'a> {
        Attributes {
            bytes: buf,
            position: pos,
            was_error: false,
        }
    }
}

impl<'a> Iterator for Attributes<'a> {
    type Item = Result<(&'a [u8], &'a [u8])>;
    fn next(&mut self) -> Option<Self::Item> {

        if self.was_error { return None; }

        let len = self.bytes.len();
        let p = self.position;
        if len <= p { return None; }

        let mut iter = self.bytes[p..].iter().cloned().enumerate();

        let start_key = {
            let mut found_space = false;
            let start: usize;
            loop {
                match iter.next() {
                    Some((_, b' '))
                        | Some((_, b'\r'))
                        | Some((_, b'\n'))
                        | Some((_, b'\t')) => if !found_space { found_space = true; },
                    Some((i, _)) => if found_space {
                        start = i;
                        break;
                    },
                    None => {
                        self.position = len;
                        return None;
                    }
                }
            }
            start
        };

        let mut has_equal = false;
        let mut end_key = None;
        let mut start_val = None;
        let mut end_val = None;
        let mut quote = 0;
        loop {
            match iter.next() {
                Some((i, b' '))
                    | Some((i, b'\r'))
                    | Some((i, b'\n'))
                    | Some((i, b'\t')) => {
                    if end_key.is_none() { end_key = Some(i); }
                },
                Some((i, b'=')) => {
                    if has_equal {
                        self.was_error = true;
                        return Some(Err(Error::Malformed("Got 2 '=' tokens".to_owned())));
                    }
                    has_equal = true;
                    if end_key.is_none() {
                        end_key = Some(i);
                    }
                },
                Some((i, q @ b'"')) | Some((i, q @ b'\'')) => {
                    if !has_equal {
                        self.was_error = true;
                        return Some(Err(Error::Malformed("Unexpected quote before '='".to_owned())));
                    }
                    if start_val.is_none() {
                        start_val = Some(i + 1);
                        quote = q;
                    } else if quote == q && end_val.is_none() {
                        end_val = Some(i);
                        break;
                    }
                },
                None => {
                    self.position = len;
                    return None;
                }
                Some((_, _)) => (),
            }
        }
        self.position += end_val.unwrap() + 1;

        Some(Ok((&self.bytes[(p + start_key)..(p + end_key.unwrap())],
           &self.bytes[(p + start_val.unwrap())..(p + end_val.unwrap())])))
    }
}
<|endoftext|>


<commit_before>extern crate rustc_serialize;
extern crate jarvis;
extern crate docopt;
#[macro_use]
extern crate log;
extern crate env_logger;

use std::env;

mod bar;
mod backlight;
mod keylight;
mod help;

use jarvis::util::Error;
use jarvis::process::Process;

pub const USAGE: &'static str = "
Just A Rather Very Intelligent System

Usage:
    jarvis <command> [<args>...]
    jarvis [options]

Options:
    -h, --help      Display this message
    -v, --version   Print version info and exit

Commands:
    bar             Create a new bar
    backlight       Control screen backlight
    keylight        Control keyboard backlight

See 'jarvis help <command>' for more information on a specific command.
";

macro_rules! each_subcommand{ ($mac:ident) => ({
    $mac!(backlight);
    $mac!(bar);
    $mac!(keylight);
    $mac!(help);
}) }

#[derive(Debug, RustcDecodable)]
pub struct Args {
    arg_command: String,
    arg_args: Vec<String>,
}

fn main() {
    env_logger::init().unwrap();
    let process = Process::new(execute, USAGE).options_first(true);
    jarvis::execute(process);
}

pub fn execute(args: Args) -> Result<(), Error> {
    let argv = match &args.arg_command[..] {
        "" | "help" if args.arg_args.is_empty() => {
            let ref argv = ["jarvis", "-h"];
            let process = Process::new(execute, USAGE).argv(argv);
            jarvis::execute(process);
            return Ok(())
        },
        "help" if args.arg_args[0] == "-h" ||
                  args.arg_args[0] == "--help" => {
            vec!["jarvis".to_string(), "help".to_string(), "-h".to_string()]
        },
        "help" => {
            vec!["jarvis".to_string(), args.arg_args[0].clone(), "-h".to_string()]
        },
        _ => {
            env::args().collect()
        },
    };

    macro_rules! cmd{ ($name:ident) => (
        if argv[1] == stringify!($name) {
            let process = Process::new($name::execute, $name::USAGE).argv(argv);
            jarvis::execute(process);
            return Ok(())
        }
    ) }
    each_subcommand!(cmd);
    Err(Error::new("No such subcommand"))
}
<commit_msg>list commands<commit_after>extern crate rustc_serialize;
extern crate jarvis;
extern crate docopt;
#[macro_use]
extern crate log;
extern crate env_logger;

use std::env;

mod bar;
mod backlight;
mod keylight;
mod sound;
mod help;

use jarvis::util::Error;
use jarvis::process::Process;

pub const USAGE: &'static str = "
Just A Rather Very Intelligent System

Usage:
    jarvis <command> [<args>...]
    jarvis [options]

Options:
    -h, --help      Display this message
    -v, --version   Print version info and exit
    --list          List commands

Commands:
    bar             Create a new bar
    backlight       Control screen backlight
    keylight        Control keyboard backlight

See 'jarvis help <command>' for more information on a specific command.
";

macro_rules! each_subcommand{ ($mac:ident) => ({
    $mac!(backlight);
    $mac!(bar);
    $mac!(sound);
    $mac!(keylight);
    $mac!(help);
}) }

#[derive(Debug, RustcDecodable)]
pub struct Args {
    arg_command: String,
    arg_args: Vec<String>,
    flag_list: bool,
}

fn main() {
    env_logger::init().unwrap();
    let process = Process::new(execute, USAGE).options_first(true);
    jarvis::execute(process);
}

pub fn execute(args: Args) -> Result<(), Error> {
    if args.flag_list {
        println!("Commands:");
        macro_rules! print_command{ ($cmd:ident) => ({
            println!("    {}", stringify!($cmd));
        }) }
        each_subcommand!(print_command);
        return Ok(())
    }

    let argv = match &args.arg_command[..] {
        "" | "help" if args.arg_args.is_empty() => {
            let ref argv = ["jarvis", "-h"];
            let process = Process::new(execute, USAGE).argv(argv);
            jarvis::execute(process);
            return Ok(())
        },
        "help" if args.arg_args[0] == "-h" ||
                  args.arg_args[0] == "--help" => {
            vec!["jarvis".to_string(), "help".to_string(), "-h".to_string()]
        },
        "help" => {
            vec!["jarvis".to_string(), args.arg_args[0].clone(), "-h".to_string()]
        },
        _ => {
            env::args().collect()
        },
    };

    macro_rules! cmd{ ($name:ident) => (
        if argv[1] == stringify!($name) {
            let process = Process::new($name::execute, $name::USAGE).argv(argv);
            jarvis::execute(process);
            return Ok(())
        }
    ) }
    each_subcommand!(cmd);
    Err(Error::new("No such subcommand"))
}
<|endoftext|>


<commit_before>#![cfg(feature = "translate")]

extern crate rusoto_core;
extern crate rusoto_translate;

use rusoto_core::Region;
use rusoto_translate::{Translate, TranslateClient, TranslateTextRequest};

#[tokio::test]
async fn should_translate_to_german() {
    let client = TranslateClient::new(Region::UsEast1);
    let request = TranslateTextRequest {
        source_language_code: "en".to_owned(),
        target_language_code: "de".to_owned(),
        text: "good day".to_owned(),
        ..Default::default()
    };

    let result = client.translate_text(request).await.unwrap();
    assert_eq!("guten tag", result.translated_text.to_lowercase());
}
<commit_msg>Fix translate integ test<commit_after>#![cfg(feature = "translate")]

extern crate rusoto_core;
extern crate rusoto_translate;

use rusoto_core::Region;
use rusoto_translate::{Translate, TranslateClient, TranslateTextRequest};

#[tokio::test]
async fn should_translate() {
    let client = TranslateClient::new(Region::UsEast1);
    let request = TranslateTextRequest {
        source_language_code: "en".to_owned(),
        target_language_code: "en".to_owned(),
        text: "good day".to_owned(),
        ..Default::default()
    };

    let result = client.translate_text(request).await.unwrap();
    assert_eq!("good day", result.translated_text.to_lowercase());
}
<|endoftext|>


<commit_before>use std::path::Path;
use sdl2::{self, INIT_VIDEO};
use sdl2::video::{Window, WindowPos, OPENGL};
use sdl2::render::{Renderer, RenderDriverIndex, ACCELERATED};
use sdl2_image::{self, LoadTexture, INIT_PNG, INIT_JPG};
use sdl2::event::Event;
use sdl2::keycode::KeyCode;

pub fn main(png: &Path) {

    let context = sdl2::init(INIT_VIDEO).unwrap();
    sdl2_image::init(INIT_PNG | INIT_JPG);

    let window = Window::new(
          &context,
          "rust-sdl2 demo: Video",
          WindowPos::PosCentered,
          WindowPos::PosCentered,
          800,
          600,
          OPENGL).unwrap();

    let renderer = Renderer::from_window(
          window,
          RenderDriverIndex::Auto,
          ACCELERATED).unwrap();

    let mut texture = renderer.load_texture(png).unwrap();

    // Draws and shows the loaded texture.
    let mut drawer = renderer.drawer();
    drawer.copy(&mut texture, None, None);
    drawer.present();

    let mut event_pump = context.event_pump();
    'mainloop: loop {
        for event in event_pump.poll_iter() {
            match event {
                Event::Quit{..} |
                Event::KeyDown {keycode: KeyCode::Escape, ..} =>
                    break 'mainloop,
                _ => {}
            }
        }
    }

    sdl2_image::quit();
}
<commit_msg>change renderer to be mutable<commit_after>use std::path::Path;
use sdl2::{self, INIT_VIDEO};
use sdl2::video::{Window, WindowPos, OPENGL};
use sdl2::render::{Renderer, RenderDriverIndex, ACCELERATED};
use sdl2_image::{self, LoadTexture, INIT_PNG, INIT_JPG};
use sdl2::event::Event;
use sdl2::keycode::KeyCode;

pub fn main(png: &Path) {

    let context = sdl2::init(INIT_VIDEO).unwrap();
    sdl2_image::init(INIT_PNG | INIT_JPG);

    let window = Window::new(
          &context,
          "rust-sdl2 demo: Video",
          WindowPos::PosCentered,
          WindowPos::PosCentered,
          800,
          600,
          OPENGL).unwrap();

    let mut renderer = Renderer::from_window(
          window,
          RenderDriverIndex::Auto,
          ACCELERATED).unwrap();

    let mut texture = renderer.load_texture(png).unwrap();

    // Draws and shows the loaded texture.
    let mut drawer = renderer.drawer();
    drawer.copy(&mut texture, None, None);
    drawer.present();

    let mut event_pump = context.event_pump();
    'mainloop: loop {
        for event in event_pump.poll_iter() {
            match event {
                Event::Quit{..} |
                Event::KeyDown {keycode: KeyCode::Escape, ..} =>
                    break 'mainloop,
                _ => {}
            }
        }
    }

    sdl2_image::quit();
}
<|endoftext|>