<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use std::rc::Rc;
use std::cell::RefCell;
use std::ops::{DerefMut, Deref};
use mio::util::Slab;
use mio::Socket;
use {EventPort, Promise, PromiseFulfiller, Result, new_promise_and_fulfiller};
use private::{with_current_event_loop};

pub trait AsyncRead {
    fn read<T>(self: Self, buf: T, min_bytes: usize) -> Promise<(Self, T, usize)>
        where T: DerefMut<Target=[u8]>;
    fn try_read<T>(self: Self, buf: T, min_bytes: usize) -> Promise<(Self, T, usize)>
        where T: DerefMut<Target=[u8]>;
}

pub trait AsyncWrite {
    fn write<T>(self: Self, buf: T) -> Promise<(Self, T)>
        where T: Deref<Target=[u8]>;
}

pub struct Slice<T> where T: Deref<Target=[u8]> {
    pub buf: T,
    pub end: usize,
}

impl <T> Slice<T> where T: Deref<Target=[u8]> {
    pub fn new(buf: T, end: usize) -> Slice<T> {
        Slice { buf: buf, end: end }
    }
}

impl <T> Deref for Slice<T> where T: Deref<Target=[u8]> {
    type Target=[u8];
    fn deref<'a>(&'a self) -> &'a [u8] {
        &self.buf[0..self.end]
    }
}

#[derive(Copy, Clone)]
pub struct NetworkAddress {
    address: ::std::net::SocketAddr,
}

impl NetworkAddress {
    pub fn new(address: ::std::net::SocketAddr) -> NetworkAddress {
        NetworkAddress { address: address }
    }

    pub fn listen(self) -> Result<ConnectionReceiver> {
        let socket = try!(::mio::tcp::TcpSocket::v4());
        try!(socket.set_reuseaddr(true));
        try!(socket.bind(&self.address));
        let token = FdObserver::new();
        Ok(ConnectionReceiver { listener: try!(socket.listen(256)),
                                token: token })
    }

    pub fn connect(self) -> Promise<(AsyncOutputStream, AsyncInputStream)> {
        let socket = ::mio::tcp::TcpSocket::v4().unwrap();
        let token = FdObserver::new();
        let (stream, _) = socket.connect(&self.address).unwrap();
        with_current_event_loop(move |event_loop| {
            event_loop.event_port.borrow_mut().reactor.register_opt(&stream, token,
                                                                    ::mio::Interest::writable(),
                                                                    ::mio::PollOpt::edge()).unwrap();
            let promise =
                event_loop.event_port.borrow_mut().handler.observers[token].when_becomes_writable();
            return promise.map(move |()| {
                // TODO check for error.

                return with_current_event_loop(move |event_loop| {
                    try!(event_loop.event_port.borrow_mut().reactor.reregister(
                        &stream, token,
                        ::mio::Interest::writable() | ::mio::Interest::readable(),
                        ::mio::PollOpt::edge()));
                    return Ok(AsyncIo::new(stream, token));
                });

            });
        })
    }
}

pub struct ConnectionReceiver {
    listener: ::mio::tcp::TcpListener,
    token: ::mio::Token,
}

impl Drop for ConnectionReceiver {
    fn drop(&mut self) {
        // deregister the token
    }
}

impl ConnectionReceiver {
    pub fn accept(self) -> Promise<(ConnectionReceiver, (AsyncOutputStream, AsyncInputStream))> {
        with_current_event_loop(move |event_loop| {
            let promise =
                event_loop.event_port.borrow_mut().handler.observers[self.token].when_becomes_readable();
            event_loop.event_port.borrow_mut().reactor.register_opt(&self.listener, self.token,
                                                                    ::mio::Interest::readable(),
                                                                    ::mio::PollOpt::edge() |
                                                                    ::mio::PollOpt::oneshot()).unwrap();
            return promise.map(move |()| {
                let stream = try!(self.listener.accept()).unwrap();
                let token = FdObserver::new();

                return with_current_event_loop(move |event_loop| {
                    try!(event_loop.event_port.borrow_mut().reactor.register_opt(
                        &stream, token,
                        ::mio::Interest::writable() | ::mio::Interest::readable(),
                        ::mio::PollOpt::edge()));
                    return Ok((self, AsyncIo::new(stream, token)));
                });
            });
        })
    }
}

pub struct AsyncInputStream {
    hub: Rc<RefCell<AsyncIo>>
}

pub struct AsyncOutputStream {
    hub: Rc<RefCell<AsyncIo>>
}

struct AsyncIo {
    stream: ::mio::tcp::TcpStream,
    token: ::mio::Token,
}

impl AsyncIo {
    fn new(stream: ::mio::tcp::TcpStream, token: ::mio::Token) -> (AsyncOutputStream, AsyncInputStream) {
        let hub = Rc::new(RefCell::new(AsyncIo { stream: stream, token: token }));

        (AsyncOutputStream { hub: hub.clone() }, AsyncInputStream { hub: hub } )
    }
}

impl AsyncInputStream {
    fn try_read_internal<T>(self,
                            mut buf: T,
                            mut already_read: usize,
                            min_bytes: usize) -> Result<Promise<(Self, T, usize)>> where T: DerefMut<Target=[u8]> {
        use mio::TryRead;

        while already_read < min_bytes {
            let read_result = try!(self.hub.borrow_mut().stream.read_slice(&mut buf[already_read..]));
            match read_result {
                Some(0) => {
                    // EOF
                    return Ok(Promise::fulfilled((self, buf, already_read)));
                }
                Some(n) => {
                    already_read += n;
                }
                None => { // would block
                    return with_current_event_loop(move |event_loop| {
                        let promise =
                            event_loop.event_port.borrow_mut()
                            .handler.observers[self.hub.borrow().token].when_becomes_readable();
                        return Ok(promise.then(move |()| {
                            return self.try_read_internal(buf, already_read, min_bytes);
                        }));
                    });
                }
            }
        }

        return Ok(Promise::fulfilled((self, buf, already_read)));
    }
}

impl AsyncOutputStream {
    fn write_internal<T>(self,
                         buf: T,
                         mut already_written: usize) -> Result<Promise<(Self, T)>> where T: Deref<Target=[u8]> {
        use mio::TryWrite;

        while already_written < buf.len() {
            let write_result = try!(self.hub.borrow_mut().stream.write_slice(&buf[already_written..]));
            match write_result {
                Some(n) => {
                    already_written += n;
                }
                None => { // would block
                    return with_current_event_loop(move |event_loop| {
                        let promise =
                            event_loop.event_port.borrow_mut()
                            .handler.observers[self.hub.borrow().token].when_becomes_writable();
                        return Ok(promise.then(move |()| {
                            return self.write_internal(buf, already_written);
                        }));
                    });
                }
            }
        }

        return Ok(Promise::fulfilled((self, buf)));
    }
}

impl AsyncRead for AsyncInputStream {
    fn read<T>(self, buf: T,
               min_bytes: usize) -> Promise<(Self, T, usize)> where T: DerefMut<Target=[u8]> {
        return self.try_read(buf, min_bytes).map(move |(s, buf, n)| {
            if n < min_bytes {
                return Err(Box::new(::std::io::Error::new(::std::io::ErrorKind::Other, "Premature EOF")))
            } else {
                return Ok((s, buf, n));
            }
        });
    }

    fn try_read<T>(self, buf: T,
               min_bytes: usize) -> Promise<(Self, T, usize)> where T: DerefMut<Target=[u8]> {
        return Promise::fulfilled(()).then(move |()| {
            return self.try_read_internal(buf, 0, min_bytes);
        });
    }
}

impl AsyncWrite for AsyncOutputStream {
    fn write<T>(self, buf: T) -> Promise<(Self, T)> where T: Deref<Target=[u8]> {
        return Promise::fulfilled(()).then(move |()| {
            return self.write_internal(buf, 0);
        });
    }
}

pub struct FdObserver {
    read_fulfiller: Option<Box<PromiseFulfiller<()>>>,
    write_fulfiller: Option<Box<PromiseFulfiller<()>>>,
}

impl FdObserver {
    pub fn new() -> ::mio::Token {
        with_current_event_loop(move |event_loop| {

            let observer = FdObserver { read_fulfiller: None, write_fulfiller: None };
            let event_port = &mut *event_loop.event_port.borrow_mut();
            let token = match event_port.handler.observers.insert(observer) {
                Ok(tok) => tok,
                Err(_obs) => panic!("could not insert observer."),
            };
            return token;
        })
    }

    pub fn when_becomes_readable(&mut self) -> Promise<()> {
        let (promise, fulfiller) = new_promise_and_fulfiller();
        self.read_fulfiller = Some(fulfiller);
        return promise;
    }

    pub fn when_becomes_writable(&mut self) -> Promise<()> {
        let (promise, fulfiller) = new_promise_and_fulfiller();
        self.write_fulfiller = Some(fulfiller);
        return promise;
    }
}

pub struct MioEventPort {
    handler: Handler,
    reactor: ::mio::EventLoop<Handler>,
}

pub struct Handler {
    observers: Slab<FdObserver>,
}

impl MioEventPort {
    pub fn new() -> Result<MioEventPort> {
        Ok(MioEventPort {
            handler: Handler { observers: Slab::new(100) },
            reactor: try!(::mio::EventLoop::new()),
        })
    }
}

impl ::mio::Handler for Handler {
    type Timeout = ();
    type Message = ();
    fn readable(&mut self, _event_loop: &mut ::mio::EventLoop<Handler>,
                token: ::mio::Token, _hint: ::mio::ReadHint) {
        match ::std::mem::replace(&mut self.observers[token].read_fulfiller, None) {
            Some(fulfiller) => {
                fulfiller.fulfill(())
            }
            None => {
                ()
            }
        }
    }
    fn writable(&mut self, _event_loop: &mut ::mio::EventLoop<Handler>, token: ::mio::Token) {
        match ::std::mem::replace(&mut self.observers[token].write_fulfiller, None) {
            Some(fulfiller) => fulfiller.fulfill(()),
            None => (),
        }
    }
}

impl EventPort for MioEventPort {
    fn wait(&mut self) -> bool {
        self.reactor.run_once(&mut self.handler).unwrap();
        return false;
    }

    fn poll(&mut self) -> bool {
        self.reactor.run_once(&mut self.handler).unwrap();
        return false;
    }
}
<commit_msg>Only register the connection receiver once.<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use std::rc::Rc;
use std::cell::RefCell;
use std::ops::{DerefMut, Deref};
use mio::util::Slab;
use mio::Socket;
use {EventPort, Promise, PromiseFulfiller, Result, new_promise_and_fulfiller};
use private::{with_current_event_loop};

pub trait AsyncRead {
    fn read<T>(self: Self, buf: T, min_bytes: usize) -> Promise<(Self, T, usize)>
        where T: DerefMut<Target=[u8]>;
    fn try_read<T>(self: Self, buf: T, min_bytes: usize) -> Promise<(Self, T, usize)>
        where T: DerefMut<Target=[u8]>;
}

pub trait AsyncWrite {
    fn write<T>(self: Self, buf: T) -> Promise<(Self, T)>
        where T: Deref<Target=[u8]>;
}

pub struct Slice<T> where T: Deref<Target=[u8]> {
    pub buf: T,
    pub end: usize,
}

impl <T> Slice<T> where T: Deref<Target=[u8]> {
    pub fn new(buf: T, end: usize) -> Slice<T> {
        Slice { buf: buf, end: end }
    }
}

impl <T> Deref for Slice<T> where T: Deref<Target=[u8]> {
    type Target=[u8];
    fn deref<'a>(&'a self) -> &'a [u8] {
        &self.buf[0..self.end]
    }
}

#[derive(Copy, Clone)]
pub struct NetworkAddress {
    address: ::std::net::SocketAddr,
}

impl NetworkAddress {
    pub fn new(address: ::std::net::SocketAddr) -> NetworkAddress {
        NetworkAddress { address: address }
    }

    pub fn listen(self) -> Result<ConnectionReceiver> {
        let socket = try!(::mio::tcp::TcpSocket::v4());
        try!(socket.set_reuseaddr(true));
        try!(socket.bind(&self.address));
        let token = FdObserver::new();
        let listener = try!(socket.listen(256));

        return with_current_event_loop(move |event_loop| {
            try!(event_loop.event_port.borrow_mut().reactor.register_opt(&listener, token,
                                                                         ::mio::Interest::readable(),
                                                                         ::mio::PollOpt::edge()));
            Ok(ConnectionReceiver { listener: listener,
                                    token: token })
        });
    }

    pub fn connect(self) -> Promise<(AsyncOutputStream, AsyncInputStream)> {
        let socket = ::mio::tcp::TcpSocket::v4().unwrap();
        let token = FdObserver::new();
        let (stream, _) = socket.connect(&self.address).unwrap();
        with_current_event_loop(move |event_loop| {
            event_loop.event_port.borrow_mut().reactor.register_opt(&stream, token,
                                                                    ::mio::Interest::writable(),
                                                                    ::mio::PollOpt::edge()).unwrap();
            let promise =
                event_loop.event_port.borrow_mut().handler.observers[token].when_becomes_writable();
            return promise.map(move |()| {
                // TODO check for error.

                return with_current_event_loop(move |event_loop| {
                    try!(event_loop.event_port.borrow_mut().reactor.reregister(
                        &stream, token,
                        ::mio::Interest::writable() | ::mio::Interest::readable(),
                        ::mio::PollOpt::edge()));
                    return Ok(AsyncIo::new(stream, token));
                });

            });
        })
    }
}

pub struct ConnectionReceiver {
    listener: ::mio::tcp::TcpListener,
    token: ::mio::Token,
}

impl Drop for ConnectionReceiver {
    fn drop(&mut self) {
        // deregister the token
    }
}

impl ConnectionReceiver {
    pub fn accept(self) -> Promise<(ConnectionReceiver, (AsyncOutputStream, AsyncInputStream))> {
        with_current_event_loop(move |event_loop| {
            let promise =
                event_loop.event_port.borrow_mut().handler.observers[self.token].when_becomes_readable();

            return promise.map(move |()| {
                let stream = try!(self.listener.accept()).unwrap();
                let token = FdObserver::new();

                return with_current_event_loop(move |event_loop| {
                    try!(event_loop.event_port.borrow_mut().reactor.register_opt(
                        &stream, token,
                        ::mio::Interest::writable() | ::mio::Interest::readable(),
                        ::mio::PollOpt::edge()));
                    return Ok((self, AsyncIo::new(stream, token)));
                });
            });
        })
    }
}

pub struct AsyncInputStream {
    hub: Rc<RefCell<AsyncIo>>
}

pub struct AsyncOutputStream {
    hub: Rc<RefCell<AsyncIo>>
}

struct AsyncIo {
    stream: ::mio::tcp::TcpStream,
    token: ::mio::Token,
}

impl AsyncIo {
    fn new(stream: ::mio::tcp::TcpStream, token: ::mio::Token) -> (AsyncOutputStream, AsyncInputStream) {
        let hub = Rc::new(RefCell::new(AsyncIo { stream: stream, token: token }));

        (AsyncOutputStream { hub: hub.clone() }, AsyncInputStream { hub: hub } )
    }
}

impl AsyncInputStream {
    fn try_read_internal<T>(self,
                            mut buf: T,
                            mut already_read: usize,
                            min_bytes: usize) -> Result<Promise<(Self, T, usize)>> where T: DerefMut<Target=[u8]> {
        use mio::TryRead;

        while already_read < min_bytes {
            let read_result = try!(self.hub.borrow_mut().stream.read_slice(&mut buf[already_read..]));
            match read_result {
                Some(0) => {
                    // EOF
                    return Ok(Promise::fulfilled((self, buf, already_read)));
                }
                Some(n) => {
                    already_read += n;
                }
                None => { // would block
                    return with_current_event_loop(move |event_loop| {
                        let promise =
                            event_loop.event_port.borrow_mut()
                            .handler.observers[self.hub.borrow().token].when_becomes_readable();
                        return Ok(promise.then(move |()| {
                            return self.try_read_internal(buf, already_read, min_bytes);
                        }));
                    });
                }
            }
        }

        return Ok(Promise::fulfilled((self, buf, already_read)));
    }
}

impl AsyncOutputStream {
    fn write_internal<T>(self,
                         buf: T,
                         mut already_written: usize) -> Result<Promise<(Self, T)>> where T: Deref<Target=[u8]> {
        use mio::TryWrite;

        while already_written < buf.len() {
            let write_result = try!(self.hub.borrow_mut().stream.write_slice(&buf[already_written..]));
            match write_result {
                Some(n) => {
                    already_written += n;
                }
                None => { // would block
                    return with_current_event_loop(move |event_loop| {
                        let promise =
                            event_loop.event_port.borrow_mut()
                            .handler.observers[self.hub.borrow().token].when_becomes_writable();
                        return Ok(promise.then(move |()| {
                            return self.write_internal(buf, already_written);
                        }));
                    });
                }
            }
        }

        return Ok(Promise::fulfilled((self, buf)));
    }
}

impl AsyncRead for AsyncInputStream {
    fn read<T>(self, buf: T,
               min_bytes: usize) -> Promise<(Self, T, usize)> where T: DerefMut<Target=[u8]> {
        return self.try_read(buf, min_bytes).map(move |(s, buf, n)| {
            if n < min_bytes {
                return Err(Box::new(::std::io::Error::new(::std::io::ErrorKind::Other, "Premature EOF")))
            } else {
                return Ok((s, buf, n));
            }
        });
    }

    fn try_read<T>(self, buf: T,
               min_bytes: usize) -> Promise<(Self, T, usize)> where T: DerefMut<Target=[u8]> {
        return Promise::fulfilled(()).then(move |()| {
            return self.try_read_internal(buf, 0, min_bytes);
        });
    }
}

impl AsyncWrite for AsyncOutputStream {
    fn write<T>(self, buf: T) -> Promise<(Self, T)> where T: Deref<Target=[u8]> {
        return Promise::fulfilled(()).then(move |()| {
            return self.write_internal(buf, 0);
        });
    }
}

pub struct FdObserver {
    read_fulfiller: Option<Box<PromiseFulfiller<()>>>,
    write_fulfiller: Option<Box<PromiseFulfiller<()>>>,
}

impl FdObserver {
    pub fn new() -> ::mio::Token {
        with_current_event_loop(move |event_loop| {

            let observer = FdObserver { read_fulfiller: None, write_fulfiller: None };
            let event_port = &mut *event_loop.event_port.borrow_mut();
            let token = match event_port.handler.observers.insert(observer) {
                Ok(tok) => tok,
                Err(_obs) => panic!("could not insert observer."),
            };
            return token;
        })
    }

    pub fn when_becomes_readable(&mut self) -> Promise<()> {
        let (promise, fulfiller) = new_promise_and_fulfiller();
        self.read_fulfiller = Some(fulfiller);
        return promise;
    }

    pub fn when_becomes_writable(&mut self) -> Promise<()> {
        let (promise, fulfiller) = new_promise_and_fulfiller();
        self.write_fulfiller = Some(fulfiller);
        return promise;
    }
}

pub struct MioEventPort {
    handler: Handler,
    reactor: ::mio::EventLoop<Handler>,
}

pub struct Handler {
    observers: Slab<FdObserver>,
}

impl MioEventPort {
    pub fn new() -> Result<MioEventPort> {
        Ok(MioEventPort {
            handler: Handler { observers: Slab::new(100) },
            reactor: try!(::mio::EventLoop::new()),
        })
    }
}

impl ::mio::Handler for Handler {
    type Timeout = ();
    type Message = ();
    fn readable(&mut self, _event_loop: &mut ::mio::EventLoop<Handler>,
                token: ::mio::Token, _hint: ::mio::ReadHint) {
        match ::std::mem::replace(&mut self.observers[token].read_fulfiller, None) {
            Some(fulfiller) => {
                fulfiller.fulfill(())
            }
            None => {
                ()
            }
        }
    }
    fn writable(&mut self, _event_loop: &mut ::mio::EventLoop<Handler>, token: ::mio::Token) {
        match ::std::mem::replace(&mut self.observers[token].write_fulfiller, None) {
            Some(fulfiller) => fulfiller.fulfill(()),
            None => (),
        }
    }
}

impl EventPort for MioEventPort {
    fn wait(&mut self) -> bool {
        self.reactor.run_once(&mut self.handler).unwrap();
        return false;
    }

    fn poll(&mut self) -> bool {
        self.reactor.run_once(&mut self.handler).unwrap();
        return false;
    }
}
<|endoftext|>


<commit_before>use types::{Result, OscType, OscPacket, OscBundle, OscMessage};
use errors::OscError;
use utils;

use byteorder::{ByteOrder, BigEndian};
use std::iter;

pub fn encode(packet: &OscPacket) -> Result<Vec<u8>> {
    match *packet {
        OscPacket::Message(ref msg) => encode_message(msg),
        OscPacket::Bundle(ref bundle) => encode_bundle(bundle),
    }
}

fn encode_message(msg: &OscMessage) -> Result<Vec<u8>> {
    let mut msg_bytes: Vec<u8> = Vec::new();

    msg_bytes.extend(encode_string(&msg.addr));
    let mut type_tags: Vec<char> = vec![','];
    let mut arg_bytes: Vec<u8> = Vec::new();

    if msg.args.is_some() {
        let args = msg.args.as_ref().unwrap();
        for arg in args {
            let (bytes, tag): (Option<Vec<u8>>, char) = try!(encode_arg(arg));

            type_tags.push(tag);
            if bytes.is_some() {
                arg_bytes.extend(bytes.unwrap());
            }
        }
    }

    msg_bytes.extend(encode_string(&type_tags.iter()
                                             .cloned()
                                             .collect::<String>()));
    if arg_bytes.len() > 0 {
        msg_bytes.extend(arg_bytes);
    }
    Ok(msg_bytes)
}

fn encode_bundle(bundle: &OscBundle) -> Result<Vec<u8>> {
    let mut bundle_bytes: Vec<u8> = Vec::new();
    bundle_bytes.extend(encode_string(&"#bundle".to_string())
                            .iter()
                            .cloned());

    match try!(encode_arg(&bundle.timetag)) {
        (Some(x), _) => {
            bundle_bytes.extend(x.iter().cloned());
        }
        (None, _) => {
            return Err(OscError::BadBundle("Missing time tag!".to_string()));
        }
    }

    if bundle.content.len() == 0 {
        // TODO: A bundle of length zero, should this really be supported?
        bundle_bytes.extend([0u8; 4].iter().cloned());
        return Ok(bundle_bytes);
    }

    for packet in &bundle.content {
        match packet {
            &OscPacket::Message(ref m) => {
                let msg = try!(encode_message(m));
                let mut msg_size = vec![0u8; 4];
                BigEndian::write_u32(&mut msg_size, msg.len() as u32);
                bundle_bytes.extend(msg_size.iter().chain(msg.iter()).cloned());
            }
            &OscPacket::Bundle(ref b) => {
                let bdl = try!(encode_bundle(b));
                let mut bdl_size = vec![0u8; 4];
                BigEndian::write_u32(&mut bdl_size, bdl.len() as u32);
                bundle_bytes.extend(bdl_size.iter().chain(bdl.iter()).cloned());
            }
        }
    }

    Ok(bundle_bytes)
}

fn encode_arg(arg: &OscType) -> Result<(Option<Vec<u8>>, char)> {
    match arg {
        &OscType::Int(ref x) => {
            let mut bytes = vec![0u8; 4];
            BigEndian::write_i32(&mut bytes, *x);
            Ok((Some(bytes), 'i'))
        }
        &OscType::Long(ref x) => {
            let mut bytes = vec![0u8; 8];
            BigEndian::write_i64(&mut bytes, *x);
            Ok((Some(bytes), 'h'))
        }
        &OscType::Float(ref x) => {
            let mut bytes = vec![0u8; 4];
            BigEndian::write_f32(&mut bytes, *x);
            Ok((Some(bytes), 'f'))
        }
        &OscType::Double(ref x) => {
            let mut bytes = vec![0u8; 8];
            BigEndian::write_f64(&mut bytes, *x);
            Ok((Some(bytes), 'd'))
        }
        &OscType::Char(ref x) => {
            let mut bytes = vec![0u8; 4];
            BigEndian::write_u32(&mut bytes, *x as u32);
            Ok((Some(bytes), 'c'))
        }
        &OscType::String(ref x) => {
            Ok((Some(encode_string(&x)), 's'))
        }
        &OscType::Blob(ref x) => {
            // let mut bytes = x.clone();
            let padded_blob_length: usize = utils::pad(x.len() as u64) as usize;
            let mut bytes = vec![0u8; 4 + padded_blob_length];
            // write length
            BigEndian::write_i32(&mut bytes[..4], x.len() as i32);
            for (i, v) in x.iter().enumerate() {
                bytes[i + 4] = *v;
            }
            Ok((Some(bytes), 'b'))
        }
        &OscType::Time(ref x, ref y) => {
            Ok((Some(encode_time_tag(*x, *y)), 't'))
        }
        &OscType::Midi(ref x) => {
            Ok((Some(vec![x.port, x.status, x.data1, x.data2]), 'm'))
        }
        &OscType::Color(ref x) => {
            Ok((Some(vec![x.red, x.green, x.blue, x.alpha]), 'r'))
        }
        &OscType::Bool(ref x) => {
            if *x {
                Ok((None, 'T'))
            } else {
                Ok((None, 'F'))
            }
        }
        &OscType::Nil => {
            Ok((None, 'N'))
        }
        &OscType::Inf => {
            Ok((None, 'I'))
        }
    }
}

fn encode_string(s: &String) -> Vec<u8> {
    let mut bytes: Vec<u8> = s.as_bytes()
                              .iter()
                              .cloned()
                              .chain(iter::once(0u8))
                              .collect();
    pad_bytes(&mut bytes);
    bytes
}

fn pad_bytes(bytes: &mut Vec<u8>) {
    let padded_lengh = utils::pad(bytes.len() as u64);
    while bytes.len() < padded_lengh as usize {
        bytes.push(0u8)
    }
}

fn encode_time_tag(sec: u32, frac: u32) -> Vec<u8> {
    let mut bytes = vec![0u8; 8];
    BigEndian::write_u32(&mut bytes[..4], sec);
    BigEndian::write_u32(&mut bytes[4..], frac);
    bytes
}
<commit_msg>Deref `match` to remove `&` on each match case<commit_after>use types::{Result, OscType, OscPacket, OscBundle, OscMessage};
use errors::OscError;
use utils;

use byteorder::{ByteOrder, BigEndian};
use std::iter;

pub fn encode(packet: &OscPacket) -> Result<Vec<u8>> {
    match *packet {
        OscPacket::Message(ref msg) => encode_message(msg),
        OscPacket::Bundle(ref bundle) => encode_bundle(bundle),
    }
}

fn encode_message(msg: &OscMessage) -> Result<Vec<u8>> {
    let mut msg_bytes: Vec<u8> = Vec::new();

    msg_bytes.extend(encode_string(&msg.addr));
    let mut type_tags: Vec<char> = vec![','];
    let mut arg_bytes: Vec<u8> = Vec::new();

    if msg.args.is_some() {
        let args = msg.args.as_ref().unwrap();
        for arg in args {
            let (bytes, tag): (Option<Vec<u8>>, char) = try!(encode_arg(arg));

            type_tags.push(tag);
            if bytes.is_some() {
                arg_bytes.extend(bytes.unwrap());
            }
        }
    }

    msg_bytes.extend(encode_string(&type_tags.iter()
                                             .cloned()
                                             .collect::<String>()));
    if arg_bytes.len() > 0 {
        msg_bytes.extend(arg_bytes);
    }
    Ok(msg_bytes)
}

fn encode_bundle(bundle: &OscBundle) -> Result<Vec<u8>> {
    let mut bundle_bytes: Vec<u8> = Vec::new();
    bundle_bytes.extend(encode_string(&"#bundle".to_string())
                            .iter()
                            .cloned());

    match try!(encode_arg(&bundle.timetag)) {
        (Some(x), _) => {
            bundle_bytes.extend(x.iter().cloned());
        }
        (None, _) => {
            return Err(OscError::BadBundle("Missing time tag!".to_string()));
        }
    }

    if bundle.content.len() == 0 {
        // TODO: A bundle of length zero, should this really be supported?
        bundle_bytes.extend([0u8; 4].iter().cloned());
        return Ok(bundle_bytes);
    }

    for packet in &bundle.content {
        match *packet {
            OscPacket::Message(ref m) => {
                let msg = try!(encode_message(m));
                let mut msg_size = vec![0u8; 4];
                BigEndian::write_u32(&mut msg_size, msg.len() as u32);
                bundle_bytes.extend(msg_size.iter().chain(msg.iter()).cloned());
            }
            OscPacket::Bundle(ref b) => {
                let bdl = try!(encode_bundle(b));
                let mut bdl_size = vec![0u8; 4];
                BigEndian::write_u32(&mut bdl_size, bdl.len() as u32);
                bundle_bytes.extend(bdl_size.iter().chain(bdl.iter()).cloned());
            }
        }
    }

    Ok(bundle_bytes)
}

fn encode_arg(arg: &OscType) -> Result<(Option<Vec<u8>>, char)> {
    match *arg {
        OscType::Int(ref x) => {
            let mut bytes = vec![0u8; 4];
            BigEndian::write_i32(&mut bytes, *x);
            Ok((Some(bytes), 'i'))
        }
        OscType::Long(ref x) => {
            let mut bytes = vec![0u8; 8];
            BigEndian::write_i64(&mut bytes, *x);
            Ok((Some(bytes), 'h'))
        }
        OscType::Float(ref x) => {
            let mut bytes = vec![0u8; 4];
            BigEndian::write_f32(&mut bytes, *x);
            Ok((Some(bytes), 'f'))
        }
        OscType::Double(ref x) => {
            let mut bytes = vec![0u8; 8];
            BigEndian::write_f64(&mut bytes, *x);
            Ok((Some(bytes), 'd'))
        }
        OscType::Char(ref x) => {
            let mut bytes = vec![0u8; 4];
            BigEndian::write_u32(&mut bytes, *x as u32);
            Ok((Some(bytes), 'c'))
        }
        OscType::String(ref x) => {
            Ok((Some(encode_string(&x)), 's'))
        }
        OscType::Blob(ref x) => {
            // let mut bytes = x.clone();
            let padded_blob_length: usize = utils::pad(x.len() as u64) as usize;
            let mut bytes = vec![0u8; 4 + padded_blob_length];
            // write length
            BigEndian::write_i32(&mut bytes[..4], x.len() as i32);
            for (i, v) in x.iter().enumerate() {
                bytes[i + 4] = *v;
            }
            Ok((Some(bytes), 'b'))
        }
        OscType::Time(ref x, ref y) => {
            Ok((Some(encode_time_tag(*x, *y)), 't'))
        }
        OscType::Midi(ref x) => {
            Ok((Some(vec![x.port, x.status, x.data1, x.data2]), 'm'))
        }
        OscType::Color(ref x) => {
            Ok((Some(vec![x.red, x.green, x.blue, x.alpha]), 'r'))
        }
        OscType::Bool(ref x) => {
            if *x {
                Ok((None, 'T'))
            } else {
                Ok((None, 'F'))
            }
        }
        OscType::Nil => {
            Ok((None, 'N'))
        }
        OscType::Inf => {
            Ok((None, 'I'))
        }
    }
}

fn encode_string(s: &String) -> Vec<u8> {
    let mut bytes: Vec<u8> = s.as_bytes()
                              .iter()
                              .cloned()
                              .chain(iter::once(0u8))
                              .collect();
    pad_bytes(&mut bytes);
    bytes
}

fn pad_bytes(bytes: &mut Vec<u8>) {
    let padded_lengh = utils::pad(bytes.len() as u64);
    while bytes.len() < padded_lengh as usize {
        bytes.push(0u8)
    }
}

fn encode_time_tag(sec: u32, frac: u32) -> Vec<u8> {
    let mut bytes = vec![0u8; 8];
    BigEndian::write_u32(&mut bytes[..4], sec);
    BigEndian::write_u32(&mut bytes[4..], frac);
    bytes
}
<|endoftext|>


<commit_before>use sdl2;
use sdl2_gfx;
use ttf = sdl2_ttf;
use sdl2::video;
use sdl2::render;
use sdl2::{event, keycode};
// for Renderer trait
use sdl2_gfx::primitives::DrawRenderer;
use sdl2::pixels::{Color, RGB, RGBA};
use sdl2::rwops;
use sdl2_ttf::LoaderRWops;

static SCREEN_WIDTH : int = 800;
static SCREEN_HEIGHT : int = 600;

mod game;

// hadle the annoying Rect i32
macro_rules! rect(
    ($x:expr, $y:expr, $w:expr, $h:expr) => (
        sdl2::rect::Rect::new($x as i32, $y as i32, $w as i32, $h as i32)
    )
)

// colors
static BG_COLOR: Color = RGB(0xee, 0xe4, 0xda);
static FG_COLOR: Color = RGB(0x77, 0x6e, 0x65);
static CHAR_COLOR: Color = RGB(0xee, 0x33, 0x66);
static CONTAINER_COLOR: Color = RGBA(0x77, 0x6e, 0x65, 200);
static CELL_COLORS: &'static [Color] = &'static [
    RGBA(0xee, 0xe4, 0xda, 120), RGB(0xed, 0xe0, 0xc8), RGB(0xf2, 0xb1, 0x79),
    RGB(0xf5, 0x95, 0x64), RGB(0xf6, 0x7c, 0x5f), RGB(0xf6, 0x5e, 0x3b),
    RGB(0xed, 0xcf, 0x72), RGB(0xed, 0xcc, 0x61), RGB(0xed, 0xc8, 0x50),
    RGB(0xed, 0xc5, 0x3f), RGB(0xed, 0xc2, 0x2e), RGB(0x3c, 0x3a, 0x32), ];

// Font
static TTF_FONT_RAW_BYTES: &'static [u8] = include_bin!("./res/OpenDyslexic-Regular.ttf");

#[allow(uppercase_variables, unused_must_use)]
fn draw_game(gm: &mut game::GameManager, ren: &render::Renderer, font: &ttf::Font,
             (x,y,w,h): (int,int,int,int)) -> Result<(), ~str> {
    assert_eq!(w, h);
    // BEST in 500x500
    let SIZE = gm.size;
    let CONTAINER_PADDING: int = 50 / (SIZE as int + 1);
    let CELL_WIDTH = (w - CONTAINER_PADDING * (SIZE as int + 1)) / SIZE as int ;
    assert!(CELL_WIDTH > 50); // Min width
    try!(ren.box_(x as i16, y as i16, (x+w) as i16, (y+h) as i16, CONTAINER_COLOR));
    gm.grid.each_cell(|j, i, tile_opt| {
        let i = i as int;
        let j = j as int;
        let val = match tile_opt {
            Some(&tile) => tile.value,
            None        => 0,
        };
        let c = if val == 0 {
            0           // or will be +Infinity
        } else {
            (val as f64).log2() as uint
        };
        let bx = (x + CONTAINER_PADDING * (j + 1) + CELL_WIDTH * j) as i16;
        let by = (y + CONTAINER_PADDING * (i + 1) + CELL_WIDTH * i) as i16;
        ren.box_(bx, by, bx + CELL_WIDTH as i16, by + CELL_WIDTH as i16, CELL_COLORS[c]);
        // ren.string(bx, by, format!("({}, {})", j, i), CHAR_COLOR); // DEBUG
        if val != 0 {
            let (tex, tw, th) = {
                let wd = format!("{}", val);
                let (w, h) = font.size_of_str(wd).ok().expect("size of str");
                let text = font.render_str_blended(wd, FG_COLOR).ok().expect("renderred surface");
                (ren.create_texture_from_surface(text).ok().expect("create texture"), w, h)
            };
            if tw > CELL_WIDTH {
                let ratio = CELL_WIDTH as f64 / tw as f64;
                let tw = (tw as f64 * ratio) as int;
                let th = (th as f64 * ratio) as int;

                ren.copy(tex, None, Some(rect!(bx as int + CELL_WIDTH / 2 - tw/2, by as int + CELL_WIDTH / 2 - th/2,
                                               tw, th)));
            } else {
                ren.copy(tex, None, Some(rect!(bx as int + CELL_WIDTH / 2 - tw/2, by as int + CELL_WIDTH / 2 - th/2,
                                               tw, th)));
            }
        }
    });
    Ok(())
}

fn draw_title(ren: &render::Renderer, font: &ttf::Font) -> Result<(), ~str> {
    let (tex2, w, h) = {
        let wd = "Rust - 2048";
        //font.set_style([ttf::StyleBold]);
        let (w, h) = try!(font.size_of_str(wd));
        let text = try!(font.render_str_blended(wd, FG_COLOR));
        (try!(ren.create_texture_from_surface(text)), w, h)
    };
    try!(ren.copy(tex2, None, Some(rect!(SCREEN_WIDTH / 2 - w / 2, 20, w, h))));
    Ok(())
}

// FIXME: tooooooo many type convertion
fn draw_popup(ren: &render::Renderer, font: &ttf::Font, msg: &str) -> Result<(), ~str> {
    let (tex, w, h) = {
        //font.set_style([ttf::StyleBold]);
        let (w, h) = try!(font.size_of_str(msg));
        let text = try!(font.render_str_blended(msg, FG_COLOR));
        (try!(ren.create_texture_from_surface(text)), w, h)
    };
    try!(ren.rounded_box((SCREEN_WIDTH / 2 - w / 2) as i16,
                         (SCREEN_HEIGHT / 2 - h / 2) as i16,
                         (SCREEN_WIDTH / 2 + w / 2) as i16,
                         (SCREEN_HEIGHT / 2 + h / 2) as i16,
                         5,
                         BG_COLOR));
    try!(ren.rounded_rectangle((SCREEN_WIDTH / 2 - w / 2) as i16,
                               (SCREEN_HEIGHT / 2 - h / 2) as i16,
                               (SCREEN_WIDTH / 2 + w / 2) as i16,
                               (SCREEN_HEIGHT / 2 + h / 2) as i16,
                               5,
                               FG_COLOR));
    try!(ren.copy(tex, None, Some(rect!(SCREEN_WIDTH / 2 - w / 2,
                                        SCREEN_HEIGHT / 2 - h / 2,
                                        w,
                                        h))));
    Ok(())
}

pub fn run(game_size: uint) -> Result<(), ~str> {
    let win = try!(video::Window::new(
        "Rust - 2048", video::PosCentered, video::PosCentered, SCREEN_WIDTH, SCREEN_HEIGHT,
        [video::Shown]));
    let ren = try!(render::Renderer::from_window(
        win, render::DriverAuto, [render::Accelerated]));

    let mut fpsm = sdl2_gfx::framerate::FPSManager::new();
    try!(fpsm.set_framerate(50));

    let font : ~ttf::Font = {
        let raw = try!(rwops::RWops::from_bytes(TTF_FONT_RAW_BYTES));
        // or try!(ttf::Font::from_file(&Path::new("./OpenDyslexic-Regular.ttf"), 48));
        try!(raw.load_font(48))
    };
    let mut gm = game::GameManager::new(game_size);

    let mut playing = false;
    let mut celebrating = false;

    'main : loop {
        'event : loop {
            fpsm.delay();
            try!(ren.set_draw_color(BG_COLOR));
            try!(ren.clear());
            // == main drawing ==
            try!(draw_title(&*ren, &*font));
            try!(ren.string(0i16, 0i16, format!("frames: {}", fpsm.get_frame_count()), CHAR_COLOR));

            try!(ren.string(200, 90, format!("your score: {}", gm.score), CHAR_COLOR));

            try!(draw_game(&mut gm, &*ren, &*font, (SCREEN_WIDTH / 2 - 400 / 2, 100, 400, 400)));

            if celebrating || (playing && !gm.moves_available()) { // can't move
                try!(draw_popup(&*ren, &*font, format!("Score: {}! Max Cell: {}", gm.score, "NaN")));
                playing = false;
                celebrating = true;

            } else if !playing && !celebrating {
                try!(draw_popup(&*ren, &*font, "Press SPACE to start!"));
            }

            // == main drawing ends ==
            ren.present();

            match event::poll_event() {
                event::QuitEvent(_) => break 'main,
                event::KeyDownEvent(_, _, keycode::LeftKey, _, _) if playing => {
                    gm.move(game::Left);
                }
                event::KeyDownEvent(_, _, keycode::RightKey, _, _) if playing => {
                    gm.move(game::Right);
                }
                event::KeyDownEvent(_, _, keycode::UpKey, _, _) if playing => {
                    gm.move(game::Up);
                }
                event::KeyDownEvent(_, _, keycode::DownKey, _, _) if playing => {
                    gm.move(game::Down);
                }
                event::KeyDownEvent(_, _, key, _, _) => {
                    if key == keycode::EscapeKey {
                        break 'main
                    } else if key == keycode::SpaceKey {
                        if !playing {
                            playing = true;
                            celebrating = false;
                            gm.setup();
                        }
                    }

                }
                event::MouseButtonDownEvent(_, _, _, _, x, y) => {
                    println!("mouse btn down at ({},{})", x, y);
                }

                _ => {}
            }
        }
    }
    Ok(())
}
<commit_msg>fix font renderring scale<commit_after>use sdl2;
use sdl2_gfx;
use ttf = sdl2_ttf;
use sdl2::video;
use sdl2::render;
use sdl2::{event, keycode};
// for Renderer trait
use sdl2_gfx::primitives::DrawRenderer;
use sdl2::pixels::{Color, RGB, RGBA};
use sdl2::rwops;
use sdl2_ttf::LoaderRWops;

static SCREEN_WIDTH : int = 800;
static SCREEN_HEIGHT : int = 600;

mod game;

// hadle the annoying Rect i32
macro_rules! rect(
    ($x:expr, $y:expr, $w:expr, $h:expr) => (
        sdl2::rect::Rect::new($x as i32, $y as i32, $w as i32, $h as i32)
    )
)

// colors
static BG_COLOR: Color = RGB(0xee, 0xe4, 0xda);
static FG_COLOR: Color = RGB(0x77, 0x6e, 0x65);
static CHAR_COLOR: Color = RGB(0xee, 0x33, 0x66);
static CONTAINER_COLOR: Color = RGBA(0x77, 0x6e, 0x65, 200);
static CELL_COLORS: &'static [Color] = &'static [
    RGBA(0xee, 0xe4, 0xda, 120), RGB(0xed, 0xe0, 0xc8), RGB(0xf2, 0xb1, 0x79),
    RGB(0xf5, 0x95, 0x64), RGB(0xf6, 0x7c, 0x5f), RGB(0xf6, 0x5e, 0x3b),
    RGB(0xed, 0xcf, 0x72), RGB(0xed, 0xcc, 0x61), RGB(0xed, 0xc8, 0x50),
    RGB(0xed, 0xc5, 0x3f), RGB(0xed, 0xc2, 0x2e), RGB(0x3c, 0x3a, 0x32), ];

// Font
static TTF_FONT_RAW_BYTES: &'static [u8] = include_bin!("./res/OpenDyslexic-Regular.ttf");

#[allow(uppercase_variables, unused_must_use)]
fn draw_game(gm: &mut game::GameManager, ren: &render::Renderer, font: &ttf::Font,
             (x,y,w,h): (int,int,int,int)) -> Result<(), ~str> {
    assert_eq!(w, h);
    // BEST in 500x500
    let SIZE = gm.size;
    let CONTAINER_PADDING: int = 50  / (SIZE as int + 1);
    let CELL_WIDTH = (w - CONTAINER_PADDING * (SIZE as int + 1)) / SIZE as int ;
    assert!(CELL_WIDTH > 40); // Min width
    try!(ren.box_(x as i16, y as i16, (x+w) as i16, (y+h) as i16, CONTAINER_COLOR));
    gm.grid.each_cell(|j, i, tile_opt| {
        let i = i as int;
        let j = j as int;
        let val = match tile_opt {
            Some(&tile) => tile.value,
            None        => 0,
        };
        let c = if val == 0 {
            0           // or will be +Infinity
        } else {
            (val as f64).log2() as uint
        };
        let bx = (x + CONTAINER_PADDING * (j + 1) + CELL_WIDTH * j) as i16;
        let by = (y + CONTAINER_PADDING * (i + 1) + CELL_WIDTH * i) as i16;
        ren.box_(bx, by, bx + CELL_WIDTH as i16, by + CELL_WIDTH as i16, CELL_COLORS[c]);
        // ren.string(bx, by, format!("({}, {})", j, i), CHAR_COLOR); // DEBUG
        if val != 0 {
            let (tex, tw, th) = {
                let wd = format!("{}", val);
                let (w, h) = font.size_of_str(wd).ok().expect("size of str");
                let text = font.render_str_blended(wd, FG_COLOR).ok().expect("renderred surface");
                (ren.create_texture_from_surface(text).ok().expect("create texture"), w, h)
            };

            let ratio = if tw > CELL_WIDTH {
                CELL_WIDTH as f64 / tw as f64
            } else if th > CELL_WIDTH {
                CELL_WIDTH as f64 / th as f64
            } else { 1.0 };

            let tw = (tw as f64 * ratio) as int;
            let th = (th as f64 * ratio) as int;

            ren.copy(tex, None, Some(rect!(bx as int + CELL_WIDTH / 2 - tw/2, by as int + CELL_WIDTH / 2 - th/2,
                                               tw, th)));
        }
    });
    Ok(())
}

fn draw_title(ren: &render::Renderer, font: &ttf::Font) -> Result<(), ~str> {
    let (tex2, w, h) = {
        let wd = "Rust - 2048";
        //font.set_style([ttf::StyleBold]);
        let (w, h) = try!(font.size_of_str(wd));
        let text = try!(font.render_str_blended(wd, FG_COLOR));
        (try!(ren.create_texture_from_surface(text)), w, h)
    };
    try!(ren.copy(tex2, None, Some(rect!(SCREEN_WIDTH / 2 - w / 2, 20, w, h))));
    Ok(())
}

// FIXME: tooooooo many type convertion
fn draw_popup(ren: &render::Renderer, font: &ttf::Font, msg: &str) -> Result<(), ~str> {
    let (tex, w, h) = {
        //font.set_style([ttf::StyleBold]);
        let (w, h) = try!(font.size_of_str(msg));
        let text = try!(font.render_str_blended(msg, FG_COLOR));
        (try!(ren.create_texture_from_surface(text)), w, h)
    };
    try!(ren.rounded_box((SCREEN_WIDTH / 2 - w / 2) as i16,
                         (SCREEN_HEIGHT / 2 - h / 2) as i16,
                         (SCREEN_WIDTH / 2 + w / 2) as i16,
                         (SCREEN_HEIGHT / 2 + h / 2) as i16,
                         5,
                         BG_COLOR));
    try!(ren.rounded_rectangle((SCREEN_WIDTH / 2 - w / 2) as i16,
                               (SCREEN_HEIGHT / 2 - h / 2) as i16,
                               (SCREEN_WIDTH / 2 + w / 2) as i16,
                               (SCREEN_HEIGHT / 2 + h / 2) as i16,
                               5,
                               FG_COLOR));
    try!(ren.copy(tex, None, Some(rect!(SCREEN_WIDTH / 2 - w / 2,
                                        SCREEN_HEIGHT / 2 - h / 2,
                                        w,
                                        h))));
    Ok(())
}

pub fn run(game_size: uint) -> Result<(), ~str> {
    let win = try!(video::Window::new(
        "Rust - 2048", video::PosCentered, video::PosCentered, SCREEN_WIDTH, SCREEN_HEIGHT,
        [video::Shown]));
    let ren = try!(render::Renderer::from_window(
        win, render::DriverAuto, [render::Accelerated]));

    let mut fpsm = sdl2_gfx::framerate::FPSManager::new();
    try!(fpsm.set_framerate(50));

    let font : ~ttf::Font = {
        let raw = try!(rwops::RWops::from_bytes(TTF_FONT_RAW_BYTES));
        // or try!(ttf::Font::from_file(&Path::new("./OpenDyslexic-Regular.ttf"), 48));
        try!(raw.load_font(48))
    };
    let mut gm = game::GameManager::new(game_size);

    let mut playing = false;
    let mut celebrating = false;

    'main : loop {
        'event : loop {
            fpsm.delay();
            try!(ren.set_draw_color(BG_COLOR));
            try!(ren.clear());
            // == main drawing ==
            try!(draw_title(&*ren, &*font));
            try!(ren.string(0i16, 0i16, format!("frames: {}", fpsm.get_frame_count()), CHAR_COLOR));

            try!(ren.string(200, 90, format!("your score: {}", gm.score), CHAR_COLOR));

            try!(draw_game(&mut gm, &*ren, &*font, (SCREEN_WIDTH / 2 - 400 / 2, 100, 400, 400)));

            if celebrating || (playing && !gm.moves_available()) { // can't move
                try!(draw_popup(&*ren, &*font, format!("Score: {}! Max Cell: {}", gm.score, "NaN")));
                playing = false;
                celebrating = true;

            } else if !playing && !celebrating {
                try!(draw_popup(&*ren, &*font, "Press SPACE to start!"));
            }

            // == main drawing ends ==
            ren.present();

            match event::poll_event() {
                event::QuitEvent(_) => break 'main,
                event::KeyDownEvent(_, _, keycode::LeftKey, _, _) if playing => {
                    gm.move(game::Left);
                }
                event::KeyDownEvent(_, _, keycode::RightKey, _, _) if playing => {
                    gm.move(game::Right);
                }
                event::KeyDownEvent(_, _, keycode::UpKey, _, _) if playing => {
                    gm.move(game::Up);
                }
                event::KeyDownEvent(_, _, keycode::DownKey, _, _) if playing => {
                    gm.move(game::Down);
                }
                event::KeyDownEvent(_, _, key, _, _) => {
                    if key == keycode::EscapeKey {
                        break 'main
                    } else if key == keycode::SpaceKey {
                        if !playing {
                            playing = true;
                            celebrating = false;
                            gm.setup();
                        }
                    }

                }
                event::MouseButtonDownEvent(_, _, _, _, x, y) => {
                    println!("mouse btn down at ({},{})", x, y);
                }

                _ => {}
            }
        }
    }
    Ok(())
}
<|endoftext|>


<commit_before>use amq_protocol::frame::{GenError, Offset, gen_frame, parse_frame};
use log::{error, trace};
use mio::{Evented, Events, Poll, PollOpt, Ready, Registration, SetReadiness, Token};
use parking_lot::Mutex;

use std::{
  io::{self, Read, Write},
  sync::{
    Arc,
    atomic::{AtomicBool, Ordering},
  },
  thread::{self, Builder as ThreadBuilder, JoinHandle},
  time::{Duration, Instant},
};

use crate::{
  buffer::Buffer,
  connection::Connection,
  connection_status::ConnectionState,
  error::{Error, ErrorKind},
};

const SOCKET:   Token = Token(1);
const DATA:     Token = Token(2);
const CONTINUE: Token = Token(3);

const FRAMES_STORAGE: usize = 32;

#[derive(Clone, Debug)]
pub(crate) struct IoLoopHandle {
  handle: Arc<Mutex<Option<JoinHandle<Result<(), Error>>>>>,
}

impl Default for IoLoopHandle {
  fn default() -> Self {
    Self { handle: Arc::new(Mutex::new(None)) }
  }
}

impl IoLoopHandle {
  pub(crate) fn register(&self, handle: JoinHandle<Result<(), Error>>) {
    *self.handle.lock() = Some(handle);
  }

  pub(crate) fn wait(&self) -> Result<(), Error> {
    if let Some(handle) = self.handle.lock().take() {
      handle.join().expect("io loop")?
    }
    Ok(())
  }
}

#[derive(Debug, PartialEq)]
enum Status {
  Initial,
  Setup,
  Stop,
}

pub(crate) struct IoLoop<T> {
  connection:     Connection,
  socket:         T,
  status:         Status,
  poll:           Poll,
  registration:   Registration,
  set_readiness:  SetReadiness,
  hb_handle:      Option<JoinHandle<()>>,
  frame_size:     usize,
  receive_buffer: Buffer,
  send_buffer:    Buffer,
  can_write:      bool,
  can_read:       bool,
  has_data:       bool,
  send_heartbeat: Arc<AtomicBool>,
}

impl<T: Evented + Read + Write + Send + 'static> IoLoop<T> {
  pub(crate) fn new(connection: Connection, socket: T) -> Result<Self, Error> {
    let frame_size = std::cmp::max(8192, connection.configuration().frame_max() as usize);
    let (registration, set_readiness) = Registration::new2();
    let inner = Self {
      connection,
      socket,
      status:         Status::Initial,
      poll:           Poll::new().map_err(ErrorKind::IOError)?,
      registration,
      set_readiness,
      hb_handle:      None,
      frame_size,
      receive_buffer: Buffer::with_capacity(FRAMES_STORAGE * frame_size),
      send_buffer:    Buffer::with_capacity(FRAMES_STORAGE * frame_size),
      can_write:      false,
      can_read:       false,
      has_data:       false,
      send_heartbeat: Arc::new(AtomicBool::new(false)),
    };
    inner.poll.register(&inner.socket, SOCKET, Ready::readable() | Ready::writable(), PollOpt::edge()).map_err(ErrorKind::IOError)?;
    inner.poll.register(&inner.connection, DATA, Ready::readable(), PollOpt::edge()).map_err(ErrorKind::IOError)?;
    inner.poll.register(&inner.registration, CONTINUE, Ready::readable(), PollOpt::edge()).map_err(ErrorKind::IOError)?;
    Ok(inner)
  }

  fn start_heartbeat(&mut self, interval: Duration) -> Result<(), Error> {
    let connection    = self.connection.clone();
    let send_hartbeat = self.send_heartbeat.clone();
    let hb_handle = ThreadBuilder::new().name("heartbeat".to_owned()).spawn(move || {
      while connection.status().connected() {
        let start         = Instant::now();
        let mut remaining = interval;

        loop {
          thread::park_timeout(remaining);
          let elapsed = start.elapsed();
          if elapsed >= remaining {
            break
          }
          remaining -= interval - elapsed;
        }

        send_hartbeat.store(true, Ordering::Relaxed);
      }
    }).map_err(ErrorKind::IOError)?;
    self.hb_handle = Some(hb_handle);
    Ok(())
  }

  fn heartbeat(&mut self) -> Result<(), Error> {
    trace!("send heartbeat");
    self.connection.send_heartbeat()?;
    self.send_heartbeat.store(false, Ordering::Relaxed);
    Ok(())
  }

  fn ensure_setup(&mut self) -> Result<(), Error> {
    if self.status != Status::Setup && self.connection.status().connected() {
      let frame_max = self.connection.configuration().frame_max() as usize;
      self.frame_size = std::cmp::max(self.frame_size, frame_max);
      self.receive_buffer.grow(FRAMES_STORAGE * self.frame_size);
      self.send_buffer.grow(FRAMES_STORAGE * self.frame_size);
      let heartbeat = self.connection.configuration().heartbeat();
      if heartbeat != 0 {
        trace!("io_loop: start heartbeat");
        self.start_heartbeat(Duration::from_secs(heartbeat as u64))?;
        trace!("io_loop: heartbeat started");
      }
      self.status = Status::Setup;
    }
    Ok(())
  }

  fn wants_to_write(&self) -> bool {
    self.can_write && self.has_data
  }

  fn wants_to_read(&self) -> bool {
    self.can_read
  }

  fn should_continue(&self) -> bool {
    let connection_status = self.connection.status();
    (self.status == Status::Initial || connection_status.connected() || connection_status.closing()) && self.status != Status::Stop && !connection_status.errored()
  }

  pub(crate) fn run(mut self) -> Result<(), Error> {
    self.connection.clone().set_io_loop(ThreadBuilder::new().name("io_loop".to_owned()).spawn(move || {
      let mut events = Events::with_capacity(1024);
      while self.should_continue() {
        self.do_run(&mut events)?;
      }
      if let Some(hb_handle) = self.hb_handle.take() {
        hb_handle.thread().unpark();
        hb_handle.join().expect("heartbeat loop failed");
      }
      Ok(())
    }).map_err(ErrorKind::IOError)?);
    Ok(())
  }

  fn do_run(&mut self, events: &mut Events) -> Result<(), Error> {
    // First, update our internal state
    trace!("io_loop run");
    self.ensure_setup()?;
    trace!("io_loop poll");
    self.poll.poll(events, None).map_err(ErrorKind::IOError)?;
    trace!("io_loop poll done");
    for event in events.iter() {
      match event.token() {
        SOCKET    => {
          if event.readiness().is_readable() {
            self.can_read = true;
          }
          if event.readiness().is_writable() {
            self.can_write = true;
          }
        },
        DATA      => self.has_data = true,
        _         => {},
      }
    }

    // Then, actually run an iteration of the event loop
    trace!("io_loop do_run; can_read={}, can_write={}, has_data={}", self.can_read, self.can_write, self.has_data);
    loop {
      if self.send_heartbeat.load(Ordering::Relaxed) {
        self.heartbeat()?;
      }
      if self.wants_to_write() && !self.connection.status().blocked() {
        if let Err(e) = self.write_to_stream() {
          match e.kind() {
            ErrorKind::IOError(e) if e.kind() == io::ErrorKind::WouldBlock => self.can_write = false,
            _ => {
              error!("error writing: {:?}", e);
              if let ConnectionState::SentProtocolHeader(wait_handle, ..) = self.connection.status().state() {
                wait_handle.error(ErrorKind::ConnectionRefused.into());
                self.status = Status::Stop;
              }
              self.connection.set_error()?;
              return Err(e);
            }
          }
        }
        self.send_buffer.shift_unless_available(self.frame_size);
      }
      if self.connection.status().closed() {
        self.status = Status::Stop;
      }
      if self.should_continue() && self.wants_to_read() {
        if let Err(e) = self.read_from_stream() {
          match e.kind() {
            ErrorKind::IOError(e) if e.kind() == io::ErrorKind::WouldBlock => self.can_read = false,
            _ => {
              error!("error reading: {:?}", e);
              self.connection.set_error()?;
              return Err(e);
            }
          }
        }
        self.receive_buffer.shift_unless_available(self.frame_size);
      }
      if self.can_parse() {
        self.parse()?;
      }
      if !self.wants_to_read() || !self.wants_to_write() || self.status == Status::Stop || self.connection.status().errored() {
        if self.status != Status::Stop && (self.wants_to_read() || self.can_parse() || self.has_data) {
          trace!("io_loop send continue; can_read={}, can_write={}, has_data={}", self.can_read, self.can_write, self.has_data);
          self.set_readiness.set_readiness(Ready::readable()).map_err(ErrorKind::IOError)?;
        }
        break;
      }
    }
    trace!("io_loop do_run done; can_read={}, can_write={}, has_data={}, status={:?}", self.can_read, self.can_write, self.has_data, self.status);
    Ok(())
  }

  fn can_parse(&self) -> bool {
    self.receive_buffer.available_data() > 0
  }

  fn write_to_stream(&mut self) -> Result<(), Error> {
    self.serialize()?;

    self.socket.write(&self.send_buffer.data()).map(|sz| {
      trace!("wrote {} bytes", sz);
      self.send_buffer.consume(sz);
    }).map_err(|e| ErrorKind::IOError(e).into())
  }

  fn read_from_stream(&mut self) -> Result<(), Error> {
    match self.connection.status().state() {
      ConnectionState::Closed => Ok(()),
      ConnectionState::Error  => Err(ErrorKind::InvalidConnectionState(ConnectionState::Error).into()),
      _                       => self.socket.read(&mut self.receive_buffer.space()).map(|sz| {
        trace!("read {} bytes", sz);
        self.receive_buffer.fill(sz);
      }).map_err(|e| ErrorKind::IOError(e).into()),
    }
  }

  fn serialize(&mut self) -> Result<(), Error> {
    if let Some((send_id, next_msg)) = self.connection.next_frame() {
      trace!("will write to buffer: {:?}", next_msg);
      match gen_frame(self.send_buffer.space(), &next_msg).map(|tup| tup.0) {
        Ok(sz) => {
          self.send_buffer.fill(sz);
          self.connection.mark_sent(send_id);
          Ok(())
        },
        Err(e) => {
          match e {
            GenError::BufferTooSmall(_) => {
              // Requeue msg
              self.connection.requeue_frame(send_id, next_msg)?;
              self.send_buffer.shift();
              Ok(())
            },
            GenError::InvalidOffset | GenError::CustomError(_) | GenError::NotYetImplemented => {
              error!("error generating frame: {:?}", e);
              self.connection.set_error()?;
              Err(ErrorKind::SerialisationError(e).into())
            }
          }
        }
      }
    } else {
      self.has_data = false;
      Ok(())
    }
  }

  fn parse(&mut self) -> Result<(), Error> {
    match parse_frame(self.receive_buffer.data()) {
      Ok((i, f)) => {
        let consumed = self.receive_buffer.data().offset(i);
        self.receive_buffer.consume(consumed);

        if let Err(e) = self.connection.handle_frame(f) {
          self.connection.set_error()?;
          Err(e)
        } else {
          Ok(())
        }
      },
      Err(e) => {
        if e.is_incomplete() {
          self.receive_buffer.shift();
          Ok(())
        } else {
          error!("parse error: {:?}", e);
          self.connection.set_error()?;
          Err(ErrorKind::ParsingError(format!("{:?}", e)).into())
        }
      }
    }
  }
}
<commit_msg>io_loop: register to all events<commit_after>use amq_protocol::frame::{GenError, Offset, gen_frame, parse_frame};
use log::{error, trace};
use mio::{Evented, Events, Poll, PollOpt, Ready, Registration, SetReadiness, Token};
use parking_lot::Mutex;

use std::{
  io::{self, Read, Write},
  sync::{
    Arc,
    atomic::{AtomicBool, Ordering},
  },
  thread::{self, Builder as ThreadBuilder, JoinHandle},
  time::{Duration, Instant},
};

use crate::{
  buffer::Buffer,
  connection::Connection,
  connection_status::ConnectionState,
  error::{Error, ErrorKind},
};

const SOCKET:   Token = Token(1);
const DATA:     Token = Token(2);
const CONTINUE: Token = Token(3);

const FRAMES_STORAGE: usize = 32;

#[derive(Clone, Debug)]
pub(crate) struct IoLoopHandle {
  handle: Arc<Mutex<Option<JoinHandle<Result<(), Error>>>>>,
}

impl Default for IoLoopHandle {
  fn default() -> Self {
    Self { handle: Arc::new(Mutex::new(None)) }
  }
}

impl IoLoopHandle {
  pub(crate) fn register(&self, handle: JoinHandle<Result<(), Error>>) {
    *self.handle.lock() = Some(handle);
  }

  pub(crate) fn wait(&self) -> Result<(), Error> {
    if let Some(handle) = self.handle.lock().take() {
      handle.join().expect("io loop")?
    }
    Ok(())
  }
}

#[derive(Debug, PartialEq)]
enum Status {
  Initial,
  Setup,
  Stop,
}

pub(crate) struct IoLoop<T> {
  connection:     Connection,
  socket:         T,
  status:         Status,
  poll:           Poll,
  registration:   Registration,
  set_readiness:  SetReadiness,
  hb_handle:      Option<JoinHandle<()>>,
  frame_size:     usize,
  receive_buffer: Buffer,
  send_buffer:    Buffer,
  can_write:      bool,
  can_read:       bool,
  has_data:       bool,
  send_heartbeat: Arc<AtomicBool>,
}

impl<T: Evented + Read + Write + Send + 'static> IoLoop<T> {
  pub(crate) fn new(connection: Connection, socket: T) -> Result<Self, Error> {
    let frame_size = std::cmp::max(8192, connection.configuration().frame_max() as usize);
    let (registration, set_readiness) = Registration::new2();
    let inner = Self {
      connection,
      socket,
      status:         Status::Initial,
      poll:           Poll::new().map_err(ErrorKind::IOError)?,
      registration,
      set_readiness,
      hb_handle:      None,
      frame_size,
      receive_buffer: Buffer::with_capacity(FRAMES_STORAGE * frame_size),
      send_buffer:    Buffer::with_capacity(FRAMES_STORAGE * frame_size),
      can_write:      false,
      can_read:       false,
      has_data:       false,
      send_heartbeat: Arc::new(AtomicBool::new(false)),
    };
    inner.poll.register(&inner.socket, SOCKET, Ready::all(), PollOpt::edge()).map_err(ErrorKind::IOError)?;
    inner.poll.register(&inner.connection, DATA, Ready::readable(), PollOpt::edge()).map_err(ErrorKind::IOError)?;
    inner.poll.register(&inner.registration, CONTINUE, Ready::readable(), PollOpt::edge()).map_err(ErrorKind::IOError)?;
    Ok(inner)
  }

  fn start_heartbeat(&mut self, interval: Duration) -> Result<(), Error> {
    let connection    = self.connection.clone();
    let send_hartbeat = self.send_heartbeat.clone();
    let hb_handle = ThreadBuilder::new().name("heartbeat".to_owned()).spawn(move || {
      while connection.status().connected() {
        let start         = Instant::now();
        let mut remaining = interval;

        loop {
          thread::park_timeout(remaining);
          let elapsed = start.elapsed();
          if elapsed >= remaining {
            break
          }
          remaining -= interval - elapsed;
        }

        send_hartbeat.store(true, Ordering::Relaxed);
      }
    }).map_err(ErrorKind::IOError)?;
    self.hb_handle = Some(hb_handle);
    Ok(())
  }

  fn heartbeat(&mut self) -> Result<(), Error> {
    trace!("send heartbeat");
    self.connection.send_heartbeat()?;
    self.send_heartbeat.store(false, Ordering::Relaxed);
    Ok(())
  }

  fn ensure_setup(&mut self) -> Result<(), Error> {
    if self.status != Status::Setup && self.connection.status().connected() {
      let frame_max = self.connection.configuration().frame_max() as usize;
      self.frame_size = std::cmp::max(self.frame_size, frame_max);
      self.receive_buffer.grow(FRAMES_STORAGE * self.frame_size);
      self.send_buffer.grow(FRAMES_STORAGE * self.frame_size);
      let heartbeat = self.connection.configuration().heartbeat();
      if heartbeat != 0 {
        trace!("io_loop: start heartbeat");
        self.start_heartbeat(Duration::from_secs(heartbeat as u64))?;
        trace!("io_loop: heartbeat started");
      }
      self.status = Status::Setup;
    }
    Ok(())
  }

  fn wants_to_write(&self) -> bool {
    self.can_write && self.has_data
  }

  fn wants_to_read(&self) -> bool {
    self.can_read
  }

  fn should_continue(&self) -> bool {
    let connection_status = self.connection.status();
    (self.status == Status::Initial || connection_status.connected() || connection_status.closing()) && self.status != Status::Stop && !connection_status.errored()
  }

  pub(crate) fn run(mut self) -> Result<(), Error> {
    self.connection.clone().set_io_loop(ThreadBuilder::new().name("io_loop".to_owned()).spawn(move || {
      let mut events = Events::with_capacity(1024);
      while self.should_continue() {
        self.do_run(&mut events)?;
      }
      if let Some(hb_handle) = self.hb_handle.take() {
        hb_handle.thread().unpark();
        hb_handle.join().expect("heartbeat loop failed");
      }
      Ok(())
    }).map_err(ErrorKind::IOError)?);
    Ok(())
  }

  fn do_run(&mut self, events: &mut Events) -> Result<(), Error> {
    // First, update our internal state
    trace!("io_loop run");
    self.ensure_setup()?;
    trace!("io_loop poll");
    self.poll.poll(events, None).map_err(ErrorKind::IOError)?;
    trace!("io_loop poll done");
    for event in events.iter() {
      match event.token() {
        SOCKET    => {
          if event.readiness().is_readable() {
            self.can_read = true;
          }
          if event.readiness().is_writable() {
            self.can_write = true;
          }
        },
        DATA      => self.has_data = true,
        _         => {},
      }
    }

    // Then, actually run an iteration of the event loop
    trace!("io_loop do_run; can_read={}, can_write={}, has_data={}", self.can_read, self.can_write, self.has_data);
    loop {
      if self.send_heartbeat.load(Ordering::Relaxed) {
        self.heartbeat()?;
      }
      if self.wants_to_write() && !self.connection.status().blocked() {
        if let Err(e) = self.write_to_stream() {
          match e.kind() {
            ErrorKind::IOError(e) if e.kind() == io::ErrorKind::WouldBlock => self.can_write = false,
            _ => {
              error!("error writing: {:?}", e);
              if let ConnectionState::SentProtocolHeader(wait_handle, ..) = self.connection.status().state() {
                wait_handle.error(ErrorKind::ConnectionRefused.into());
                self.status = Status::Stop;
              }
              self.connection.set_error()?;
              return Err(e);
            }
          }
        }
        self.send_buffer.shift_unless_available(self.frame_size);
      }
      if self.connection.status().closed() {
        self.status = Status::Stop;
      }
      if self.should_continue() && self.wants_to_read() {
        if let Err(e) = self.read_from_stream() {
          match e.kind() {
            ErrorKind::IOError(e) if e.kind() == io::ErrorKind::WouldBlock => self.can_read = false,
            _ => {
              error!("error reading: {:?}", e);
              self.connection.set_error()?;
              return Err(e);
            }
          }
        }
        self.receive_buffer.shift_unless_available(self.frame_size);
      }
      if self.can_parse() {
        self.parse()?;
      }
      if !self.wants_to_read() || !self.wants_to_write() || self.status == Status::Stop || self.connection.status().errored() {
        if self.status != Status::Stop && (self.wants_to_read() || self.can_parse() || self.has_data) {
          trace!("io_loop send continue; can_read={}, can_write={}, has_data={}", self.can_read, self.can_write, self.has_data);
          self.set_readiness.set_readiness(Ready::readable()).map_err(ErrorKind::IOError)?;
        }
        break;
      }
    }
    trace!("io_loop do_run done; can_read={}, can_write={}, has_data={}, status={:?}", self.can_read, self.can_write, self.has_data, self.status);
    Ok(())
  }

  fn can_parse(&self) -> bool {
    self.receive_buffer.available_data() > 0
  }

  fn write_to_stream(&mut self) -> Result<(), Error> {
    self.serialize()?;

    self.socket.write(&self.send_buffer.data()).map(|sz| {
      trace!("wrote {} bytes", sz);
      self.send_buffer.consume(sz);
    }).map_err(|e| ErrorKind::IOError(e).into())
  }

  fn read_from_stream(&mut self) -> Result<(), Error> {
    match self.connection.status().state() {
      ConnectionState::Closed => Ok(()),
      ConnectionState::Error  => Err(ErrorKind::InvalidConnectionState(ConnectionState::Error).into()),
      _                       => self.socket.read(&mut self.receive_buffer.space()).map(|sz| {
        trace!("read {} bytes", sz);
        self.receive_buffer.fill(sz);
      }).map_err(|e| ErrorKind::IOError(e).into()),
    }
  }

  fn serialize(&mut self) -> Result<(), Error> {
    if let Some((send_id, next_msg)) = self.connection.next_frame() {
      trace!("will write to buffer: {:?}", next_msg);
      match gen_frame(self.send_buffer.space(), &next_msg).map(|tup| tup.0) {
        Ok(sz) => {
          self.send_buffer.fill(sz);
          self.connection.mark_sent(send_id);
          Ok(())
        },
        Err(e) => {
          match e {
            GenError::BufferTooSmall(_) => {
              // Requeue msg
              self.connection.requeue_frame(send_id, next_msg)?;
              self.send_buffer.shift();
              Ok(())
            },
            GenError::InvalidOffset | GenError::CustomError(_) | GenError::NotYetImplemented => {
              error!("error generating frame: {:?}", e);
              self.connection.set_error()?;
              Err(ErrorKind::SerialisationError(e).into())
            }
          }
        }
      }
    } else {
      self.has_data = false;
      Ok(())
    }
  }

  fn parse(&mut self) -> Result<(), Error> {
    match parse_frame(self.receive_buffer.data()) {
      Ok((i, f)) => {
        let consumed = self.receive_buffer.data().offset(i);
        self.receive_buffer.consume(consumed);

        if let Err(e) = self.connection.handle_frame(f) {
          self.connection.set_error()?;
          Err(e)
        } else {
          Ok(())
        }
      },
      Err(e) => {
        if e.is_incomplete() {
          self.receive_buffer.shift();
          Ok(())
        } else {
          error!("parse error: {:?}", e);
          self.connection.set_error()?;
          Err(ErrorKind::ParsingError(format!("{:?}", e)).into())
        }
      }
    }
  }
}
<|endoftext|>


<commit_before>//! IPC for way-cooler

use std::thread;
use std::env;
use std::path::PathBuf;
use std::fs;

use unix_socket::UnixListener;

mod channel;
mod command;
mod event;

#[cfg(test)]
mod tests;

/// Versions are incremented.
pub const VERSION: u64 = 0u64; // Increment to 1 on release.

/// Very much not cross-platform!
/// Submit an issue when Wayland is ported to Windoze.
pub const TEMP_FOLDER: &'static str = "/run/way-cooler/";
/// Socket over which synchronous communication is made with clients.
pub const COMMAND_SOCKET: &'static str = "command";
/// Socket over which events are sent to clients.
pub const EVENT_SOCKET: &'static str = "event";
/// Folder in which sockets are created
pub const PATH_VAR: &'static str = "WAY_COOLER_SOCKET_FOLDER";

/// We need random folder names to place sockets in, but they don't need
/// to be _that_ random.
pub fn unique_ish_id() -> u32 {
    use std::hash::{Hash, Hasher, SipHasher};
    use std::time::Instant;

    // If you shift a u64 hash right by this you get a "checksum",
    // a number which retains some of the entropy of the hash but
    // is small enough to fit a more comfortable file name.
    const MAGIC_SHIFT_NUMBER: u64 = 0b110000;

    // Instant doesn't implement hash, and it's supposed to be an opaque
    // struct, but it does implement debug...
    let now = Instant::now();
    let mut hasher = SipHasher::new();
    format!("{:?}", now).hash(&mut hasher);
    (hasher.finish() >> MAGIC_SHIFT_NUMBER) as u32
}

/// Initialize the IPC socket.
pub fn init() {
    let id = unique_ish_id();
    info!("Starting IPC with unique ID {}", id);

    let mut path = PathBuf::from(TEMP_FOLDER);
    path.push(id.to_string());

    if let Err(ioerr) = fs::create_dir_all(path.clone()) {
        // How can we handle not having a socket?
        // In the future, we could log and continue.
        // We could have a config option to not create/create-if-possible
        error!("Unable to create temp folder: {:?}", ioerr);
        return;
    }
    let command_socket = UnixListener::bind(path.join(COMMAND_SOCKET))
        .expect("Unable to open command socket!");

    let event_socket = UnixListener::bind(path.join(EVENT_SOCKET))
        .expect("Unable to open event socket!");

    env::set_var(PATH_VAR, path.clone());

    debug!("IPC initialized, now listening for clients.");

    let _server_handle = thread::Builder::new()
        .name("Command socket listener".to_string())
        .spawn(move || { command_thread(command_socket) });

    let _event_handle = thread::Builder::new()
        .name("Event socket listener".to_string())
        .spawn(move || { event_thread(event_socket) });

    trace!("IPC initialized.");
}

fn command_thread(socket: UnixListener) {
    for stream in socket.incoming() {
        trace!("Sever: new connection: {:?}", stream);
        match stream {
            Ok(mut stream) => {
                info!("Command: connected to {:?}", stream);
                let _handle = thread::Builder::new()
                    .name("IPC server helper".to_string())
                    .spawn(move || command::thread(&mut stream));
            },
            Err(err) => {
                info!("Error receiving a stream: {}", err);
            }
        }
    }
}

fn event_thread(socket: UnixListener) {
    for stream in socket.incoming() {
        trace!("Event: new connection: {:?}", stream);
        match stream {
            Ok(mut stream) => {
                info!("Event: connected to {:?}", stream);
                let _handle = thread::Builder::new()
                    .name("IPC evemt helper".to_string())
                    .spawn(move || event::thread(&mut stream));
            },
            Err(err) => {
                info!("Error receiving a stream: {}", err);
            }
        }
    }
}
<commit_msg>Move IPC socket to /var/run<commit_after>//! IPC for way-cooler

use std::thread;
use std::env;
use std::socket_path::PathBuf;
use std::fs;

use unix_socket::UnixListener;

mod channel;
mod command;
mod event;

#[cfg(test)]
mod tests;

/// Versions are incremented.
pub const VERSION: u64 = 0u64; // Increment to 1 on release.

/// Very much not cross-platform!
/// Submit an issue when Wayland is ported to Windoze.
pub const SOCKET_FOLDER: &'static str = "/var/run/way-cooler/";
/// Socket over which synchronous communication is made with clients.
pub const COMMAND_SOCKET: &'static str = "command";
/// Socket over which events are sent to clients.
pub const EVENT_SOCKET: &'static str = "event";
/// Folder in which sockets are created
pub const PATH_VAR: &'static str = "WAY_COOLER_SOCKET_FOLDER";

/// We need random folder names to place sockets in, but they don't need
/// to be _that_ random.
pub fn unique_ish_id() -> u32 {
    use std::hash::{Hash, Hasher, SipHasher};
    use std::time::Instant;

    // If you shift a u64 hash right by this you get a "checksum",
    // a number which retains some of the entropy of the hash but
    // is small enough to fit a more comfortable file name.
    const MAGIC_SHIFT_NUMBER: u64 = 0b110000;

    // Instant doesn't implement hash, and it's supposed to be an opaque
    // struct, but it does implement debug...
    let now = Instant::now();
    let mut hasher = SipHasher::new();
    format!("{:?}", now).hash(&mut hasher);
    (hasher.finish() >> MAGIC_SHIFT_NUMBER) as u32
}

/// Initialize the IPC socket.
pub fn init() {
    let id = unique_ish_id();
    info!("Starting IPC with unique ID {}", id);

    let mut socket_path = PathBuf::from(SOCKET_FOLDER);
    socket_path.push(id.to_string());

    if let Err(ioerr) = fs::create_dir_all(socket_path.clone()) {
        // How can we handle not having a socket?
        // In the future, we could log and continue.
        // We could have a config option to not create/create-if-possible
        error!("Unable to create temp folder: {:?}", ioerr);
        return;
    }
    let command_socket = UnixListener::bind(socket_path.join(COMMAND_SOCKET))
        .expect("Unable to open command socket!");

    let event_socket = UnixListener::bind(socket_path.join(EVENT_SOCKET))
        .expect("Unable to open event socket!");

    env::set_var(PATH_VAR, socket_path.clone());

    debug!("IPC initialized, now listening for clients.");

    let _server_handle = thread::Builder::new()
        .name("Command socket listener".to_string())
        .spawn(move || { command_thread(command_socket) });

    let _event_handle = thread::Builder::new()
        .name("Event socket listener".to_string())
        .spawn(move || { event_thread(event_socket) });

    trace!("IPC initialized.");
}

fn command_thread(socket: UnixListener) {
    for stream in socket.incoming() {
        trace!("Sever: new connection: {:?}", stream);
        match stream {
            Ok(mut stream) => {
                info!("Command: connected to {:?}", stream);
                let _handle = thread::Builder::new()
                    .name("IPC server helper".to_string())
                    .spawn(move || command::thread(&mut stream));
            },
            Err(err) => {
                info!("Error receiving a stream: {}", err);
            }
        }
    }
}

fn event_thread(socket: UnixListener) {
    for stream in socket.incoming() {
        trace!("Event: new connection: {:?}", stream);
        match stream {
            Ok(mut stream) => {
                info!("Event: connected to {:?}", stream);
                let _handle = thread::Builder::new()
                    .name("IPC evemt helper".to_string())
                    .spawn(move || event::thread(&mut stream));
            },
            Err(err) => {
                info!("Error receiving a stream: {}", err);
            }
        }
    }
}
<|endoftext|>


<commit_before>use unix_socket::UnixStream;

use std::io::{Result, Read, Write};
use std::io::Error;
use std::io::ErrorKind::Other;

use parser::{LvmTextMap, TextMapOps, into_textmap};
use vg;
use parser;

const LVMETAD_PATH: &'static str = "/run/lvm/lvmetad.socket";

fn collect_response(stream: &mut UnixStream) -> Result<Vec<u8>> {
    let mut response = [0; 32];
    let mut v = Vec::new();

    loop {
        let bytes_read = try!(stream.read(&mut response));

        v.extend(&response[..bytes_read]);

        if v.ends_with(b"\n##\n") {
            // drop the end marker
            let len = v.len() - 4;
            v.truncate(len);
            return Ok(v);
        }
    }
}

pub fn _request(s: &[u8],
                token: Option<&[u8]>,
                stream: &mut UnixStream,
                args: Option<&[&[u8]]>) -> Result<Vec<u8>> {
    try!(stream.write_all(b"request = \""));
    try!(stream.write_all(s));
    try!(stream.write_all(b"\"\n"));

    if let Some(token) = token {
        try!(stream.write_all(b"token = \""));
        try!(stream.write_all(token));
        try!(stream.write_all(b"\"\n"));
        try!(stream.write_all(b"\n"));
    }

    if let Some(args) = args {
        for arg in args {
            try!(stream.write_all(arg));
            try!(stream.write_all(b"\n"));
        }
    }

    try!(stream.write_all(b"\n##\n"));

    collect_response(stream)
}

pub fn request(s: &[u8], args: Option<&[&[u8]]>) -> Result<LvmTextMap> {
    let err = || Error::new(Other, "response parsing error");
    let token = b"0";

    let mut stream = try!(UnixStream::connect(LVMETAD_PATH));

    let txt = try!(_request(s, Some(token), &mut stream, args));
    let mut response = try!(into_textmap(&txt));

    if try!(response.string_from_textmap("response").ok_or(err())) == "token_mismatch" {
        try!(_request(b"token_update", Some(token), &mut stream, None));
        response = try!(_request(s, Some(token), &mut stream, args)
            .and_then(|r| into_textmap(&r)));
    }

    if response.get("global_invalid").is_some() || response.get("vg_invalid").is_some() {
        return Err(Error::new(Other, "cached metadata flagged as invalid"));
    }

    if try!(response.string_from_textmap("response").ok_or(err())) != "OK" {
        let reason = match response.string_from_textmap("reason") {
            Some(x) => x,
            None => "no reason given",
        };
        return Err(Error::new(Other, reason));
    }

    response.remove("response");

    Ok(response)
}

pub fn vgs_from_lvmetad() -> Result<Vec<vg::VG>> {
    let err = || Error::new(Other, "response parsing error");
    let mut v = Vec::new();

    let vg_list = try!(request(b"vg_list", None));
    let vgs = try!(vg_list.textmap_from_textmap("volume_groups").ok_or(err()));

    for id in vgs.keys() {
        let name = try!(vgs.textmap_from_textmap(id)
                        .and_then(|val| val.string_from_textmap("name"))
                        .ok_or(err()));

        let mut option: Vec<u8> = Vec::new();
        option.extend(b"uuid = \"");
        option.extend(id.as_bytes());
        option.extend(b"\"");
        let options = vec!(&option[..]);

        let vg_info = try!(request(b"vg_lookup", Some(&options[..])));
        let md = try!(vg_info.textmap_from_textmap("metadata").ok_or(err()));

        let vg = parser::vg_from_textmap(&name, md).expect("didn't get vg!");

        v.push(vg);
    }

    Ok(v)
}
<commit_msg>metad: add vg_update_metad()<commit_after>use unix_socket::UnixStream;

use std::io::{Result, Read, Write};
use std::io::Error;
use std::io::ErrorKind::Other;

use parser::{LvmTextMap, TextMapOps, into_textmap};
use vg;
use parser;

const LVMETAD_PATH: &'static str = "/run/lvm/lvmetad.socket";

fn collect_response(stream: &mut UnixStream) -> Result<Vec<u8>> {
    let mut response = [0; 32];
    let mut v = Vec::new();

    loop {
        let bytes_read = try!(stream.read(&mut response));

        v.extend(&response[..bytes_read]);

        if v.ends_with(b"\n##\n") {
            // drop the end marker
            let len = v.len() - 4;
            v.truncate(len);
            return Ok(v);
        }
    }
}

pub fn _request(s: &[u8],
                token: Option<&[u8]>,
                stream: &mut UnixStream,
                args: Option<&[&[u8]]>) -> Result<Vec<u8>> {
    try!(stream.write_all(b"request = \""));
    try!(stream.write_all(s));
    try!(stream.write_all(b"\"\n"));

    if let Some(token) = token {
        try!(stream.write_all(b"token = \""));
        try!(stream.write_all(token));
        try!(stream.write_all(b"\"\n"));
        try!(stream.write_all(b"\n"));
    }

    if let Some(args) = args {
        for arg in args {
            try!(stream.write_all(arg));
            try!(stream.write_all(b"\n"));
        }
    }

    try!(stream.write_all(b"\n##\n"));

    collect_response(stream)
}

pub fn request(s: &[u8], args: Option<&[&[u8]]>) -> Result<LvmTextMap> {
    let err = || Error::new(Other, "response parsing error");
    let token = b"0";

    let mut stream = try!(UnixStream::connect(LVMETAD_PATH));

    let txt = try!(_request(s, Some(token), &mut stream, args));
    let mut response = try!(into_textmap(&txt));

    if try!(response.string_from_textmap("response").ok_or(err())) == "token_mismatch" {
        try!(_request(b"token_update", Some(token), &mut stream, None));
        response = try!(_request(s, Some(token), &mut stream, args)
            .and_then(|r| into_textmap(&r)));
    }

    if response.get("global_invalid").is_some() || response.get("vg_invalid").is_some() {
        return Err(Error::new(Other, "cached metadata flagged as invalid"));
    }

    if try!(response.string_from_textmap("response").ok_or(err())) != "OK" {
        let reason = match response.string_from_textmap("reason") {
            Some(x) => x,
            None => "no reason given",
        };
        return Err(Error::new(Other, reason));
    }

    response.remove("response");

    Ok(response)
}

pub fn vgs_from_lvmetad() -> Result<Vec<vg::VG>> {
    let err = || Error::new(Other, "response parsing error");
    let mut v = Vec::new();

    let vg_list = try!(request(b"vg_list", None));
    let vgs = try!(vg_list.textmap_from_textmap("volume_groups").ok_or(err()));

    for id in vgs.keys() {
        let name = try!(vgs.textmap_from_textmap(id)
                        .and_then(|val| val.string_from_textmap("name"))
                        .ok_or(err()));

        let mut option: Vec<u8> = Vec::new();
        option.extend(b"uuid = \"");
        option.extend(id.as_bytes());
        option.extend(b"\"");
        let options = vec!(&option[..]);

        let vg_info = try!(request(b"vg_lookup", Some(&options[..])));
        let md = try!(vg_info.textmap_from_textmap("metadata").ok_or(err()));

        let vg = parser::vg_from_textmap(&name, md).expect("didn't get vg!");

        v.push(vg);
    }

    Ok(v)
}

pub fn vg_update_lvmetad(map: &LvmTextMap) -> Result<()> {

    assert_eq!(map.len(), 1);

    let k = map.keys().next().unwrap();
    let v = map.textmap_from_textmap(k).unwrap();

    let mut option = Vec::new();
    option.extend(b"vgname = \"");
    option.extend(k.as_bytes());
    option.extend(b"\"");

    let mut option2 = Vec::new();
    option2.extend(b"metadata {");
    option2.extend(textmap_to_buf(v));
    option2.extend(b"}");

    let mut options: Vec<&[u8]> = Vec::new();

    options.push(&option);
    options.push(&option2);

    try!(request(b"vg_update", Some(options)));

    Ok(())
}
<|endoftext|>


<commit_before>//! This is a collection of string metrics that are suitable for use with a
//! BK-tree.

use std::cmp::min;

use Metric;

/// This calculates the Levenshtein distance between two strings.
///
/// The [distance metric itself][1] is calculated using the [Wagner-Fischer][2]
/// dynamic programming algorithm.
///
/// # Examples
///
/// ```
/// use bk_tree::Metric;
/// use bk_tree::metrics::Levenshtein;
///
/// assert_eq!(Levenshtein.distance("bar", "baz"), 1);
/// assert_eq!(Levenshtein.distance("kitten", "sitting"), 3);
/// ```
///
/// [1]: https://en.wikipedia.org/wiki/Levenshtein_distance
/// [2]: https://en.wikipedia.org/wiki/Wagner%E2%80%93Fischer_algorithm
pub struct Levenshtein;

impl<K: AsRef<str> + ?Sized> Metric<K> for Levenshtein
{
    fn distance(&self, a: &K, b: &K) -> u64 {
        let str_a: &str = a.as_ref();
        let str_b: &str = b.as_ref();

        let len_a: u64 = str_a.chars().collect::<Vec<char>>().len() as u64;
        let len_b: u64 = str_b.chars().collect::<Vec<char>>().len() as u64;
        if len_a == 0 {
            return len_b;
        }
        if len_b == 0 {
            return len_a;
        }

        // This is a case-insensitive algorithm
        let a_lower = str_a.to_lowercase();
        let b_lower = str_b.to_lowercase();

        // Initialize the array
        let mut d: Vec<Vec<u64>> = Vec::new();
        for j in 0..(len_b + 1) {
            let mut cur_vec = Vec::new();
            for i in 0..(len_a + 1) {
                if j == 0 {
                    cur_vec.push(i);
                } else if i == 0 {
                    cur_vec.push(j);
                } else {
                    cur_vec.push(0);
                }
            }
            d.push(cur_vec);
        }

        for j in 0..len_b as usize {
            for i in 0..len_a as usize {
                let chr_a = a_lower.chars().nth(i).unwrap();
                let chr_b = b_lower.chars().nth(j).unwrap();
                if chr_a == chr_b {
                    // If they're the same, then don't modify the value
                    d[j + 1][i + 1] = d[j][i];
                } else {
                    // Otherwise, pick the lowest cost option for an error
                    let deletion = d[j + 1][i] + 1;
                    let insertion = d[j][i + 1] + 1;
                    let substitution = d[j][i] + 1;
                    d[j + 1][i + 1] = min(min(deletion, insertion), substitution);
                }
            }
        }

        d[len_b as usize][len_a as usize]
    }
}
<commit_msg>Clean up Levenshtein function<commit_after>//! This is a collection of string metrics that are suitable for use with a
//! BK-tree.

use std::cmp::min;

use Metric;

/// This calculates the Levenshtein distance between two strings.
///
/// The [distance metric itself][1] is calculated using the [Wagner-Fischer][2]
/// dynamic programming algorithm.
///
/// # Examples
///
/// ```
/// use bk_tree::Metric;
/// use bk_tree::metrics::Levenshtein;
///
/// assert_eq!(Levenshtein.distance("bar", "baz"), 1);
/// assert_eq!(Levenshtein.distance("kitten", "sitting"), 3);
/// ```
///
/// [1]: https://en.wikipedia.org/wiki/Levenshtein_distance
/// [2]: https://en.wikipedia.org/wiki/Wagner%E2%80%93Fischer_algorithm
pub struct Levenshtein;

impl<K: AsRef<str> + ?Sized> Metric<K> for Levenshtein
{
    fn distance(&self, a: &K, b: &K) -> u64 {
        let str_a: &str = a.as_ref();
        let str_b: &str = b.as_ref();

        let len_a = str_a.chars().count();
        let len_b = str_b.chars().count();
        if len_a == 0 {
            return len_b as u64;
        }
        if len_b == 0 {
            return len_a as u64;
        }

        // This is a case-insensitive algorithm
        let a_lower = str_a.to_lowercase();
        let b_lower = str_b.to_lowercase();

        // Initialize the array
        let mut d: Vec<Vec<usize>> = Vec::new();
        for j in 0..(len_b + 1) {
            let mut cur_vec = Vec::new();
            for i in 0..(len_a + 1) {
                if j == 0 {
                    cur_vec.push(i);
                } else if i == 0 {
                    cur_vec.push(j);
                } else {
                    cur_vec.push(0);
                }
            }
            d.push(cur_vec);
        }

        for (j, chr_b) in b_lower.chars().enumerate() {
            for (i, chr_a) in a_lower.chars().enumerate() {
                if chr_a == chr_b {
                    // If they're the same, then don't modify the value
                    d[j + 1][i + 1] = d[j][i];
                } else {
                    // Otherwise, pick the lowest cost option for an error
                    let deletion = d[j + 1][i] + 1;
                    let insertion = d[j][i + 1] + 1;
                    let substitution = d[j][i] + 1;
                    d[j + 1][i + 1] = min(min(deletion, insertion), substitution);
                }
            }
        }

        d[len_b][len_a] as u64
    }
}
<|endoftext|>