<commit_before>use std::fmt;
use std::hash;
use std::mem;

use runtime::{Message, Object};
use {ToMessage};

pub struct Owned;
pub struct Shared;

pub trait Ownership { }
impl Ownership for Owned { }
impl Ownership for Shared { }

#[unsafe_no_drop_flag]
pub struct Id<T: Message, O: Ownership = Owned> {
	ptr: *mut T,
}

impl<T: Message, O: Ownership> Id<T, O> {
	pub unsafe fn from_ptr(ptr: *mut T) -> Id<T, O> {
		match Id::maybe_from_ptr(ptr) {
			Some(id) => id,
			None => panic!("Attempted to construct an Id from a null pointer"),
		}
	}

	pub unsafe fn from_retained_ptr(ptr: *mut T) -> Id<T, O> {
		match Id::maybe_from_retained_ptr(ptr) {
			Some(id) => id,
			None => panic!("Attempted to construct an Id from a null pointer"),
		}
	}

	pub unsafe fn maybe_from_ptr(ptr: *mut T) -> Option<Id<T, O>> {
		// objc_msgSend is a no-op on null pointers
		msg_send![ptr retain];
		Id::maybe_from_retained_ptr(ptr)
	}

	pub unsafe fn maybe_from_retained_ptr(ptr: *mut T) -> Option<Id<T, O>> {
		if ptr.is_null() {
			None
		} else {
			Some(Id { ptr: ptr })
		}
	}
}

impl<T: Message> Id<T, Owned> {
	pub fn share(self) -> ShareId<T> {
		unsafe {
			mem::transmute(self)
		}
	}
}

impl<T: Message, O: Ownership> ToMessage for Id<T, O> {
	fn as_ptr(&self) -> *mut Object {
		self.ptr.as_ptr()
	}
}

impl<T: Message> Clone for Id<T, Shared> {
	fn clone(&self) -> ShareId<T> {
		unsafe { Id::from_ptr(self.ptr) }
	}
}

#[unsafe_destructor]
impl<T: Message, O: Ownership> Drop for Id<T, O> {
	fn drop(&mut self) {
		if !self.ptr.is_null() {
			let ptr = mem::replace(&mut self.ptr, RawPtr::null());
			unsafe {
				msg_send![ptr release];
			}
		}
	}
}

impl<T: Message, O: Ownership> Deref<T> for Id<T, O> {
	fn deref(&self) -> &T {
		unsafe { &*self.ptr }
	}
}

impl<T: Message> DerefMut<T> for Id<T, Owned> {
	fn deref_mut(&mut self) -> &mut T {
		unsafe { &mut *self.ptr }
	}
}

impl<T: Message + PartialEq, O: Ownership> PartialEq for Id<T, O> {
	fn eq(&self, other: &Id<T, O>) -> bool {
		self.deref() == other.deref()
	}

	fn ne(&self, other: &Id<T, O>) -> bool {
		self.deref() != other.deref()
	}
}

impl<T: Message + Eq, O: Ownership> Eq for Id<T, O> { }

impl<T: Message + hash::Hash, O: Ownership> hash::Hash for Id<T, O> {
	fn hash(&self, state: &mut hash::sip::SipState) {
		self.deref().hash(state)
	}
}

impl<T: Message + fmt::Show, O: Ownership> fmt::Show for Id<T, O> {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		self.deref().fmt(f)
	}
}

pub type ShareId<T> = Id<T, Shared>;

pub trait IdVector<T> for Sized? {
	fn as_refs_slice(&self) -> &[&T];
}

impl<T: Message, O: Ownership> IdVector<T> for [Id<T, O>] {
	fn as_refs_slice(&self) -> &[&T] {
		unsafe {
			mem::transmute(self)
		}
	}
}

impl<T: Message, O: Ownership> IdVector<T> for Vec<Id<T, O>> {
	fn as_refs_slice(&self) -> &[&T] {
		self.as_slice().as_refs_slice()
	}
}

pub trait IntoIdVector<T> {
	unsafe fn into_id_vec<O: Ownership>(self) -> Vec<Id<T, O>>;
}

impl<T: Message> IntoIdVector<T> for Vec<*mut T> {
	unsafe fn into_id_vec<O: Ownership>(self) -> Vec<Id<T, O>> {
		for &ptr in self.iter() {
			msg_send![ptr retain];
		}
		mem::transmute(self)
	}
}

impl<'a, T: Message> IntoIdVector<T> for Vec<&'a T> {
	unsafe fn into_id_vec<O: Ownership>(self) -> Vec<Id<T, O>> {
		for &obj in self.iter() {
			msg_send![obj retain];
		}
		mem::transmute(self)
	}
}
<commit_msg>Removed superfluous as_refs_slice implementation.<commit_after>use std::fmt;
use std::hash;
use std::mem;

use runtime::{Message, Object};
use {ToMessage};

pub struct Owned;
pub struct Shared;

pub trait Ownership { }
impl Ownership for Owned { }
impl Ownership for Shared { }

#[unsafe_no_drop_flag]
pub struct Id<T: Message, O: Ownership = Owned> {
	ptr: *mut T,
}

impl<T: Message, O: Ownership> Id<T, O> {
	pub unsafe fn from_ptr(ptr: *mut T) -> Id<T, O> {
		match Id::maybe_from_ptr(ptr) {
			Some(id) => id,
			None => panic!("Attempted to construct an Id from a null pointer"),
		}
	}

	pub unsafe fn from_retained_ptr(ptr: *mut T) -> Id<T, O> {
		match Id::maybe_from_retained_ptr(ptr) {
			Some(id) => id,
			None => panic!("Attempted to construct an Id from a null pointer"),
		}
	}

	pub unsafe fn maybe_from_ptr(ptr: *mut T) -> Option<Id<T, O>> {
		// objc_msgSend is a no-op on null pointers
		msg_send![ptr retain];
		Id::maybe_from_retained_ptr(ptr)
	}

	pub unsafe fn maybe_from_retained_ptr(ptr: *mut T) -> Option<Id<T, O>> {
		if ptr.is_null() {
			None
		} else {
			Some(Id { ptr: ptr })
		}
	}
}

impl<T: Message> Id<T, Owned> {
	pub fn share(self) -> ShareId<T> {
		unsafe {
			mem::transmute(self)
		}
	}
}

impl<T: Message, O: Ownership> ToMessage for Id<T, O> {
	fn as_ptr(&self) -> *mut Object {
		self.ptr.as_ptr()
	}
}

impl<T: Message> Clone for Id<T, Shared> {
	fn clone(&self) -> ShareId<T> {
		unsafe { Id::from_ptr(self.ptr) }
	}
}

#[unsafe_destructor]
impl<T: Message, O: Ownership> Drop for Id<T, O> {
	fn drop(&mut self) {
		if !self.ptr.is_null() {
			let ptr = mem::replace(&mut self.ptr, RawPtr::null());
			unsafe {
				msg_send![ptr release];
			}
		}
	}
}

impl<T: Message, O: Ownership> Deref<T> for Id<T, O> {
	fn deref(&self) -> &T {
		unsafe { &*self.ptr }
	}
}

impl<T: Message> DerefMut<T> for Id<T, Owned> {
	fn deref_mut(&mut self) -> &mut T {
		unsafe { &mut *self.ptr }
	}
}

impl<T: Message + PartialEq, O: Ownership> PartialEq for Id<T, O> {
	fn eq(&self, other: &Id<T, O>) -> bool {
		self.deref() == other.deref()
	}

	fn ne(&self, other: &Id<T, O>) -> bool {
		self.deref() != other.deref()
	}
}

impl<T: Message + Eq, O: Ownership> Eq for Id<T, O> { }

impl<T: Message + hash::Hash, O: Ownership> hash::Hash for Id<T, O> {
	fn hash(&self, state: &mut hash::sip::SipState) {
		self.deref().hash(state)
	}
}

impl<T: Message + fmt::Show, O: Ownership> fmt::Show for Id<T, O> {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		self.deref().fmt(f)
	}
}

pub type ShareId<T> = Id<T, Shared>;

pub trait IdVector<T> for Sized? {
	fn as_refs_slice(&self) -> &[&T];
}

impl<T: Message, O: Ownership> IdVector<T> for [Id<T, O>] {
	fn as_refs_slice(&self) -> &[&T] {
		unsafe {
			mem::transmute(self)
		}
	}
}

pub trait IntoIdVector<T> {
	unsafe fn into_id_vec<O: Ownership>(self) -> Vec<Id<T, O>>;
}

impl<T: Message> IntoIdVector<T> for Vec<*mut T> {
	unsafe fn into_id_vec<O: Ownership>(self) -> Vec<Id<T, O>> {
		for &ptr in self.iter() {
			msg_send![ptr retain];
		}
		mem::transmute(self)
	}
}

impl<'a, T: Message> IntoIdVector<T> for Vec<&'a T> {
	unsafe fn into_id_vec<O: Ownership>(self) -> Vec<Id<T, O>> {
		for &obj in self.iter() {
			msg_send![obj retain];
		}
		mem::transmute(self)
	}
}
<|endoftext|>


<commit_before>extern crate slack;

use std::env;
use std::sync::atomic::{AtomicIsize, Ordering};
use std::sync::mpsc::Sender;
use std::sync::mpsc::Receiver;
use std::sync::mpsc::channel;
use std::thread;

use rustc_serialize::json::Json;
use rustc_serialize::json;
use rustc_serialize::json::DecoderError::MissingFieldError;
use rustc_serialize::Decodable;
use rustc_serialize::Decoder;

use slack::Message;

use message::AdapterMsg;
use message::IncomingMessage;
use adapter::ChatAdapter;

/// SlackAdapter sends and receives messages from the Slack chat service. Until actualy
/// configuration is added, the slack token should be placed in the environment variable
/// `SLACK_BOT_TOKEN`
pub struct SlackAdapter {
    token: String
}

impl SlackAdapter {
    pub fn new() -> SlackAdapter {
        SlackAdapter {
            token: match env::var("SLACK_BOT_TOKEN") {
                Ok(t) => t,
                Err(_) => panic!("Failed to get SLACK_BOT_TOKEN from env")
            }
        }
    }
}

struct MyHandler {
  count: i64,
  tx_bot: Sender<IncomingMessage>,
  tx_adapter: Sender<AdapterMsg>
}

/// Data for a SlackMsg::Message
#[allow(dead_code)]
struct MessageData {
    text: String,
    channel: String,
    user: String,
    ts: String,
    team: String
}

macro_rules! str_accessor {
    ($s:ident) => {
        pub fn $s(&self) -> &str {
            self.$s.as_ref()
        }
    }
}

#[allow(dead_code)]
impl MessageData {
    str_accessor!(text);
    str_accessor!(channel);
    str_accessor!(user);
    str_accessor!(ts);
    str_accessor!(team);
}

/// Incoming slack messages on the websocket api
enum SlackMsg {
    /// A message was sent to a channel
    Message(MessageData),

    /// Some other type of message arrived.
    /// [The list](https://api.slack.com/rtm) is quite extensive, and only the
    /// messages the adapter is concerned with are enumerated here.
    Other
}

impl Decodable for SlackMsg {
    fn decode<D: Decoder>(d: &mut D) -> Result<SlackMsg, D::Error> {
        d.read_struct("root", 0, |root| {
            let msg_type = try!(root.read_struct_field("type", 0, |f| f.read_str() ));

            match msg_type.as_ref() {
                "message" => {
                    Ok(SlackMsg::Message(MessageData {
                        text: try!(root.read_struct_field("text", 0, |f| f.read_str())),
                        channel: try!(root.read_struct_field("channel", 0, |f| f.read_str())),
                        user: try!(root.read_struct_field("user", 0, |f| f.read_str())),
                        ts: try!(root.read_struct_field("ts", 0, |f| f.read_str())),
                        team: try!(root.read_struct_field("team", 0, |f| f.read_str())),
                    }))
                },
                _ => {
                    Ok(SlackMsg::Other)
                }
            }
        })
    }
}

/// Convert a JSON string to a SlackMsg
///
/// This methods provides additional error handling around json::decode for certain errors
/// that cannot be handled in the Decodable implementation. Specifically, MissingFieldError
/// where the field is "type" are actually valid messages despite missing the "type" field.
fn string_to_slack_msg(raw: &str) -> Result<SlackMsg, json::DecoderError> {
    // Some messages arriving from the slack client don't have a type. So far I've only
    // witnessed confirmation messages arriving in this fashion. Since they go through the same
    // pipeline as content messages, the decoder should be able to handle them.
    match json::decode::<SlackMsg>(raw) {
        Ok(value) => Ok(value),
        Err(e) => {
            match e {
                MissingFieldError(field) => {
                    match field.as_ref() {
                        "type" => Ok(SlackMsg::Other),
                        _ => Err(MissingFieldError(field))
                    }
                },
                _ => Err(e)
            }
        }
    }
}

#[allow(unused_variables)]
impl slack::MessageHandler for MyHandler {
    fn on_receive(&mut self, cli: &mut slack::RtmClient, raw: &str) {
        println!("Received[{}]: {}", self.count, raw.to_string());
        self.count = self.count + 1;

        match string_to_slack_msg(raw) {
            Ok(slack_msg) => {
                match slack_msg {
                    SlackMsg::Message(msg) => {
                        let incoming = IncomingMessage::new("SlackAdapter".to_owned(), None,
                            Some(msg.channel().to_owned()), Some(msg.user().to_owned()),
                            msg.text().to_owned(), self.tx_adapter.clone());

                        self.tx_bot.send(incoming).ok().expect("Bot unable to process messages");
                    },
                    _ => ()
                }
            },
            Err(e) => {
                println!("error decoding slack message: {:?}", e);
                println!("please consider reporting this to jwilm/chatbot as it is probably a bug");
            }
        }
    }

    fn on_ping(&mut self, cli: &mut slack::RtmClient) {
        println!("<on_ping>");
    }

    fn on_close(&mut self, cli: &mut slack::RtmClient) {
        println!("<on_close>");
    }

    fn on_connect(&mut self, cli: &mut slack::RtmClient) {
        println!("<on_connect>");
        // let _ = cli.send_message("#general", "bla");
    }
}

impl ChatAdapter for SlackAdapter {
    /// SlackAdapter name
    fn get_name(&self) -> &str {
        "SlackAdapter"
    }

    fn process_events(&self) -> Receiver<IncomingMessage> {
        println!("SlackAdapter: process_events");
        let (tx_bot, rx_bot) = channel();
        let (tx_adapter, rx_adapter) = channel();

        let uid = AtomicIsize::new(0);

        let mut cli = slack::RtmClient::new();
        let (client, slack_rx) = cli.login(self.token.as_ref()).unwrap();
        let slack_tx = cli.get_outs().unwrap();

        thread::Builder::new().name("Chatbot Slack Receiver".to_owned()).spawn(move || {
            let mut handler = MyHandler{count: 0, tx_bot: tx_bot, tx_adapter: tx_adapter};
            cli.run::<MyHandler>(&mut handler, client, slack_rx).unwrap();
        }).ok().expect("failed to create thread for slack receiver");

        thread::Builder::new().name("Chatbot Slack Sender".to_owned()).spawn(move || {
            loop {
                match rx_adapter.recv() {
                    Ok(msg) => {
                        match msg {
                            AdapterMsg::Outgoing(msg) => {
                                let n = uid.fetch_add(1, Ordering::SeqCst);
                                let chan = msg.get_incoming().channel().unwrap();
                                let payload = msg.as_ref();
                                let mut obj = json::Object::new();
                                obj.insert("id".to_string(), Json::I64(n as i64));
                                obj.insert("channel".to_string(), Json::String(chan.to_owned()));
                                obj.insert("type".to_string(), Json::String("message".to_owned()));
                                obj.insert("text".to_string(), Json::String(payload.to_owned()));
                                let json = Json::Object(obj);
                                let slack_msg = Message::Text(json.to_string());
                                slack_tx.send(slack_msg).unwrap();
                            }
                            _ => println!("TODO")
                        }
                    },
                    Err(e) => {
                        println!("error receiving outgoing messages to the slack adapter: {}", e);
                        break
                    }
                }
            }
        }).ok().expect("failed to create thread for slack sender");

        rx_bot
    }
}

#[cfg(test)]
mod tests {
    use adapter::slack::SlackMsg;
    use adapter::slack::string_to_slack_msg;

    #[test]
    fn decode_message() {
        let raw = "{\"type\":\"message\", \
                    \"channel\":\"D04UYUAMW\", \
                    \"user\":\"U02ALMR84\", \
                    \"text\":\"ping\", \
                    \"ts\":\"1432563914.000007\", \
                    \"team\":\"T02ALMR82\"}";

        let slack_msg = string_to_slack_msg(raw).unwrap();

        match slack_msg {
            SlackMsg::Message(data) => {
                assert_eq!(data.text(), "ping");
                assert_eq!(data.channel(), "D04UYUAMW");
                assert_eq!(data.user(), "U02ALMR84");
                assert_eq!(data.ts(), "1432563914.000007");
                assert_eq!(data.team(), "T02ALMR82");
            },
            _ => panic!("Expected SlackMsg::Message")
        }
    }
    #[test]
    fn decode_confirmation_message() {
        let raw = r#"{"ok":true,"reply_to":0,"ts":"1432566639.000014","text":"pong"}"#;

        match string_to_slack_msg(raw).unwrap() {
            SlackMsg::Other => (),
            _ => panic!("expected SlackMsg::Other")
        }
    }

    #[test]
    fn decode_unexpected_type() {
        let raw = r#"{"type":"not_a_slack_msg_type"}"#;

        match string_to_slack_msg(raw).unwrap() {
            SlackMsg::Other => (),
            _ => panic!("expected SlackMsg::Other")
        }
    }
}
<commit_msg>Add OutgoingSlackMsg type<commit_after>extern crate slack;

use std::collections::BTreeMap;
use std::env;
use std::sync::atomic::{AtomicIsize, Ordering};
use std::sync::mpsc::Sender;
use std::sync::mpsc::Receiver;
use std::sync::mpsc::channel;
use std::thread;

use rustc_serialize::json::{self, Json, ToJson};
use rustc_serialize::json::DecoderError::MissingFieldError;
use rustc_serialize::Decodable;
use rustc_serialize::Decoder;

use slack::Message;

use adapter::ChatAdapter;
use message::AdapterMsg;
use message::IncomingMessage;
use message::OutgoingMessage;

/// SlackAdapter sends and receives messages from the Slack chat service. Until actualy
/// configuration is added, the slack token should be placed in the environment variable
/// `SLACK_BOT_TOKEN`
pub struct SlackAdapter {
    token: String
}

impl SlackAdapter {
    pub fn new() -> SlackAdapter {
        SlackAdapter {
            token: match env::var("SLACK_BOT_TOKEN") {
                Ok(t) => t,
                Err(_) => panic!("Failed to get SLACK_BOT_TOKEN from env")
            }
        }
    }
}

struct MyHandler {
  count: i64,
  tx_bot: Sender<IncomingMessage>,
  tx_adapter: Sender<AdapterMsg>
}

/// Data for a SlackMsg::Message
#[allow(dead_code)]
struct MessageData {
    text: String,
    channel: String,
    user: String,
    ts: String,
    team: String
}

macro_rules! str_accessor {
    ($s:ident) => {
        pub fn $s(&self) -> &str {
            self.$s.as_ref()
        }
    }
}

#[allow(dead_code)]
impl MessageData {
    str_accessor!(text);
    str_accessor!(channel);
    str_accessor!(user);
    str_accessor!(ts);
    str_accessor!(team);
}

/// Incoming slack messages on the websocket api
enum SlackMsg {
    /// A message was sent to a channel
    Message(MessageData),

    /// Some other type of message arrived.
    /// [The list](https://api.slack.com/rtm) is quite extensive, and only the
    /// messages the adapter is concerned with are enumerated here.
    Other
}

impl Decodable for SlackMsg {
    fn decode<D: Decoder>(d: &mut D) -> Result<SlackMsg, D::Error> {
        d.read_struct("root", 0, |root| {
            let msg_type = try!(root.read_struct_field("type", 0, |f| f.read_str() ));

            match msg_type.as_ref() {
                "message" => {
                    Ok(SlackMsg::Message(MessageData {
                        text: try!(root.read_struct_field("text", 0, |f| f.read_str())),
                        channel: try!(root.read_struct_field("channel", 0, |f| f.read_str())),
                        user: try!(root.read_struct_field("user", 0, |f| f.read_str())),
                        ts: try!(root.read_struct_field("ts", 0, |f| f.read_str())),
                        team: try!(root.read_struct_field("team", 0, |f| f.read_str())),
                    }))
                },
                _ => {
                    Ok(SlackMsg::Other)
                }
            }
        })
    }
}

/// Convert a JSON string to a SlackMsg
///
/// This methods provides additional error handling around json::decode for certain errors
/// that cannot be handled in the Decodable implementation. Specifically, MissingFieldError
/// where the field is "type" are actually valid messages despite missing the "type" field.
fn string_to_slack_msg(raw: &str) -> Result<SlackMsg, json::DecoderError> {
    // Some messages arriving from the slack client don't have a type. So far I've only
    // witnessed confirmation messages arriving in this fashion. Since they go through the same
    // pipeline as content messages, the decoder should be able to handle them.
    match json::decode::<SlackMsg>(raw) {
        Ok(value) => Ok(value),
        Err(e) => {
            match e {
                MissingFieldError(field) => {
                    match field.as_ref() {
                        "type" => Ok(SlackMsg::Other),
                        _ => Err(MissingFieldError(field))
                    }
                },
                _ => Err(e)
            }
        }
    }
}

#[derive(Debug)]
struct OutgoingSlackMsg {
    id: i64,
    channel: String,
    msg_type: String,
    text: String
}

impl OutgoingSlackMsg {
    fn new(id: i64, m: OutgoingMessage) -> OutgoingSlackMsg {
        OutgoingSlackMsg {
            id: id,
            channel: m.get_incoming()
                      .channel()
                      .expect("missing channel").to_owned(),
            msg_type: "message".to_owned(),
            text: m.as_ref().to_owned() // TODO move instead of copy
        }
    }
}

impl ToJson for OutgoingSlackMsg {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("id".to_string(), self.id.to_json());
        d.insert("channel".to_string(), self.channel.to_json());
        d.insert("type".to_string(), self.msg_type.to_json());
        d.insert("text".to_string(), self.text.to_json());
        Json::Object(d)
    }
}

#[allow(unused_variables)]
impl slack::MessageHandler for MyHandler {
    fn on_receive(&mut self, cli: &mut slack::RtmClient, raw: &str) {
        println!("Received[{}]: {}", self.count, raw.to_string());
        self.count = self.count + 1;

        match string_to_slack_msg(raw) {
            Ok(slack_msg) => {
                match slack_msg {
                    SlackMsg::Message(msg) => {
                        let incoming = IncomingMessage::new("SlackAdapter".to_owned(), None,
                            Some(msg.channel().to_owned()), Some(msg.user().to_owned()),
                            msg.text().to_owned(), self.tx_adapter.clone());

                        self.tx_bot.send(incoming).ok().expect("Bot unable to process messages");
                    },
                    _ => ()
                }
            },
            Err(e) => {
                println!("error decoding slack message: {:?}", e);
                println!("please consider reporting this to jwilm/chatbot as it is probably a bug");
            }
        }
    }

    fn on_ping(&mut self, cli: &mut slack::RtmClient) { }

    fn on_close(&mut self, cli: &mut slack::RtmClient) { }

    fn on_connect(&mut self, cli: &mut slack::RtmClient) { }
}

impl ChatAdapter for SlackAdapter {
    /// SlackAdapter name
    fn get_name(&self) -> &str {
        "SlackAdapter"
    }

    fn process_events(&self) -> Receiver<IncomingMessage> {
        println!("SlackAdapter: process_events");
        let (tx_bot, rx_bot) = channel();
        let (tx_adapter, rx_adapter) = channel();

        let uid = AtomicIsize::new(0);

        let mut cli = slack::RtmClient::new();
        let (client, slack_rx) = cli.login(self.token.as_ref()).unwrap();
        let slack_tx = cli.get_outs().unwrap();

        thread::Builder::new().name("Chatbot Slack Receiver".to_owned()).spawn(move || {
            let mut handler = MyHandler{count: 0, tx_bot: tx_bot, tx_adapter: tx_adapter};
            cli.run::<MyHandler>(&mut handler, client, slack_rx).unwrap();
        }).ok().expect("failed to create thread for slack receiver");

        thread::Builder::new().name("Chatbot Slack Sender".to_owned()).spawn(move || {
            loop {
                match rx_adapter.recv() {
                    Ok(msg) => {
                        match msg {
                            AdapterMsg::Outgoing(m) => {
                                let id = uid.fetch_add(1, Ordering::SeqCst) as i64;
                                let out = OutgoingSlackMsg::new(id, m);
                                slack_tx.send(Message::Text(out.to_json().to_string())).unwrap();
                            }
                            _ => unreachable!("No other messages being sent yet")
                        }
                    },
                    Err(e) => {
                        println!("error receiving outgoing messages: {}", e);
                        break
                    }
                }
            }
        }).ok().expect("failed to create thread for slack sender");

        rx_bot
    }
}

#[cfg(test)]
mod tests {
    use adapter::slack::SlackMsg;
    use adapter::slack::string_to_slack_msg;

    #[test]
    fn decode_message() {
        let raw = "{\"type\":\"message\", \
                    \"channel\":\"D04UYUAMW\", \
                    \"user\":\"U02ALMR84\", \
                    \"text\":\"ping\", \
                    \"ts\":\"1432563914.000007\", \
                    \"team\":\"T02ALMR82\"}";

        let slack_msg = string_to_slack_msg(raw).unwrap();

        match slack_msg {
            SlackMsg::Message(data) => {
                assert_eq!(data.text(), "ping");
                assert_eq!(data.channel(), "D04UYUAMW");
                assert_eq!(data.user(), "U02ALMR84");
                assert_eq!(data.ts(), "1432563914.000007");
                assert_eq!(data.team(), "T02ALMR82");
            },
            _ => panic!("Expected SlackMsg::Message")
        }
    }
    #[test]
    fn decode_confirmation_message() {
        let raw = r#"{"ok":true,"reply_to":0,"ts":"1432566639.000014","text":"pong"}"#;

        match string_to_slack_msg(raw).unwrap() {
            SlackMsg::Other => (),
            _ => panic!("expected SlackMsg::Other")
        }
    }

    #[test]
    fn decode_unexpected_type() {
        let raw = r#"{"type":"not_a_slack_msg_type"}"#;

        match string_to_slack_msg(raw).unwrap() {
            SlackMsg::Other => (),
            _ => panic!("expected SlackMsg::Other")
        }
    }
}
<|endoftext|>


<commit_before>extern crate winapi;
extern crate ws2_32;

use std::io;
use std::os::windows::io::{AsRawSocket, RawSocket};

use self::winapi::{c_int, LPWSABUF};

use self::ws2_32::{WSASend, WSARecv};

use ::{Rawv, Writev, Readv};

struct WinSock(RawSocket);

impl<T: AsRawSocket> Rawv for T {
    fn readv(&mut self, buffers: &[&mut [u8]]) -> io::Result<usize> {
        WinSock(self.as_raw_socket()).readv(buffers)
    }

    fn writev(&mut self, buffers: &[&[u8]]) -> io::Result<usize> {
        WinSock(self.as_raw_socket()).writev(buffers)
    }
}

impl Writev for WinSock {
    fn writev(&mut self, buffers: &[&[u8]]) -> io::Result<usize> {
        unsafe {
            let mut bytes = 0;
            let ret = WSASend(
                self.0,
                buffers.as_ptr() as LPWSABUF,
                buffers.len() as c_int,
                &mut bytes,
                0,
                0,
                0
            );
            if ret != 0 {
                Err(io::Error::last_os_error())
            } else {
                Ok(bytes as usize)
            }
        }
    }
}

impl Readv for WinSock {
    fn readv(&mut self, buffers: &[&mut [u8]]) -> io::Result<usize> {
        unsafe {
            let mut bytes = 0;
            let ret = WSARecv(
                self.0,
                buffers.as_ptr() as LPWSABUF,
                buffers.len() as c_int,
                &mut bytes,
                0,
                0,
                0
            );
            if ret != 0 {
                Err(io::Error::last_os_error())
            } else {
                Ok(ret as usize)
            }
        }
    }
}
<commit_msg>fix types for WSA<commit_after>extern crate winapi;
extern crate ws2_32;

use std::io;
use std::os::windows::io::{AsRawSocket, RawSocket};

use self::winapi::{DWORD, LPWSABUF};

use self::ws2_32::{WSASend, WSARecv};

use ::{Rawv, Writev, Readv};

struct WinSock(RawSocket);

impl<T: AsRawSocket> Rawv for T {
    fn readv(&mut self, buffers: &[&mut [u8]]) -> io::Result<usize> {
        WinSock(self.as_raw_socket()).readv(buffers)
    }

    fn writev(&mut self, buffers: &[&[u8]]) -> io::Result<usize> {
        WinSock(self.as_raw_socket()).writev(buffers)
    }
}

impl Writev for WinSock {
    fn writev(&mut self, buffers: &[&[u8]]) -> io::Result<usize> {
        unsafe {
            let mut bytes = 0;
            let ret = WSASend(
                self.0,
                buffers.as_ptr() as LPWSABUF,
                buffers.len() as DWORD,
                &mut bytes,
                0,
                0 as *const _,
                None
            );
            if ret != 0 {
                Err(io::Error::last_os_error())
            } else {
                Ok(bytes as usize)
            }
        }
    }
}

impl Readv for WinSock {
    fn readv(&mut self, buffers: &[&mut [u8]]) -> io::Result<usize> {
        unsafe {
            let mut bytes = 0;
            let ret = WSARecv(
                self.0,
                buffers.as_ptr() as LPWSABUF,
                buffers.len() as DWORD,
                &mut bytes,
                0,
                0 as *const _,
                None
            );
            if ret != 0 {
                Err(io::Error::last_os_error())
            } else {
                Ok(ret as usize)
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::boxed::FnBox;
use std::thread::{self, spawn, JoinHandle};
use std::sync::mpsc::{channel, Sender, SendError, Receiver};
use std::sync::{Arc, Mutex};
use std::error::Error;
use std::fmt;

use queue;
use mpmc_channel;

trait Runner {
    fn run(self: Box<Self>);
}

impl <F: FnBox()> Runner for F {
    fn run(self: Box<F>) {
        self.call_box(())
    }
}

type Proc<'a> = Box<Runner + Send + 'a>;

#[derive(Clone)]
pub struct Thread {
    inner: ThreadInner
}

#[derive(Clone)]
struct ThreadInner {
    sender: Sender<Proc<'static>>,
    result: queue::Receiver<thread::Result<()>>,
}

impl Thread {
    fn new(sender: Sender<Proc<'static>>, result: queue::Receiver<thread::Result<()>>) -> Thread {
        Thread {
            inner: ThreadInner {
                       sender: sender,
                       result: result,
                   },
        }
    }

    pub fn start(&self, f: Proc<'static>) -> Result<(), SendError<Proc<'static>>> {
        self.inner.sender.send(f)
    }

    pub fn join(&self) -> thread::Result<()> {
        self.inner.result.recv().unwrap()
    }
}

pub struct ThreadPool {
    id_sender: Sender<usize>, // Keep this for spawning new threads.
    free_threads: Receiver<usize>, // Threads will send their id when they are free.
    thread_handles: Arc<Mutex<Vec<JoinHandle<()>>>>, // Active threads
    threads: Arc<Mutex<Vec<Thread>>>, // Threads
    max_threads: usize,
}

fn initialize(init_threads: usize, id_sender: Sender<usize>, threads: &Arc<Mutex<Vec<Thread>>>, handles: &Arc<Mutex<Vec<JoinHandle<()>>>>) {
    let mut locked_thrs = threads.lock().unwrap();
    let mut locked_handles = handles.lock().unwrap();

    for i in 0..init_threads {
        let (handle, thread) = spawn_thread(i, id_sender.clone(), threads.clone(), handles.clone());
        locked_handles.push(handle);
        locked_thrs.push(thread);
    }
}

fn spawn_thread(id: usize, free: Sender<usize>, threads: Arc<Mutex<Vec<Thread>>>, handles: Arc<Mutex<Vec<JoinHandle<()>>>>) -> (JoinHandle<()>, Thread) {
        let (thr, jobs) = channel();
        let (res_sender, res_recver) = mpmc_channel(1);
        let thread = Thread::new(thr, res_recver);

        let handle = spawn(move || {
            let sentinel = Sentinel::new(id, handles, threads);
            ThreadRunner::new(id, res_sender, free, jobs).run();
            sentinel.done();
        });

        (handle, thread)
}

impl ThreadPool {
    pub fn new(init_threads: usize, max_threads: usize) -> ThreadPool {
        let (sn, rc) = channel();
        let threads = Arc::new(Mutex::new(Vec::new()));
        let handles = Arc::new(Mutex::new(Vec::new()));

        initialize(init_threads, sn.clone(), &threads, &handles);

        ThreadPool {
            id_sender: sn,
            free_threads: rc,
            thread_handles: handles,
            threads: threads,
            max_threads: max_threads
        }
    }

    pub fn thread(&self) -> Result<Thread, ThreadError> {
        let thr_id = self.free_threads.recv().expect("Could not receive free thread id");
        let thrs = self.threads.lock().unwrap();
        if thrs.len() >= self.max_threads {
            Err(ThreadError)
        } else {
            Ok(thrs[thr_id].clone())
        }
    }
}

#[derive(Debug, Clone)]
pub struct ThreadError;

impl Error for ThreadError {
    fn description(&self) -> &str {
        "Could not make any more threads."
    }
}

impl fmt::Display for ThreadError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        "Could not make any more threads.".fmt(f)
    }
}

struct Sentinel {
    id: usize,
    thread_handles: Arc<Mutex<Vec<JoinHandle<()>>>>, // Active threads
    threads: Arc<Mutex<Vec<Thread>>>, // Thread job queues
    active: bool,
}

// Idea taken from https://github.com/rust-lang/threadpool/blob/b9416b4cb591a3ac8bac8efef19e5cbf5e212a9d/src/lib.rs#L40
impl Sentinel {
    fn new(
        id: usize,
        thread_handles: Arc<Mutex<Vec<JoinHandle<()>>>>,
        threads: Arc<Mutex<Vec<Thread>>>
        ) -> Sentinel {
        Sentinel {
            id: id,
            thread_handles: thread_handles,
            threads: threads,
            active: true,
        }
    }

    // Cancel and destroy this sentinel.
    fn done(mut self) {
        self.active = false;
    }
}

impl Drop for Sentinel {
    fn drop(&mut self) {
        if self.active {
            // Spawn new thread and remove old one.
        }
    }
}

struct ThreadRunner {
    id: usize,
    result_chan: queue::Sender<thread::Result<()>>,
    free_chan: Sender<usize>, // ThreadRunner will send its id when it is ready to do work
    jobs: Receiver<Proc<'static>>, // Job queue
}

impl ThreadRunner {
    pub fn new(id: usize, result_chan: queue::Sender<thread::Result<()>>, free_chan: Sender<usize>, jobs: Receiver<Proc<'static>>) -> ThreadRunner {
        ThreadRunner {
            id: id,
            result_chan: result_chan,
            free_chan: free_chan,
            jobs: jobs,
        }
    }

    fn run(self) {
        self.free_chan.send(self.id).unwrap();
        loop {
            let job = self.jobs.recv().unwrap();
            let res = thread::catch_panic(move || { job.run(); });
            self.result_chan.send(res).unwrap();
            self.free_chan.send(self.id).unwrap();
        }
    }
}

#[cfg(test)]
mod test {
    use std::sync::mpsc::{channel};
    // use std::time::{Duration};
    // use std::thread::{sleep};
    use thread_pool::{ThreadPool, Runner};

    #[test]
    fn test_runable() {
        let (sn, rc) = channel::<u8>();
        let f = box move || {
            sn.send(0u8).unwrap();
        };
        f.run();
        assert!(rc.recv().unwrap() == 0);
    }

    #[test]
    fn test_thread_pool_thread_and_start() {
        let (sn, rc) = channel::<u8>();
        let (init, max) = (1, 2);
        let pool = ThreadPool::new(init, max);

        let f = box move || {
            sn.send(0u8).unwrap();
        };

        let thr1 = pool.thread();
        let thr2 = pool.thread();
        let thr3 = pool.thread();
        assert!(thr3.is_err());

        let thr1 = thr1.ok().unwrap();

        let res = thr1.start(f);
        assert!(res.is_ok());

        assert!(rc.recv().unwrap() == 0);
    }

    #[test]
    fn test_thread_pool_join() {
        let (sn1, rc1) = channel::<u8>();
        let (init, max) = (1, 2);
        let pool = ThreadPool::new(init, max);

        let f1 = box move || {
            sn1.send(0u8).unwrap();
        };

        let f2 = box move || {
            panic!();
        };

        // Initial thread.
        let thr1 = pool.thread();
        // Start a new one.
        let thr2 = pool.thread();
        let thr1 = thr1.ok().unwrap();
        let thr2 = thr2.ok().unwrap();

        thr1.start(f1);
        thr2.start(f2);
        let res = thr1.join();
        assert!(res.is_ok());

        let res = thr2.join();
        assert!(res.is_err());
    }

    #[test]
    fn test_thread_pool_max_threads_panic() {
        let (sn1, rc1) = channel::<u8>();
        let (init, max) = (1, 2);
        let pool = ThreadPool::new(init, max);

        let f1 = box move || {
            sn1.send(0u8).unwrap();
        };

        let f2 = box move || {
            panic!();
        };

        // Initial thread.
        let thr1 = pool.thread();
        // Start a new one.
        let thr2 = pool.thread();
        let thr1 = thr1.ok().unwrap();
        let thr2 = thr2.ok().unwrap();

        thr2.start(f2);
        let res = thr2.join();
        assert!(res.is_err());

        let thr3 = pool.thread();
        // Can still get thread after panic
        assert!(thr3.is_ok());

        thr1.start(f1);
        let res = thr1.join();
        assert!(res.is_ok());
    }
}
<commit_msg>Use try_recv when reading from free id channel.<commit_after>use std::boxed::FnBox;
use std::thread::{self, spawn, JoinHandle};
use std::sync::mpsc::{channel, Sender, SendError, Receiver, TryRecvError};
use std::sync::{Arc, Mutex};
use std::error::Error;
use std::fmt;

use queue;
use mpmc_channel;

trait Runner {
    fn run(self: Box<Self>);
}

impl <F: FnBox()> Runner for F {
    fn run(self: Box<F>) {
        self.call_box(())
    }
}

type Proc<'a> = Box<Runner + Send + 'a>;

#[derive(Clone)]
pub struct Thread {
    inner: ThreadInner
}

#[derive(Clone)]
struct ThreadInner {
    sender: Sender<Proc<'static>>,
    result: queue::Receiver<thread::Result<()>>,
}

impl Thread {
    fn new(sender: Sender<Proc<'static>>, result: queue::Receiver<thread::Result<()>>) -> Thread {
        Thread {
            inner: ThreadInner {
                       sender: sender,
                       result: result,
                   },
        }
    }

    pub fn start(&self, f: Proc<'static>) -> Result<(), SendError<Proc<'static>>> {
        self.inner.sender.send(f)
    }

    pub fn join(&self) -> thread::Result<()> {
        self.inner.result.recv().unwrap()
    }
}

pub struct ThreadPool {
    id_sender: Sender<usize>, // Keep this for spawning new threads.
    free_threads: Receiver<usize>, // Threads will send their id when they are free.
    thread_handles: Arc<Mutex<Vec<JoinHandle<()>>>>, // Active threads
    threads: Arc<Mutex<Vec<Thread>>>, // Threads
    max_threads: usize,
}

fn initialize(init_threads: usize, id_sender: Sender<usize>, threads: &Arc<Mutex<Vec<Thread>>>, handles: &Arc<Mutex<Vec<JoinHandle<()>>>>) {
    let mut locked_thrs = threads.lock().unwrap();
    let mut locked_handles = handles.lock().unwrap();

    for i in 0..init_threads {
        let (handle, thread) = spawn_thread(i, id_sender.clone(), threads.clone(), handles.clone());
        locked_handles.push(handle);
        locked_thrs.push(thread);
    }
}

fn spawn_thread(id: usize, free: Sender<usize>, threads: Arc<Mutex<Vec<Thread>>>, handles: Arc<Mutex<Vec<JoinHandle<()>>>>) -> (JoinHandle<()>, Thread) {
        let (thr, jobs) = channel();
        let (res_sender, res_recver) = mpmc_channel(1);
        let thread = Thread::new(thr, res_recver);

        let handle = spawn(move || {
            let sentinel = Sentinel::new(id, handles, threads);
            ThreadRunner::new(id, res_sender, free, jobs).run();
            sentinel.done();
        });

        (handle, thread)
}

impl ThreadPool {
    pub fn new(init_threads: usize, max_threads: usize) -> ThreadPool {
        let (sn, rc) = channel();
        let threads = Arc::new(Mutex::new(Vec::new()));
        let handles = Arc::new(Mutex::new(Vec::new()));

        initialize(init_threads, sn.clone(), &threads, &handles);

        ThreadPool {
            id_sender: sn,
            free_threads: rc,
            thread_handles: handles,
            threads: threads,
            max_threads: max_threads
        }
    }

    pub fn thread(&self) -> Result<Thread, ThreadError> {
        let thrs = self.threads.lock().unwrap();
        if thrs.len() >= self.max_threads {
            Err(ThreadError)
        } else {
            let res = self.free_threads.try_recv();
            match res {
                Ok(thr_id) => Ok(thrs[thr_id].clone()),
                Err(TryRecvError::Empty) => Err(ThreadError),
                Err(TryRecvError::Disconnected) => panic!("channel closed"),
            }
        }
    }
}

#[derive(Debug, Clone)]
pub struct ThreadError;

impl Error for ThreadError {
    fn description(&self) -> &str {
        "Could not make any more threads."
    }
}

impl fmt::Display for ThreadError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        "Could not make any more threads.".fmt(f)
    }
}

struct Sentinel {
    id: usize,
    thread_handles: Arc<Mutex<Vec<JoinHandle<()>>>>, // Active threads
    threads: Arc<Mutex<Vec<Thread>>>, // Thread job queues
    active: bool,
}

// Idea taken from https://github.com/rust-lang/threadpool/blob/b9416b4cb591a3ac8bac8efef19e5cbf5e212a9d/src/lib.rs#L40
impl Sentinel {
    fn new(
        id: usize,
        thread_handles: Arc<Mutex<Vec<JoinHandle<()>>>>,
        threads: Arc<Mutex<Vec<Thread>>>
        ) -> Sentinel {
        Sentinel {
            id: id,
            thread_handles: thread_handles,
            threads: threads,
            active: true,
        }
    }

    // Cancel and destroy this sentinel.
    fn done(mut self) {
        self.active = false;
    }
}

impl Drop for Sentinel {
    fn drop(&mut self) {
        if self.active {
            // Spawn new thread and remove old one.
        }
    }
}

struct ThreadRunner {
    id: usize,
    result_chan: queue::Sender<thread::Result<()>>,
    free_chan: Sender<usize>, // ThreadRunner will send its id when it is ready to do work
    jobs: Receiver<Proc<'static>>, // Job queue
}

impl ThreadRunner {
    pub fn new(id: usize, result_chan: queue::Sender<thread::Result<()>>, free_chan: Sender<usize>, jobs: Receiver<Proc<'static>>) -> ThreadRunner {
        ThreadRunner {
            id: id,
            result_chan: result_chan,
            free_chan: free_chan,
            jobs: jobs,
        }
    }

    fn run(self) {
        self.free_chan.send(self.id).unwrap();
        loop {
            let job = self.jobs.recv().unwrap();
            let res = thread::catch_panic(move || { job.run(); });
            self.result_chan.send(res).unwrap();
            self.free_chan.send(self.id).unwrap();
        }
    }
}

#[cfg(test)]
mod test {
    use std::sync::mpsc::{channel};
    use thread_pool::{ThreadPool, Runner};

    #[test]
    fn test_runable() {
        let (sn, rc) = channel::<u8>();
        let f = box move || {
            sn.send(0u8).unwrap();
        };
        f.run();
        assert!(rc.recv().unwrap() == 0);
    }

    #[test]
    fn test_thread_pool_thread_and_start() {
        let (sn, rc) = channel::<u8>();
        let (init, max) = (1, 2);
        let pool = ThreadPool::new(init, max);

        let f = box move || {
            sn.send(0u8).unwrap();
        };

        let thr1 = pool.thread();
        let thr2 = pool.thread();
        let thr3 = pool.thread();
        assert!(thr3.is_err());

        let thr1 = thr1.ok().unwrap();

        let res = thr1.start(f);
        assert!(res.is_ok());

        assert!(rc.recv().unwrap() == 0);
    }

    #[test]
    fn test_thread_pool_join() {
        let (sn1, rc1) = channel::<u8>();
        let (init, max) = (1, 2);
        let pool = ThreadPool::new(init, max);

        let f1 = box move || {
            sn1.send(0u8).unwrap();
        };

        let f2 = box move || {
            panic!();
        };

        // Initial thread.
        let thr1 = pool.thread();
        // Start a new one.
        let thr2 = pool.thread();
        let thr1 = thr1.ok().unwrap();
        let thr2 = thr2.ok().unwrap();

        thr1.start(f1);
        thr2.start(f2);
        let res = thr1.join();
        assert!(res.is_ok());

        let res = thr2.join();
        assert!(res.is_err());
    }

    #[test]
    fn test_thread_pool_max_threads_panic() {
        let (sn1, rc1) = channel::<u8>();
        let (init, max) = (1, 2);
        let pool = ThreadPool::new(init, max);

        let f1 = box move || {
            sn1.send(0u8).unwrap();
        };

        let f2 = box move || {
            panic!();
        };

        // Initial thread.
        let thr1 = pool.thread();
        // Start a new one.
        let thr2 = pool.thread();
        let thr1 = thr1.ok().unwrap();
        let thr2 = thr2.ok().unwrap();

        thr2.start(f2);
        let res = thr2.join();
        assert!(res.is_err());

        let thr3 = pool.thread();
        // Can still get thread after panic
        assert!(thr3.is_ok());

        thr1.start(f1);
        let res = thr1.join();
        assert!(res.is_ok());
    }
}
<|endoftext|>


<commit_before>//! Game Boy GPU emulation

use std::fmt::{Show, Formatter, FormatError};

use ui::Display;

/// GPU state.
pub struct Gpu<'a> {
    /// Emulator Display
    display: &'a mut Display + 'a,
    /// Current line. [0,143] is active video, [144,153] is blanking.
    line: u8,
    /// Position on the current line.
    col: u16,
    /// Object attritube memory
    oam: [u8, ..0xa0],
    /// Video Ram
    vram: [u8, ..0x2000],
    /// `true` if the LCD is enabled.
    enabled: bool,
    /// `true` if we use tile map #1. Otherwise use tile map #0
    window_tile_map_select: bool,
    /// `true` if window display is enabled
    window_display: bool,
    /// `true` if we use tile set #1. Otherwise use tile set #0`
    tile_data_select: bool,
    /// `true` if we use tile map #1. Otherwise use tile map #0
    bg_tile_map_select: bool,
    /// `true` if sprite size is 8x16. Otherwise sprite size is 8x8.
    object_size: bool,
    /// `true` if sprites are displayed
    objects_enabled: bool,
    /// `true` if BG and window display are enabled
    bg_window_enabled: bool,
    /// Background palette
    bgp: u8,
}

/// Current GPU mode
#[deriving(Show)]
pub enum Mode {
    /// In horizontal blanking
    HBlank = 0,
    /// In vertical blanking
    VBlank = 1,
    /// Accessing sprite memory, Sprite attributes RAM [0xfe00, 0xfe9f]
    /// can't be accessed
    Prelude = 2,
    /// Accessing sprite memory and video memory [0x8000, 0x9fff],
    /// both can't be accessed from CPU
    Active = 3,
}

impl<'a> Gpu<'a> {
    /// Create a new Gpu instance.
    pub fn new<'n>(display: &'n mut Display) -> Gpu<'n> {
        Gpu { line:                   0,
              col:                    0,
              oam:                    [0xca, ..0xa0],
              vram:                   [0xca, ..0x2000],
              display:                display,
              enabled:                true,
              window_tile_map_select: false,
              window_display:         false,
              tile_data_select:       true,
              bg_tile_map_select:     false,
              object_size:            false,
              objects_enabled:        false,
              bg_window_enabled:      true,
              bgp:                    0xfc,
        }
    }

    /// Reset the GPU state to power up values
    pub fn reset(&mut self) {
        self.line                   = 0;
        self.col                    = 0;
        self.oam                    = [0xca, ..0xa0];
        self.vram                   = [0xca, ..0x2000];
        self.enabled                = true;
        self.window_tile_map_select = false;
        self.window_display         = false;
        self.tile_data_select       = true;
        self.bg_tile_map_select     = false;
        self.object_size            = false;
        self.objects_enabled        = false;
        self.bg_window_enabled      = true;
        self.bgp                    = 0xfc;
    }

    /// Called at each tick of the system clock. Move the emulated
    /// state one step forward.
    pub fn step(&mut self) {

        //println!("{}", *self);

        if self.col < 456 {
            self.col += 1;
        } else {
            self.col = 0;

            // Move on to the next line
            if self.line < 154 {
                self.line += 1;

                if self.line == 144 {
                    // We're entering blanking, we're done drawing the
                    // current frame
                    self.end_of_frame()
                }

            } else {
                // New frame
                self.line = 0;
            }
        }

        if self.col < 160 && self.line < 144 {
            let x = self.col as u8;
            let y = self.line;

            self.render_pixel(x, y);
        }
    }

    /// Return current GPU mode
    pub fn get_mode(&self) -> Mode {
        if self.line < 144 {
            match self.col {
                0  ... 79  => Prelude,
                80 ... 172 => Active,
                _          => HBlank,
            }
        } else {
            VBlank
        }
    }

    /// Handle reconfig through LCDC register
    pub fn set_lcdc(&mut self, lcdc: u8) {
        self.enabled                = lcdc & 0x80 != 0;
        self.window_tile_map_select = lcdc & 0x40 != 0;
        self.window_display         = lcdc & 0x20 != 0;
        self.tile_data_select       = lcdc & 0x10 != 0;
        self.bg_tile_map_select     = lcdc & 0x08 != 0;
        self.object_size            = lcdc & 0x04 != 0;
        self.objects_enabled        = lcdc & 0x02 != 0;
        self.bg_window_enabled      = lcdc & 0x01 != 0;
    }

    pub fn set_bgp(&mut self, bgp: u8) {
        self.bgp = bgp;
    }

    pub fn bgp(&self) -> u8 {
        self.bgp
    }

    /// Return number of line currently being drawn
    pub fn get_line(&self) -> u8 {
        self.line
    }

    /// Called when the last line of the active display has been drawn
    fn end_of_frame(&mut self) {
        self.display.flip();
    }

    /// Get byte from VRAM
    pub fn get_vram(&self, addr: u16) -> u8 {
        self.vram[addr as uint]
    }

    /// Set byte in VRAM
    pub fn set_vram(&mut self, addr: u16, val: u8) {
        self.vram[addr as uint] = val;
    }

    /// Get byte from OAM
    pub fn get_oam(&self, addr: u16) -> u8 {
        self.oam[addr as uint]
    }

    /// Set byte in OAM
    pub fn set_oam(&mut self, addr: u16, val: u8) {
        self.oam[addr as uint] = val;
    }

    fn render_pixel(&mut self, x: u8, y: u8) {
        let tile_map_x = x / 8;
        let tile_map_y = y / 8;
        let tile_x     = x % 8;
        let tile_y     = y % 8;

        // The screen is divided in 8x8 pixel tiles. It creates a
        // matrix of 32x32 tiles (As far as the GPU is concerned the
        // screen resolution is 256x256). The tile map contains one u8
        // per tile which is the index of the tile to use in the tile
        // set.
        let tile_index = self.bg_tile_index(tile_map_x, tile_map_y);

        let tile_pix_value = self.get_pix_value(tile_index, tile_x, tile_y);

        // Use tile_pix_value as index in the bgp
        let pix_value = (self.bgp >> ((tile_pix_value * 2) as uint)) & 0x3;

        self.display.set_pixel(x as u32, y as u32, pix_value);
    }

    /// Return the background tile index for the tile at (`tx`, `ty`)
    fn bg_tile_index(&self, tx: u8, ty: u8) -> u8 {
        let base = match self.bg_tile_map_select {
            false  => 0x1800,
            true   => 0x1c00,
        };

        let tx = tx as u16;
        let ty = ty as u16;

        let map_addr = base + (ty * 32) + tx;

        self.vram[map_addr as uint]
    }

    /// Get the value of pixel (`x`, `y`) in `tile`. Return a value
    /// between 0 and 3.
    fn get_pix_value(&self, tile: u8, x: u8, y: u8) -> u8 {

        let (x, y) = (y, x);

        if x >= 8 || y >= 8 {
            panic!("tile pos out of range");
        }

        let base = match self.tile_data_select {
            // If tile_data_select is false `tile` is signed and in
            // the range [-128, 127]. Tile 0 is at 0x9000.
            false => (0x1000 + ((tile as i8) as i16) * 16) as u16,
            // Otherwise it's unsigned and starts at 0x8000
            true  => 0x0 + (tile as u16) * 16,
        };

        let addr = base + 2 * (x as u16);

        let addr = addr    as uint;
        let y    = (7 - y) as uint;

        // Each row of 8 pixels is split across two contiguous bytes:
        // the first for the LSB, the 2nd for the MSB
        let lsb = (self.vram[addr]     >> y) & 1;
        let msb = (self.vram[addr + 1] >> y) & 1;

        msb << 1 | lsb
    }
}

impl<'a> Show for Gpu<'a> {
    fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
        try!(write!(f, "Gpu at ({}, {}) [{}] ", self.col, self.line, self.get_mode()));

        Ok(())
    }
}
<commit_msg>Cleanup GPU pixel computation code<commit_after>//! Game Boy GPU emulation

use std::fmt::{Show, Formatter, FormatError};

use ui::Display;

/// GPU state.
pub struct Gpu<'a> {
    /// Emulator Display
    display: &'a mut Display + 'a,
    /// Current line. [0,143] is active video, [144,153] is blanking.
    line: u8,
    /// Position on the current line.
    col: u16,
    /// Object attritube memory
    oam: [u8, ..0xa0],
    /// Video Ram
    vram: [u8, ..0x2000],
    /// `true` if the LCD is enabled.
    enabled: bool,
    /// `true` if we use tile map #1. Otherwise use tile map #0
    window_tile_map_select: bool,
    /// `true` if window display is enabled
    window_display: bool,
    /// `true` if we use tile set #1. Otherwise use tile set #0`
    tile_data_select: bool,
    /// `true` if we use tile map #1. Otherwise use tile map #0
    bg_tile_map_select: bool,
    /// `true` if sprite size is 8x16. Otherwise sprite size is 8x8.
    object_size: bool,
    /// `true` if sprites are displayed
    objects_enabled: bool,
    /// `true` if BG and window display are enabled
    bg_window_enabled: bool,
    /// Background palette
    bgp: u8,
}

/// Current GPU mode
#[deriving(Show)]
pub enum Mode {
    /// In horizontal blanking
    HBlank = 0,
    /// In vertical blanking
    VBlank = 1,
    /// Accessing sprite memory, Sprite attributes RAM [0xfe00, 0xfe9f]
    /// can't be accessed
    Prelude = 2,
    /// Accessing sprite memory and video memory [0x8000, 0x9fff],
    /// both can't be accessed from CPU
    Active = 3,
}

impl<'a> Gpu<'a> {
    /// Create a new Gpu instance.
    pub fn new<'n>(display: &'n mut Display) -> Gpu<'n> {
        Gpu { line:                   0,
              col:                    0,
              oam:                    [0xca, ..0xa0],
              vram:                   [0xca, ..0x2000],
              display:                display,
              enabled:                true,
              window_tile_map_select: false,
              window_display:         false,
              tile_data_select:       true,
              bg_tile_map_select:     false,
              object_size:            false,
              objects_enabled:        false,
              bg_window_enabled:      true,
              bgp:                    0xfc,
        }
    }

    /// Reset the GPU state to power up values
    pub fn reset(&mut self) {
        self.line                   = 0;
        self.col                    = 0;
        self.oam                    = [0xca, ..0xa0];
        self.vram                   = [0xca, ..0x2000];
        self.enabled                = true;
        self.window_tile_map_select = false;
        self.window_display         = false;
        self.tile_data_select       = true;
        self.bg_tile_map_select     = false;
        self.object_size            = false;
        self.objects_enabled        = false;
        self.bg_window_enabled      = true;
        self.bgp                    = 0xfc;
    }

    /// Called at each tick of the system clock. Move the emulated
    /// state one step forward.
    pub fn step(&mut self) {

        //println!("{}", *self);

        if self.col < 456 {
            self.col += 1;
        } else {
            self.col = 0;

            // Move on to the next line
            if self.line < 154 {
                self.line += 1;

                if self.line == 144 {
                    // We're entering blanking, we're done drawing the
                    // current frame
                    self.end_of_frame()
                }

            } else {
                // New frame
                self.line = 0;
            }
        }

        if self.col < 160 && self.line < 144 {
            let x = self.col as u8;
            let y = self.line;

            self.render_pixel(x, y);
        }
    }

    /// Return current GPU mode
    pub fn get_mode(&self) -> Mode {
        if self.line < 144 {
            match self.col {
                0  ... 79  => Prelude,
                80 ... 172 => Active,
                _          => HBlank,
            }
        } else {
            VBlank
        }
    }

    /// Handle reconfig through LCDC register
    pub fn set_lcdc(&mut self, lcdc: u8) {
        self.enabled                = lcdc & 0x80 != 0;
        self.window_tile_map_select = lcdc & 0x40 != 0;
        self.window_display         = lcdc & 0x20 != 0;
        self.tile_data_select       = lcdc & 0x10 != 0;
        self.bg_tile_map_select     = lcdc & 0x08 != 0;
        self.object_size            = lcdc & 0x04 != 0;
        self.objects_enabled        = lcdc & 0x02 != 0;
        self.bg_window_enabled      = lcdc & 0x01 != 0;
    }

    pub fn set_bgp(&mut self, bgp: u8) {
        self.bgp = bgp;
    }

    pub fn bgp(&self) -> u8 {
        self.bgp
    }

    /// Return number of line currently being drawn
    pub fn get_line(&self) -> u8 {
        self.line
    }

    /// Called when the last line of the active display has been drawn
    fn end_of_frame(&mut self) {
        self.display.flip();
    }

    /// Get byte from VRAM
    pub fn get_vram(&self, addr: u16) -> u8 {
        self.vram[addr as uint]
    }

    /// Set byte in VRAM
    pub fn set_vram(&mut self, addr: u16, val: u8) {
        self.vram[addr as uint] = val;
    }

    /// Get byte from OAM
    pub fn get_oam(&self, addr: u16) -> u8 {
        self.oam[addr as uint]
    }

    /// Set byte in OAM
    pub fn set_oam(&mut self, addr: u16, val: u8) {
        self.oam[addr as uint] = val;
    }

    fn render_pixel(&mut self, x: u8, y: u8) {
        let tile_map_x = x / 8;
        let tile_map_y = y / 8;
        let tile_x     = x % 8;
        let tile_y     = y % 8;

        // The screen is divided in 8x8 pixel tiles. It creates a
        // matrix of 32x32 tiles (As far as the GPU is concerned the
        // screen resolution is 256x256). The tile map contains one u8
        // per tile which is the index of the tile to use in the tile
        // set.
        let tile_index = self.bg_tile_index(tile_map_x, tile_map_y);

        let tile_pix_value = self.get_pix_value(tile_index, tile_x, tile_y);

        // Use tile_pix_value as index in the bgp
        let pix_value = (self.bgp >> ((tile_pix_value * 2) as uint)) & 0x3;

        self.display.set_pixel(x as u32, y as u32, pix_value);
    }

    /// Return the background tile index for the tile at (`tx`, `ty`)
    fn bg_tile_index(&self, tx: u8, ty: u8) -> u8 {
        let base = match self.bg_tile_map_select {
            false  => 0x1800,
            true   => 0x1c00,
        };

        let tx = tx as u16;
        let ty = ty as u16;

        let map_addr = base + (ty * 32) + tx;

        self.vram[map_addr as uint]
    }

    /// Get the value of pixel (`x`, `y`) in `tile`. Return a value
    /// between 0 and 3.
    fn get_pix_value(&self, tile: u8, x: u8, y: u8) -> u8 {

        if x >= 8 || y >= 8 {
            panic!("tile pos out of range");
        }

        let base = match self.tile_data_select {
            // If tile_data_select is false `tile` is signed and in
            // the range [-128, 127]. Tile 0 is at 0x9000.
            false => (0x1000 + (((tile as i8) as i16) * 16)) as u16,
            // Otherwise it's unsigned and starts at 0x8000
            true  => 0x0 + (tile as u16) * 16,
        };

        let addr = base + 2 * (y as u16);

        let addr = addr    as uint;
        let x    = (7 - x) as uint;

        // Each row of 8 pixels is split across two contiguous bytes:
        // the first for the LSB, the 2nd for the MSB
        let lsb = (self.vram[addr]     >> x) & 1;
        let msb = (self.vram[addr + 1] >> x) & 1;

        msb << 1 | lsb
    }
}

impl<'a> Show for Gpu<'a> {
    fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
        try!(write!(f, "Gpu at ({}, {}) [{}] ", self.col, self.line, self.get_mode()));

        Ok(())
    }
}
<|endoftext|>


<commit_before>use handlebars::Handlebars;

use hyper::{Control, Decoder, Encoder, Next};
use hyper::HttpVersion::{Http09, Http10, Http11};

use hyper::error::Error as HyperError;
use hyper::header::{ContentLength, ContentType, Encoding, TransferEncoding};
use hyper::method::Method::{Connect, Delete, Get, Head, Trace};
use hyper::net::HttpStream;
use hyper::server::{Handler, Request as HttpRequest, Response as HttpResponse};
use hyper::status::StatusCode as Status;

use scoped_pool::Scope;

use serde_json::value as json;

use url::Url;

use buffer::Buffer;
use request::{self, Request};
use response::{self, Response, Result, Action};
use router::{Callback, RouterAny};

use crossbeam::sync::chase_lev::{deque, Steal, Stealer, Worker};

use std::any::Any;
use std::io::{self, Write};

enum Reply {
    Headers(Response),
    Body(Buffer)
}

enum Body {
    Empty,
    Some(Buffer),
    Streaming(Box<Fn(&mut Any, &mut Write)>)
}

struct Stream {
    worker: Worker<Reply>,
    control: Control
}

impl Write for Stream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.worker.push(Reply::Body(buf.to_vec().into()));
        if let Err(e) = self.control.ready(Next::write()) {
            error!("could not notify handler: {}", e);
        }
        Ok(buf.len())
    }

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

impl Drop for Stream {
    fn drop(&mut self) {
        self.worker.push(Reply::Body(vec![].into()));
        if let Err(e) = self.control.ready(Next::write()) {
            error!("could not notify handler: {}", e);
        }
    }
}

/// a handler that lasts only the time of a request
/// scope outlives handler
pub struct EdgeHandler<'handler, 'scope: 'handler> {
    scope: &'handler Scope<'scope>,
    base_url: &'handler Url,
    routers: &'scope [RouterAny],
    request: Option<Request>,
    is_head_request: bool,
    buffer: Option<Buffer>,

    handlebars: &'scope Handlebars,
    control: Control,
    stealer: Option<Stealer<Reply>>,
    streaming: bool
}

impl<'handler, 'scope> EdgeHandler<'handler, 'scope> {
    pub fn new(scope: &'handler Scope<'scope>, base_url: &'handler Url, routers: &'scope [RouterAny], handlebars: &'scope Handlebars, control: Control) -> EdgeHandler<'handler, 'scope> {
        EdgeHandler {
            scope: scope,
            base_url: base_url,
            routers: routers,
            request: None,
            is_head_request: false,
            buffer: None,

            handlebars: handlebars,
            control: control,
            stealer: None,
            streaming: false
        }
    }

    fn callback(&mut self) -> Next {
        let (mut worker, stealer) = deque();
        self.stealer = Some(stealer);

        let mut req = self.request.take().unwrap();

        let result = self.routers.iter().filter_map(|router|
            if let Some(callback) = router.find_callback(&mut req) {
                Some((router, callback))
            } else {
                None
            }
        ).next();

        if let Some((router, callback)) = result {
            let mut boxed_app = router.new_instance();

            // add job to scoped pool
            let ctrl = self.control.clone();
            let handlebars = self.handlebars;

            self.scope.execute(move || {
                let mut response = Response::new();
                let app = boxed_app.as_mut();
                let result =
                    match *callback {
                        Callback::Instance(ref f) => {
                            router.run_middleware(app, &mut req, &mut response);
                            f(app, &req, &mut response)
                        }
                        Callback::Static(ref f) => f(&req, &mut response)
                    };

                let body = process_handle_result(&mut response, result, handlebars);
                if let Body::Some(ref body) = body {
                    response.len(body.len() as u64);
                }
                worker.push(Reply::Headers(response));
                match body {
                    Body::Some(body) => { worker.push(Reply::Body(body)); }
                    Body::Streaming(closure) => {
                        if let Err(e) = ctrl.ready(Next::write()) {
                            error!("could not notify handler: {}", e);
                        }
                        let mut stream = Stream {
                            worker: worker,
                            control: ctrl
                        };
                        closure(app, &mut stream);
                        return;
                    }
                    Body::Empty => ()
                }

                if let Err(e) = ctrl.ready(Next::write()) {
                    error!("could not notify handler: {}", e);
                }
            });

            // and wait for it to notify us
            Next::wait()
        } else {
            //warn!("route not found for path {:?}", req.path())
            let mut response = Response::new();
            response.status(Status::NotFound).content_type("text/plain");
            worker.push(Reply::Headers(response));
            worker.push(Reply::Body(format!("not found: {:?}", req.path()).into_bytes().into()));
            Next::write()
        }
    }

    fn bad_request(&mut self, message: &str) -> Next {
        let (mut worker, stealer) = deque();
        self.stealer = Some(stealer);

        error!("Bad Request: {}", message);
        let mut response = Response::new();
        response.status(Status::BadRequest).content_type("text/plain; charset=UTF-8");
        worker.push(Reply::Headers(response));
        worker.push(Reply::Body(message.to_string().into_bytes().into()));
        Next::write()
    }

}

/// Matches the result to update the response and produce a body.
///
/// If the result is Ok, converts the value into a HandleResult, and calls
/// end/send/render/redirect depending on the type of result.
/// Otherwise, if the result is Err, sets the status with the error message as content (if specified).
/// as the body.
fn process_handle_result(response: &mut Response, result: Result, handlebars: &Handlebars) -> Body {
    match result {
        Ok(handler) => {
            match handler.into() {
                Action::End(status) => {
                    if let Some(status) = status {
                        response.status(status);
                    }
                    Body::Empty
                }
                Action::Redirect(status, url) => {
                    response.status(status);
                    response.location(url);
                    Body::Empty
                }
                Action::Render(name, json) => {
                    let buffer = render(response, handlebars, &name, &json);
                    Body::Some(buffer)
                }
                Action::Send(body) => {
                    Body::Some(body.into())
                }
                Action::SendFile(filename) => {
                    if let Some(body) = response::send_file(response, filename).map(|vec| vec.into()) {
                        Body::Some(body)
                    } else {
                        Body::Empty
                    }
                }
                Action::Stream(closure) => {
                    response::set_streaming(response);
                    Body::Streaming(closure)
                }
            }
        }
        Err(error) => {
            match error.message {
                None => {
                    response.status(error.status);
                    Body::Empty
                }
                Some(message) => {
                    response.status(error.status);
                    response.content_type("text/plain");
                    Body::Some((&*message).as_bytes().to_vec().into())
                }
            }
        }
    }
}

/// Renders the template with the given name using the given data.
///
/// If no Content-Type header is set, the content type is set to `text/html`.
fn render(response: &mut Response, handlebars: &Handlebars, name: &str, json: &json::Value) -> Buffer {
    if !response.headers.has::<ContentType>() {
        response.header(ContentType::html());
    }

    let result = handlebars.render(name, json);
    result.unwrap().into_bytes().into()
}

/// Implements Handler for our EdgeHandler.
impl<'handler, 'scope> Handler<HttpStream> for EdgeHandler<'handler, 'scope> {
    fn on_request(&mut self, req: HttpRequest) -> Next {
        debug!("on_request");

        match request::new(&self.base_url, req) {
            Ok(req) => {
                let result = check_request(&req, &mut self.buffer);
                self.is_head_request = *req.method() == Head;
                self.request = Some(req);

                match result {
                    Err(msg) => self.bad_request(msg),
                    Ok(false) => self.callback(),
                    Ok(true) => Next::read()
                }
            }
            Err(error) => {
                self.bad_request(&error.to_string())
            }
        }
    }

    fn on_request_readable(&mut self, transport: &mut Decoder<HttpStream>) -> Next {
        debug!("on_request_readable");

        // we can only get here if self.buffer = Some(...), or there is a bug
        {
            let body = self.buffer.as_mut().unwrap();
            if let Ok(keep_reading) = body.read_from(transport) {
                if keep_reading {
                    return Next::read();
                }
            }
        }

        // move body to the request
        request::set_body(self.request.as_mut(), self.buffer.take());
        self.callback()
    }

    fn on_response(&mut self, res: &mut HttpResponse) -> Next {
        debug!("on_response");

        // we got here from callback directly or Resp notified the Control
        loop {
            match self.stealer.as_ref().unwrap().steal() {
                Steal::Data(reply) => {
                    match reply {
                        Reply::Headers(response) => {
                            self.streaming = response::is_streaming(&response);
                            let status = response.status;

                            // set status and headers
                            res.set_status(status);
                            *res.headers_mut() = response.headers;

                            // 3.3.2 Content-Length
                            // http://httpwg.org/specs/rfc7230.html#header.content-length
                            //
                            // A server MUST NOT send a Content-Length header field in any response
                            // with a status code of 1xx (Informational) or 204 (No Content).
                            //
                            // A server MAY send a Content-Length header field in a response to a HEAD request
                            // A server MAY send a Content-Length header field in a 304 (Not Modified) response
                            if status.is_informational() ||
                                status == Status::NoContent || status == Status::NotModified ||
                                self.is_head_request {
                                // we remove any ContentLength header in those cases
                                // even in 304 and response to HEAD
                                // because we cannot guarantee that the length is the same
                                res.headers_mut().remove::<ContentLength>();
                                return Next::end();
                            }
                        }
                        Reply::Body(body) => {
                            debug!("has body");
                            self.buffer = Some(body);
                            return Next::write();
                        }
                    }
                }
                Steal::Empty => {
                    if self.streaming {
                        debug!("streaming mode, waiting");
                        return Next::wait();
                    } else {
                        debug!("has no body, ending");
                        return Next::end();
                    }
                }
                Steal::Abort => panic!("abort")
            }
        }
    }

    fn on_response_writable(&mut self, transport: &mut Encoder<HttpStream>) -> Next {
        debug!("on_response_writable");

        if self.streaming {
            if self.buffer.is_none() {
                self.buffer = match self.stealer.as_ref().unwrap().steal() {
                    Steal::Data(Reply::Body(body)) => Some(body),
                    Steal::Empty => None,
                    _ => panic!("unexpected")
                };
            }

            if self.buffer.is_none() {
                // no buffer available yet
                Next::wait()
            } else {
                let empty = self.buffer.as_mut().unwrap().is_empty();
                if empty {
                    // an empty body means no more data to write
                    debug!("done writing");
                    Next::end()
                } else {
                    let result = self.buffer.as_mut().unwrap().write_to(transport);
                    if let Ok(keep_writing) = result {
                        if keep_writing {
                            Next::write()
                        } else {
                            // done writing this buffer, try to get another one
                            self.buffer = None;
                            Next::write()
                        }
                    } else {
                        Next::remove()
                    }
                }
            }
        } else {
            let body = self.buffer.as_mut().unwrap();
            if let Ok(keep_writing) = body.write_to(transport) {
                if keep_writing {
                    Next::write()
                } else {
                    Next::end()
                }
            } else {
                Next::remove()
            }
        }
    }

    fn on_error(&mut self, err: HyperError) -> Next {
        debug!("on_error {:?}", err);
        Next::remove()
    }

    fn on_remove(self, _transport: HttpStream) {
        debug!("on_remove");
    }
}

fn check_request(req: &Request, buffer: &mut Option<Buffer>) -> ::std::result::Result<bool, &'static str> {
    let headers = req.headers();
    let http1x = { let version = req.version(); *version == Http09 || *version == Http10 || *version == Http11 };

    // RFC 7230 Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing
    // 3.3.3 Message Body Length
    // http://httpwg.org/specs/rfc7230.html#message.body.length
    //
    let len =
        if let Some(&TransferEncoding(ref codings)) = headers.get() {
            if codings.last() != Some(&Encoding::Chunked) {
                // 3. If a Transfer-Encoding header field is present in a request and
                // the chunked transfer coding is not the final encoding,
                // the message body length cannot be determined reliably;
                // the server MUST respond with the 400 (Bad Request) status code
                // and then close the connection.
                return Err("Last encoding of Transfer-Encoding must be chunked")
            }

            // Transfer-Encoding is correct, we have a payload
            None
        } else if let Some(&ContentLength(len)) = headers.get() {
            // 5. If a valid Content-Length header field is present without Transfer-Encoding,
            // its decimal value defines the expected message body length in octets.
            if len == 0 {
                info!("Request with empty payload Content-Length: 0");
                return Ok(false);
            }

            Some(len as usize)
        } else if headers.has::<ContentLength>() {
            // 4. If a message is received without Transfer-Encoding
            // and with either multiple Content-Length header fields having
            // differing field-values or a single Content-Length header field
            // having an invalid value, then the message framing is invalid
            // and the recipient MUST treat it as an unrecoverable error.
            // If this is a request message, the server MUST respond with
            // a 400 (Bad Request) status code and then close the connection.
            return Err("Invalid Content-Length header");
        } else if http1x {
            // If this is a request message and none of the above are true,
            // then the message body length is zero (no message body is present).
            return Ok(false);
        } else {
            // in HTTP/2 a request message can have a body even if
            // no Transfer-Encoding or Content-Length headers are present
            None
        };

    // RFC 7231 Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content
    // 4.3 Method Definitions
    // http://httpwg.org/specs/rfc7231.html#method.definitions
    //
    // A payload within a GET/HEAD/DELETE/CONNECT request message has no defined
    // semantics; sending a payload body on a GET/HEAD/DELETE/CONNECT request
    // might cause some existing implementations to reject the request.
    let method = req.method();
    if *method == Get || *method == Head || *method == Delete || *method == Connect {
        // payload in these methods has no defined semantics
        if http1x {
            // warns only for HTTP/1.x-compatible
            // because we cannot know for sure whether there is a payload in HTTP/2
            warn!("Ignoring payload for {} request", *method);
        }

        Ok(false)
    } else if *method == Trace {
        Err("A client MUST NOT send a message body in a TRACE request.")
    } else {
        // payload is allowed
        // if Content-Length is known create buffer with fixed size, otherwise allocate growable buffer
        *buffer = Some(len.map_or(Buffer::new(), |len| Buffer::new_fixed(len)));
        Ok(true)
    }
}
<commit_msg>rewrite some code in callback function to make it easier to follow<commit_after>use handlebars::Handlebars;

use hyper::{Control, Decoder, Encoder, Next};
use hyper::HttpVersion::{Http09, Http10, Http11};

use hyper::error::Error as HyperError;
use hyper::header::{ContentLength, ContentType, Encoding, TransferEncoding};
use hyper::method::Method::{Connect, Delete, Get, Head, Trace};
use hyper::net::HttpStream;
use hyper::server::{Handler, Request as HttpRequest, Response as HttpResponse};
use hyper::status::StatusCode as Status;

use scoped_pool::Scope;

use serde_json::value as json;

use url::Url;

use buffer::Buffer;
use request::{self, Request};
use response::{self, Response, Result, Action};
use router::{Callback, RouterAny};

use crossbeam::sync::chase_lev::{deque, Steal, Stealer, Worker};

use std::any::Any;
use std::io::{self, Write};

enum Reply {
    Headers(Response),
    Body(Buffer)
}

enum Body {
    Empty,
    Some(Buffer),
    Streaming(Box<Fn(&mut Any, &mut Write)>)
}

struct Stream {
    worker: Worker<Reply>,
    control: Control
}

fn notify(control: &Control) {
    if let Err(e) = control.ready(Next::write()) {
        error!("could not notify handler: {}", e);
    }
}

impl Write for Stream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.worker.push(Reply::Body(buf.to_vec().into()));
        notify(&self.control);
        Ok(buf.len())
    }

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

impl Drop for Stream {
    fn drop(&mut self) {
        self.worker.push(Reply::Body(vec![].into()));
        notify(&self.control);
    }
}

/// a handler that lasts only the time of a request
/// scope outlives handler
pub struct EdgeHandler<'handler, 'scope: 'handler> {
    scope: &'handler Scope<'scope>,
    base_url: &'handler Url,
    routers: &'scope [RouterAny],
    request: Option<Request>,
    is_head_request: bool,
    buffer: Option<Buffer>,

    handlebars: &'scope Handlebars,
    control: Control,
    stealer: Option<Stealer<Reply>>,
    streaming: bool
}

impl<'handler, 'scope> EdgeHandler<'handler, 'scope> {
    pub fn new(scope: &'handler Scope<'scope>, base_url: &'handler Url, routers: &'scope [RouterAny], handlebars: &'scope Handlebars, control: Control) -> EdgeHandler<'handler, 'scope> {
        EdgeHandler {
            scope: scope,
            base_url: base_url,
            routers: routers,
            request: None,
            is_head_request: false,
            buffer: None,

            handlebars: handlebars,
            control: control,
            stealer: None,
            streaming: false
        }
    }

    fn callback(&mut self) -> Next {
        let (mut worker, stealer) = deque();
        self.stealer = Some(stealer);

        let mut req = self.request.take().unwrap();

        let result = self.routers.iter().filter_map(|router|
            if let Some(callback) = router.find_callback(&mut req) {
                Some((router, callback))
            } else {
                None
            }
        ).next();

        if let Some((router, callback)) = result {
            // add job to scoped pool
            let ctrl = self.control.clone();
            let handlebars = self.handlebars;

            self.scope.execute(move || {
                let mut response = Response::new();
                let mut boxed_app = router.new_instance();
                let app = boxed_app.as_mut();
                let result =
                    match *callback {
                        Callback::Instance(ref f) => {
                            router.run_middleware(app, &mut req, &mut response);
                            f(app, &req, &mut response)
                        }
                        Callback::Static(ref f) => f(&req, &mut response)
                    };

                match process_handle_result(&mut response, result, handlebars) {
                    Body::Empty => {
                        worker.push(Reply::Headers(response));
                        notify(&ctrl);
                    }
                    Body::Some(body) => {
                        response.len(body.len() as u64);
                        worker.push(Reply::Headers(response));
                        worker.push(Reply::Body(body));
                        notify(&ctrl);
                    }
                    Body::Streaming(closure) => {
                        worker.push(Reply::Headers(response));
                        notify(&ctrl);

                        let mut stream = Stream {
                            worker: worker,
                            control: ctrl
                        };
                        closure(app, &mut stream);
                    }
                }
            });

            // and wait for it to notify us
            Next::wait()
        } else {
            //warn!("route not found for path {:?}", req.path())
            let mut response = Response::new();
            response.status(Status::NotFound).content_type("text/plain");
            worker.push(Reply::Headers(response));
            worker.push(Reply::Body(format!("not found: {:?}", req.path()).into_bytes().into()));
            Next::write()
        }
    }

    fn bad_request(&mut self, message: &str) -> Next {
        let (mut worker, stealer) = deque();
        self.stealer = Some(stealer);

        error!("Bad Request: {}", message);
        let mut response = Response::new();
        response.status(Status::BadRequest).content_type("text/plain; charset=UTF-8");
        worker.push(Reply::Headers(response));
        worker.push(Reply::Body(message.to_string().into_bytes().into()));
        Next::write()
    }

}

/// Matches the result to update the response and produce a body.
///
/// If the result is Ok, converts the value into a HandleResult, and calls
/// end/send/render/redirect depending on the type of result.
/// Otherwise, if the result is Err, sets the status with the error message as content (if specified).
/// as the body.
fn process_handle_result(response: &mut Response, result: Result, handlebars: &Handlebars) -> Body {
    match result {
        Ok(handler) => {
            match handler.into() {
                Action::End(status) => {
                    if let Some(status) = status {
                        response.status(status);
                    }
                    Body::Empty
                }
                Action::Redirect(status, url) => {
                    response.status(status);
                    response.location(url);
                    Body::Empty
                }
                Action::Render(name, json) => {
                    let buffer = render(response, handlebars, &name, &json);
                    Body::Some(buffer)
                }
                Action::Send(body) => {
                    Body::Some(body.into())
                }
                Action::SendFile(filename) => {
                    if let Some(body) = response::send_file(response, filename).map(|vec| vec.into()) {
                        Body::Some(body)
                    } else {
                        Body::Empty
                    }
                }
                Action::Stream(closure) => {
                    response::set_streaming(response);
                    Body::Streaming(closure)
                }
            }
        }
        Err(error) => {
            match error.message {
                None => {
                    response.status(error.status);
                    Body::Empty
                }
                Some(message) => {
                    response.status(error.status);
                    response.content_type("text/plain");
                    Body::Some((&*message).as_bytes().to_vec().into())
                }
            }
        }
    }
}

/// Renders the template with the given name using the given data.
///
/// If no Content-Type header is set, the content type is set to `text/html`.
fn render(response: &mut Response, handlebars: &Handlebars, name: &str, json: &json::Value) -> Buffer {
    if !response.headers.has::<ContentType>() {
        response.header(ContentType::html());
    }

    let result = handlebars.render(name, json);
    result.unwrap().into_bytes().into()
}

/// Implements Handler for our EdgeHandler.
impl<'handler, 'scope> Handler<HttpStream> for EdgeHandler<'handler, 'scope> {
    fn on_request(&mut self, req: HttpRequest) -> Next {
        debug!("on_request");

        match request::new(&self.base_url, req) {
            Ok(req) => {
                let result = check_request(&req, &mut self.buffer);
                self.is_head_request = *req.method() == Head;
                self.request = Some(req);

                match result {
                    Err(msg) => self.bad_request(msg),
                    Ok(false) => self.callback(),
                    Ok(true) => Next::read()
                }
            }
            Err(error) => {
                self.bad_request(&error.to_string())
            }
        }
    }

    fn on_request_readable(&mut self, transport: &mut Decoder<HttpStream>) -> Next {
        debug!("on_request_readable");

        // we can only get here if self.buffer = Some(...), or there is a bug
        {
            let body = self.buffer.as_mut().unwrap();
            if let Ok(keep_reading) = body.read_from(transport) {
                if keep_reading {
                    return Next::read();
                }
            }
        }

        // move body to the request
        request::set_body(self.request.as_mut(), self.buffer.take());
        self.callback()
    }

    fn on_response(&mut self, res: &mut HttpResponse) -> Next {
        debug!("on_response");

        // we got here from callback directly or Resp notified the Control
        loop {
            match self.stealer.as_ref().unwrap().steal() {
                Steal::Data(reply) => {
                    match reply {
                        Reply::Headers(response) => {
                            self.streaming = response::is_streaming(&response);
                            let status = response.status;

                            // set status and headers
                            res.set_status(status);
                            *res.headers_mut() = response.headers;

                            // 3.3.2 Content-Length
                            // http://httpwg.org/specs/rfc7230.html#header.content-length
                            //
                            // A server MUST NOT send a Content-Length header field in any response
                            // with a status code of 1xx (Informational) or 204 (No Content).
                            //
                            // A server MAY send a Content-Length header field in a response to a HEAD request
                            // A server MAY send a Content-Length header field in a 304 (Not Modified) response
                            if status.is_informational() ||
                                status == Status::NoContent || status == Status::NotModified ||
                                self.is_head_request {
                                // we remove any ContentLength header in those cases
                                // even in 304 and response to HEAD
                                // because we cannot guarantee that the length is the same
                                res.headers_mut().remove::<ContentLength>();
                                return Next::end();
                            }
                        }
                        Reply::Body(body) => {
                            debug!("has body");
                            self.buffer = Some(body);
                            return Next::write();
                        }
                    }
                }
                Steal::Empty => {
                    if self.streaming {
                        debug!("streaming mode, waiting");
                        return Next::wait();
                    } else {
                        debug!("has no body, ending");
                        return Next::end();
                    }
                }
                Steal::Abort => panic!("abort")
            }
        }
    }

    fn on_response_writable(&mut self, transport: &mut Encoder<HttpStream>) -> Next {
        debug!("on_response_writable");

        if self.streaming {
            if self.buffer.is_none() {
                self.buffer = match self.stealer.as_ref().unwrap().steal() {
                    Steal::Data(Reply::Body(body)) => Some(body),
                    Steal::Empty => None,
                    _ => panic!("unexpected")
                };
            }

            if self.buffer.is_none() {
                // no buffer available yet
                Next::wait()
            } else {
                let empty = self.buffer.as_mut().unwrap().is_empty();
                if empty {
                    // an empty body means no more data to write
                    debug!("done writing");
                    Next::end()
                } else {
                    let result = self.buffer.as_mut().unwrap().write_to(transport);
                    if let Ok(keep_writing) = result {
                        if keep_writing {
                            Next::write()
                        } else {
                            // done writing this buffer, try to get another one
                            self.buffer = None;
                            Next::write()
                        }
                    } else {
                        Next::remove()
                    }
                }
            }
        } else {
            let body = self.buffer.as_mut().unwrap();
            if let Ok(keep_writing) = body.write_to(transport) {
                if keep_writing {
                    Next::write()
                } else {
                    Next::end()
                }
            } else {
                Next::remove()
            }
        }
    }

    fn on_error(&mut self, err: HyperError) -> Next {
        debug!("on_error {:?}", err);
        Next::remove()
    }

    fn on_remove(self, _transport: HttpStream) {
        debug!("on_remove");
    }
}

fn check_request(req: &Request, buffer: &mut Option<Buffer>) -> ::std::result::Result<bool, &'static str> {
    let headers = req.headers();
    let http1x = { let version = req.version(); *version == Http09 || *version == Http10 || *version == Http11 };

    // RFC 7230 Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing
    // 3.3.3 Message Body Length
    // http://httpwg.org/specs/rfc7230.html#message.body.length
    //
    let len =
        if let Some(&TransferEncoding(ref codings)) = headers.get() {
            if codings.last() != Some(&Encoding::Chunked) {
                // 3. If a Transfer-Encoding header field is present in a request and
                // the chunked transfer coding is not the final encoding,
                // the message body length cannot be determined reliably;
                // the server MUST respond with the 400 (Bad Request) status code
                // and then close the connection.
                return Err("Last encoding of Transfer-Encoding must be chunked")
            }

            // Transfer-Encoding is correct, we have a payload
            None
        } else if let Some(&ContentLength(len)) = headers.get() {
            // 5. If a valid Content-Length header field is present without Transfer-Encoding,
            // its decimal value defines the expected message body length in octets.
            if len == 0 {
                info!("Request with empty payload Content-Length: 0");
                return Ok(false);
            }

            Some(len as usize)
        } else if headers.has::<ContentLength>() {
            // 4. If a message is received without Transfer-Encoding
            // and with either multiple Content-Length header fields having
            // differing field-values or a single Content-Length header field
            // having an invalid value, then the message framing is invalid
            // and the recipient MUST treat it as an unrecoverable error.
            // If this is a request message, the server MUST respond with
            // a 400 (Bad Request) status code and then close the connection.
            return Err("Invalid Content-Length header");
        } else if http1x {
            // If this is a request message and none of the above are true,
            // then the message body length is zero (no message body is present).
            return Ok(false);
        } else {
            // in HTTP/2 a request message can have a body even if
            // no Transfer-Encoding or Content-Length headers are present
            None
        };

    // RFC 7231 Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content
    // 4.3 Method Definitions
    // http://httpwg.org/specs/rfc7231.html#method.definitions
    //
    // A payload within a GET/HEAD/DELETE/CONNECT request message has no defined
    // semantics; sending a payload body on a GET/HEAD/DELETE/CONNECT request
    // might cause some existing implementations to reject the request.
    let method = req.method();
    if *method == Get || *method == Head || *method == Delete || *method == Connect {
        // payload in these methods has no defined semantics
        if http1x {
            // warns only for HTTP/1.x-compatible
            // because we cannot know for sure whether there is a payload in HTTP/2
            warn!("Ignoring payload for {} request", *method);
        }

        Ok(false)
    } else if *method == Trace {
        Err("A client MUST NOT send a message body in a TRACE request.")
    } else {
        // payload is allowed
        // if Content-Length is known create buffer with fixed size, otherwise allocate growable buffer
        *buffer = Some(len.map_or(Buffer::new(), |len| Buffer::new_fixed(len)));
        Ok(true)
    }
}
<|endoftext|>


<commit_before>mod crc;
#[macro_use]
mod macros;

pub use self::crc::{crc8, crc16};

// Convert one to four byte slices into an unsigned 32-bit number.
//
// NOTE: This assumes big-endian since most numbers in the FLAC binary are
// that endianness.
#[inline]
pub fn to_u32(bytes: &[u8]) -> u32 {
  let length = bytes.len();

  debug_assert!(length <= 4);

  (0..length).fold(0, |result, i|
    result + ((bytes[i] as u32) << ((length - 1 - i) * 8))
  )
}

pub fn extend_sign(value: u32, bit_count: usize) -> i32 {
  if bit_count >= 32 || value < (1 << (bit_count - 1)) {
    value as i32
  } else {
    (value as i32).wrapping_sub(1 << bit_count)
  }
}

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

  #[test]
  #[should_panic]
  fn test_panic_to_u32() {
    to_u32(&[0x00, 0x00, 0x00, 0x00, 0x00]);
  }

  #[test]
  fn test_to_u32() {
    let bytes = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];

    assert_eq!(to_u32(&bytes[0..1]), 0x00000001);
    assert_eq!(to_u32(&bytes[3..5]), 0x00006789);
    assert_eq!(to_u32(&bytes[1..4]), 0x00234567);
    assert_eq!(to_u32(&bytes[4..]), 0x89abcdef);
  }
}
<commit_msg>Add tests for `extend_sign`<commit_after>mod crc;
#[macro_use]
mod macros;

pub use self::crc::{crc8, crc16};

// Convert one to four byte slices into an unsigned 32-bit number.
//
// NOTE: This assumes big-endian since most numbers in the FLAC binary are
// that endianness.
#[inline]
pub fn to_u32(bytes: &[u8]) -> u32 {
  let length = bytes.len();

  debug_assert!(length <= 4);

  (0..length).fold(0, |result, i|
    result + ((bytes[i] as u32) << ((length - 1 - i) * 8))
  )
}

pub fn extend_sign(value: u32, bit_count: usize) -> i32 {
  if bit_count >= 32 || value < (1 << (bit_count - 1)) {
    value as i32
  } else {
    (value as i32).wrapping_sub(1 << bit_count)
  }
}

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

  #[test]
  #[should_panic]
  fn test_panic_to_u32() {
    to_u32(&[0x00, 0x00, 0x00, 0x00, 0x00]);
  }

  #[test]
  fn test_to_u32() {
    let bytes = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];

    assert_eq!(to_u32(&bytes[0..1]), 0x00000001);
    assert_eq!(to_u32(&bytes[3..5]), 0x00006789);
    assert_eq!(to_u32(&bytes[1..4]), 0x00234567);
    assert_eq!(to_u32(&bytes[4..]), 0x89abcdef);
  }

  #[test]
  fn test_extend_sign() {
    assert_eq!(extend_sign(32, 6), -32);
    assert_eq!(extend_sign(31, 6), 31);
    assert_eq!(extend_sign(128, 8), -128);
    assert_eq!(extend_sign(127, 8), 127);

    assert_eq!(extend_sign(2048, 12), -2048);
    assert_eq!(extend_sign(2047, 12), 2047);
    assert_eq!(extend_sign(32768, 16), -32768);
    assert_eq!(extend_sign(32767, 16), 32767);

    assert_eq!(extend_sign(8388608, 24), -8388608);
    assert_eq!(extend_sign(8388607, 24), 8388607);
    assert_eq!(extend_sign(2147483648, 32), -2147483648);
    assert_eq!(extend_sign(2147483647, 32), 2147483647);
  }
}
<|endoftext|>