<commit_before>use std::collections::HashMap;
use std::str::FromStr;
use std::any::Any;

macro_rules! blanket_impl {
  ($trait_: ident for $($type_: ty),*) => {
    $(
      impl $trait_ for $type_ {}
    )*
  };
}

macro_rules! impl_graphql_type_for {
    ($tt: ty where name = $name: expr, description = $desc: expr) => {
        impl GraphQLType for $tt {
            fn name(&self) -> &str { $name }
            fn description(&self) -> Option<&str> { Some($desc) }
        }
    };

    ($($type_: ty),*) => {
      $(
        impl GraphQLType for $type_ {
            fn name(&self) -> &str { self.name.as_ref() }

            fn description(&self) -> Option<&str> {
                self.description.as_ref().map(|s| s.as_ref())
            }
        }
      )*
    };
}

pub trait GraphQLType {
  fn name(&self) -> &str;
  fn description(&self) -> Option<&str>;
}
impl_graphql_type_for! { GraphQLEnum }

pub trait GraphQLScalar: GraphQLType {
    type ValueType: Any;
  fn coerce_literal(&self, value: &str) -> Option<Self::ValueType>;
}

pub struct GraphQLInt;
impl_graphql_type_for! {
    GraphQLInt where
    name = "Int",
    description = "The Int scalar type represents a signed 32‐bit numeric non‐fractional values."
}

impl GraphQLScalar for GraphQLInt {
  type ValueType = i32;
  fn coerce_literal(&self, value: &str) -> Option<Self::ValueType> {
    i32::from_str(value).ok()
  }
}

pub struct GraphQLFloat;
impl_graphql_type_for! {
    GraphQLFloat where
    name = "Float",
    description = "The Float scalar type represents signed double-precision fractional values as specified by IEEE 754."
}

impl GraphQLScalar for GraphQLFloat {
  type ValueType = f64;
  fn coerce_literal(&self, value: &str) -> Option<Self::ValueType> {
    f64::from_str(value).ok()
  }
}

pub struct GraphQLString;
impl_graphql_type_for! {
    GraphQLString where
    name = "String",
    description = "The String scalar type represents textual data, represented as UTF-8 character sequences."
}

impl GraphQLScalar for GraphQLString {
  type ValueType = String;
  fn coerce_literal(&self, value: &str) -> Option<Self::ValueType> {
    String::from_str(value).ok()
  }
}

pub struct GraphQLBoolean;
impl_graphql_type_for! {
    GraphQLBoolean where
    name = "Boolean",
    description = "The Boolean scalar type represents true or false."
}

impl GraphQLScalar for GraphQLBoolean {
  type ValueType = bool;
  fn coerce_literal(&self, value: &str) -> Option<Self::ValueType> {
    bool::from_str(value).ok()
  }
}

pub struct GraphQLEnum {
  name: String,
  description: Option<String>,
  values: HashMap<String, GraphQLEnumValue>,
}

impl GraphQLEnum {
  fn values(&self) -> &HashMap<String, GraphQLEnumValue> {
    &self.values
  }
}

pub struct GraphQLEnumValue {
  value: String,
  description: Option<String>,
  depreciation_reason: Option<String>,
}

impl GraphQLEnumValue {
  pub fn new(value: &str) -> GraphQLEnumValue {
    GraphQLEnumValue {
      value: value.to_owned(),
      description: None,
      depreciation_reason: None,
    }
  }

  pub fn value(&self) -> &str {
    self.value.as_ref()
  }

  pub fn description(&self) -> Option<&str> {
    self.description.as_ref().map(|s| s.as_ref())
  }

  pub fn with_description(mut self, description: &str) -> GraphQLEnumValue {
    self.description = Some(description.to_owned());
    self
  }

  pub fn mark_depreciated(mut self, depreciation_reason: &str) -> GraphQLEnumValue {
    let reason = depreciation_reason.trim().to_owned();
    if reason.len() == 0 {
      panic!("Deprecation reason for enum value {:?} cannot be empty",
             self.value);
    }
    self.depreciation_reason = Some(reason);
    self
  }
}

pub struct GraphQLEnumBuilder {
  name: String,
  description: Option<String>,
  values: HashMap<String, GraphQLEnumValue>,
}

impl GraphQLEnumBuilder {
  fn new(name: &str) -> GraphQLEnumBuilder {
    GraphQLEnumBuilder {
      name: name.to_owned(),
      description: None,
      values: HashMap::new(),
    }
  }

  fn with_description(mut self, description: &str) -> GraphQLEnumBuilder {
    self.description = Some(description.to_owned());
    self
  }

  fn value_fn<F>(mut self, name: &str, f: F) -> GraphQLEnumBuilder
    where F: FnOnce(GraphQLEnumValue) -> GraphQLEnumValue
  {
    let v = f(GraphQLEnumValue::new(name));
    self.values.insert(v.value.clone(), v);
    self
  }

  fn value(mut self, name: &str) -> GraphQLEnumBuilder {
    self.values.insert(name.to_owned(), GraphQLEnumValue::new(name));
    self
  }

  fn build(self) -> GraphQLEnum {
    if self.values.len() == 0 {
      panic!("Enum {:?} must has at least one value defined.", self.name);
    }

    GraphQLEnum {
      name: self.name,
      description: self.description,
      values: self.values,
    }
  }
}

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

  #[test]
  fn test_scalar_type() {
    let int_t = GraphQLInt;
    assert_eq!("Int", int_t.name());
    assert_eq!(Some(10), int_t.coerce_literal("10"));
    assert_eq!(None, int_t.coerce_literal("a"));

    let float_t = GraphQLFloat;
    assert_eq!("Float", float_t.name());
    assert_eq!(Some(2.0), float_t.coerce_literal("2.0"));
    assert_eq!(Some(2.0), float_t.coerce_literal("2"));
    assert_eq!(None, float_t.coerce_literal("2.0a"));

    let string_t = GraphQLString;
    assert_eq!("String", string_t.name());
    assert_eq!(Some(String::from("abc")), string_t.coerce_literal("abc"));
    assert_eq!(Some(String::from("2.0")), string_t.coerce_literal("2.0"));

    let boolean_t = GraphQLBoolean;
    assert_eq!("Boolean", boolean_t.name());
    assert_eq!(Some(true), boolean_t.coerce_literal("true"));
    assert_eq!(Some(false), boolean_t.coerce_literal("false"));
    assert_eq!(None, boolean_t.coerce_literal("1"));
    assert_eq!(None, boolean_t.coerce_literal("0"));
    assert_eq!(None, boolean_t.coerce_literal("True"));
    assert_eq!(None, boolean_t.coerce_literal("False"));
    assert_eq!(None, boolean_t.coerce_literal("TRUE"));
    assert_eq!(None, boolean_t.coerce_literal("FALSE"));
  }

  #[test]
  fn test_enum_type() {
    let rgb = GraphQLEnumBuilder::new("RGB")
                .value("RED")
                .value("GREEN")
                .value("BLUE")
                .build();
    assert_eq!(3, rgb.values().len());

    let days = GraphQLEnumBuilder::new("DAYS")
                 .with_description("Days of the week")
                 .value_fn("SAT", |v| v.with_description("Satarday"))
                 .value_fn("SUN", |v| v.with_description("Sunday"))
                 .value_fn("MON", |v| v.with_description("Monday"))
                 .value_fn("TUE", |v| v.with_description("Tuesday"))
                 .value_fn("WED", |v| v.with_description("Wedsday"))
                 .value_fn("THU", |v| v.with_description("Thusday"))
                 .value_fn("FRI", |v| v.with_description("Friday"))
                 .build();
    assert_eq!("Days of the week", days.description().unwrap_or(""));
    assert_eq!("Monday", days.values()["MON"].description().unwrap_or(""));;
  }
}
<commit_msg>add test cases for GraphQLInt<commit_after>use std::collections::HashMap;
use std::str::FromStr;
use std::any::Any;

macro_rules! blanket_impl {
  ($trait_: ident for $($type_: ty),*) => {
    $(
      impl $trait_ for $type_ {}
    )*
  };
}

macro_rules! impl_graphql_type_for {
    ($tt: ty where name = $name: expr, description = $desc: expr) => {
        impl GraphQLType for $tt {
            fn name(&self) -> &str { $name }
            fn description(&self) -> Option<&str> { Some($desc) }
        }
    };

    ($($type_: ty),*) => {
      $(
        impl GraphQLType for $type_ {
            fn name(&self) -> &str { self.name.as_ref() }

            fn description(&self) -> Option<&str> {
                self.description.as_ref().map(|s| s.as_ref())
            }
        }
      )*
    };
}

pub trait GraphQLType {
  fn name(&self) -> &str;
  fn description(&self) -> Option<&str>;
}
impl_graphql_type_for! { GraphQLEnum }

pub trait GraphQLScalar: GraphQLType {
  type ValueType: Any;
  fn coerce_literal(&self, value: &str) -> Option<Self::ValueType>;
}

pub struct GraphQLInt;
impl_graphql_type_for! {
    GraphQLInt where
    name = "Int",
    description = "The Int scalar type represents a signed 32‐bit numeric non‐fractional values."
}

impl GraphQLScalar for GraphQLInt {
  type ValueType = i32;
  fn coerce_literal(&self, value: &str) -> Option<Self::ValueType> {
    i32::from_str(value).ok()
  }
}

pub struct GraphQLFloat;
impl_graphql_type_for! {
    GraphQLFloat where
    name = "Float",
    description = "The Float scalar type represents signed double-precision fractional values as specified by IEEE 754."
}

impl GraphQLScalar for GraphQLFloat {
  type ValueType = f64;
  fn coerce_literal(&self, value: &str) -> Option<Self::ValueType> {
    f64::from_str(value).ok()
  }
}

pub struct GraphQLString;
impl_graphql_type_for! {
    GraphQLString where
    name = "String",
    description = "The String scalar type represents textual data, represented as UTF-8 character sequences."
}

impl GraphQLScalar for GraphQLString {
  type ValueType = String;
  fn coerce_literal(&self, value: &str) -> Option<Self::ValueType> {
    String::from_str(value).ok()
  }
}

pub struct GraphQLBoolean;
impl_graphql_type_for! {
    GraphQLBoolean where
    name = "Boolean",
    description = "The Boolean scalar type represents true or false."
}

impl GraphQLScalar for GraphQLBoolean {
  type ValueType = bool;
  fn coerce_literal(&self, value: &str) -> Option<Self::ValueType> {
    bool::from_str(value).ok()
  }
}

pub struct GraphQLEnum {
  name: String,
  description: Option<String>,
  values: HashMap<String, GraphQLEnumValue>,
}

impl GraphQLEnum {
  fn values(&self) -> &HashMap<String, GraphQLEnumValue> {
    &self.values
  }
}

pub struct GraphQLEnumValue {
  value: String,
  description: Option<String>,
  depreciation_reason: Option<String>,
}

impl GraphQLEnumValue {
  pub fn new(value: &str) -> GraphQLEnumValue {
    GraphQLEnumValue {
      value: value.to_owned(),
      description: None,
      depreciation_reason: None,
    }
  }

  pub fn value(&self) -> &str {
    self.value.as_ref()
  }

  pub fn description(&self) -> Option<&str> {
    self.description.as_ref().map(|s| s.as_ref())
  }

  pub fn with_description(mut self, description: &str) -> GraphQLEnumValue {
    self.description = Some(description.to_owned());
    self
  }

  pub fn mark_depreciated(mut self, depreciation_reason: &str) -> GraphQLEnumValue {
    let reason = depreciation_reason.trim().to_owned();
    if reason.len() == 0 {
      panic!("Deprecation reason for enum value {:?} cannot be empty",
             self.value);
    }
    self.depreciation_reason = Some(reason);
    self
  }
}

pub struct GraphQLEnumBuilder {
  name: String,
  description: Option<String>,
  values: HashMap<String, GraphQLEnumValue>,
}

impl GraphQLEnumBuilder {
  fn new(name: &str) -> GraphQLEnumBuilder {
    GraphQLEnumBuilder {
      name: name.to_owned(),
      description: None,
      values: HashMap::new(),
    }
  }

  fn with_description(mut self, description: &str) -> GraphQLEnumBuilder {
    self.description = Some(description.to_owned());
    self
  }

  fn value_fn<F>(mut self, name: &str, f: F) -> GraphQLEnumBuilder
    where F: FnOnce(GraphQLEnumValue) -> GraphQLEnumValue
  {
    let v = f(GraphQLEnumValue::new(name));
    self.values.insert(v.value.clone(), v);
    self
  }

  fn value(mut self, name: &str) -> GraphQLEnumBuilder {
    self.values.insert(name.to_owned(), GraphQLEnumValue::new(name));
    self
  }

  fn build(self) -> GraphQLEnum {
    if self.values.len() == 0 {
      panic!("Enum {:?} must has at least one value defined.", self.name);
    }

    GraphQLEnum {
      name: self.name,
      description: self.description,
      values: self.values,
    }
  }
}

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

  #[test]
  fn test_scalar_type() {
    let int_t = GraphQLInt;
    assert_eq!("Int", int_t.name());
    assert_eq!(Some(10), int_t.coerce_literal("10"));
    assert_eq!(None, int_t.coerce_literal("10.1"));
    assert_eq!(None, int_t.coerce_literal("a"));
    assert_eq!(None, int_t.coerce_literal(&i64::max_value().to_string()));
    assert_eq!(None, int_t.coerce_literal(&i64::min_value().to_string()));

    let float_t = GraphQLFloat;
    assert_eq!("Float", float_t.name());
    assert_eq!(Some(2.0), float_t.coerce_literal("2.0"));
    assert_eq!(Some(2.0), float_t.coerce_literal("2"));
    assert_eq!(None, float_t.coerce_literal("2.0a"));

    let string_t = GraphQLString;
    assert_eq!("String", string_t.name());
    assert_eq!(Some(String::from("abc")), string_t.coerce_literal("abc"));
    assert_eq!(Some(String::from("2.0")), string_t.coerce_literal("2.0"));

    let boolean_t = GraphQLBoolean;
    assert_eq!("Boolean", boolean_t.name());
    assert_eq!(Some(true), boolean_t.coerce_literal("true"));
    assert_eq!(Some(false), boolean_t.coerce_literal("false"));
    assert_eq!(None, boolean_t.coerce_literal("1"));
    assert_eq!(None, boolean_t.coerce_literal("0"));
    assert_eq!(None, boolean_t.coerce_literal("True"));
    assert_eq!(None, boolean_t.coerce_literal("False"));
    assert_eq!(None, boolean_t.coerce_literal("TRUE"));
    assert_eq!(None, boolean_t.coerce_literal("FALSE"));
  }

  #[test]
  fn test_enum_type() {
    let rgb = GraphQLEnumBuilder::new("RGB")
                .value("RED")
                .value("GREEN")
                .value("BLUE")
                .build();
    assert_eq!(3, rgb.values().len());

    let days = GraphQLEnumBuilder::new("DAYS")
                 .with_description("Days of the week")
                 .value_fn("SAT", |v| v.with_description("Satarday"))
                 .value_fn("SUN", |v| v.with_description("Sunday"))
                 .value_fn("MON", |v| v.with_description("Monday"))
                 .value_fn("TUE", |v| v.with_description("Tuesday"))
                 .value_fn("WED", |v| v.with_description("Wedsday"))
                 .value_fn("THU", |v| v.with_description("Thusday"))
                 .value_fn("FRI", |v| v.with_description("Friday"))
                 .build();
    assert_eq!("Days of the week", days.description().unwrap_or(""));
    assert_eq!("Monday", days.values()["MON"].description().unwrap_or(""));;
  }
}
<|endoftext|>


<commit_before>extern crate ws;

use message::PeerMessage;

use std::cmp;
use std::collections::hash_map::HashMap;
use std::collections::VecDeque;
use std::sync::{Arc, Mutex};

use bincode::rustc_serialize::decode;

use ws::util::Token;

static LIB_NAME: &'static str = "ws-p2p";

const DELAYED_MESSAGE: Token = Token(1);

/// Connection handler for incoming messages.
pub struct MessageHandler {
    /// Sender that is used to communicate for the handler.
    pub ws: ws::Sender,
    /// An arc clone of my local vector clocks.
    pub clocks: Arc<Mutex<HashMap<String, u32>>>,
    /// My address/name.
    pub me: String,
    /// Buffer of messages that caused conflicts when initially received.
    pub buffer: Arc<Mutex<VecDeque<PeerMessage>>>,
    /// Delays messages received from client.
    pub demo_client: Option<String>,
    /// Holder for delayed messages.
    message_queue: VecDeque<PeerMessage>,
}

impl ws::Handler for MessageHandler {
    fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> {
        match msg {
            ws::Message::Binary(vector) => {
                let encoded_msg = &*vector.into_boxed_slice();
                let message: PeerMessage = decode(encoded_msg).unwrap();

                debug!(target: LIB_NAME, "I am using {:?}.", self.ws.token());

                if let Some(demo_client) = self.demo_client.clone() {
                    if message.sender.as_str() == demo_client.as_str() {
                        info!(target: LIB_NAME, "Faking delay for messages from {}!", demo_client);
                        self.message_queue.push_back(message);
                        return self.ws.timeout(4000, DELAYED_MESSAGE);
                    }
                }

                self.message_handler(message);
                Ok(())
            }
            ws::Message::Text(string) => {
                info!(target: LIB_NAME, "Received peer's name. Adding {} to client list", string);
                let mut clocks = self.clocks.lock().unwrap();
                clocks.insert(string, 0u32);
                Ok(())
            }
        }
    }
    fn on_timeout(&mut self, event: Token) -> ws::Result<()> {
        match event {
            DELAYED_MESSAGE => {
                let msg = self.message_queue.pop_front().unwrap();
                self.message_handler(msg);
                Ok(())
            }
            _ => Err(ws::Error::new(ws::ErrorKind::Internal,
                                    "Invalid timeout token encountered!")),
        }
    }
    fn on_close(&mut self, code: ws::CloseCode, reason: &str) {
        // TODO: Remove disconnected client's clock from our vclock copy.
        if reason.is_empty() {
            // This works: CloseCode::Abnormal
            info!(target: LIB_NAME, "Client disconnected with code: {:?}", code);
        } else {
            info!(target: LIB_NAME, "{} d/c with code: {:?} and reason: {}", self.me, code, reason);
        }
    }
    fn on_error(&mut self, err: ws::Error) {
        warn!(target: LIB_NAME, "Error family robinson! {:?}", err.kind);
    }
    fn on_shutdown(&mut self) {
        warn!(target: LIB_NAME, "Socket shutdown from {}", self.me);
    }
}

impl MessageHandler {
    fn buffer_check(&self) {
        let mut buffer = self.buffer.lock().unwrap();
        let buffer_clone = buffer.clone();
        for message in buffer_clone.iter() {
            let mut vclocks = self.clocks.lock().unwrap();
            for (key, val) in message.clocks.iter() {
                if key.as_str() == message.sender.as_str() {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        if *val != *lval + 1 {
                            debug!(target: LIB_NAME, "discrepency still exists");
                            return;
                        }
                    }
                } else {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        debug!(target: LIB_NAME, "key: {} val: {} and lval: {}", key, val, lval);
                        if val <= lval {
                            debug!(target: LIB_NAME, "val <= lval");
                            continue;
                        } else {
                            // There's a clock that is greater than what we have
                            debug!(target: LIB_NAME, "discrepency still exists");
                            return;
                        }
                    }
                }
            }

            // Update clocks
            for (key, val) in message.clocks.iter() {
                let lval = vclocks.get(&key.clone()).unwrap().clone();
                let max_val = cmp::max(val, &lval);
                vclocks.insert(key.clone(), *max_val);
            }
            info!(target: LIB_NAME, "buf_check: Peer {} with clocks: {:?} got message: {}",
                    message.sender, message.clocks, message.message);
            buffer.pop_front();
        }
    }
    fn message_handler(&self, message: PeerMessage) {
        {
            let mut vclocks = self.clocks.lock().unwrap();
            for (key, val) in message.clocks.iter() {
                if key.as_str() == message.sender.as_str() {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        if *val != *lval + 1 {
                            let mut buffer = self.buffer.lock().unwrap();
                            buffer.push_back(message.clone());
                            debug!(target: LIB_NAME, "clock discrepency with from incoming peer");
                            return;
                        }
                    }
                } else {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        debug!(target: LIB_NAME, "key: {} val: {} and lval: {}", key, val, lval);
                        if val <= lval {
                            debug!(target: LIB_NAME, "val <= lval");
                            continue;
                        } else {
                            // There's a clock that is greater than what we have
                            // Push to local buffer
                            let mut buffer = self.buffer.lock().unwrap();
                            buffer.push_back(message.clone());
                            debug!(target: LIB_NAME, "clock discrepency from other peer clocks");
                            return;
                        }
                    }
                }
            }

            // Update clocks
            debug!(target: LIB_NAME, "Updating clocks now because no discrepency");
            info!(target: LIB_NAME, "msg_handler: Peer {} with clocks: {:?} got message: {}",
                    message.sender, message.clocks, message.message);
            for (key, val) in message.clocks.iter() {
                vclocks.insert(key.clone(), *val);
            }
        }
        self.buffer_check();
    }
}

#[derive(Clone)]
pub struct MessageFactory {
    vclocks: Arc<Mutex<HashMap<String, u32>>>,
    me: String,
    buffer: Arc<Mutex<VecDeque<PeerMessage>>>,
    demo_client: Option<String>,
}

impl MessageFactory {
    pub fn build(vclocks: Arc<Mutex<HashMap<String, u32>>>) -> MessageFactory {
        MessageFactory {
            vclocks: vclocks.clone(),
            me: String::from("undefined"),
            buffer: Arc::new(Mutex::new(VecDeque::new())),
            demo_client: None,
        }
    }
    pub fn me(&self, me: &str) -> MessageFactory {
        MessageFactory {
            vclocks: self.vclocks.clone(),
            me: String::from(me),
            buffer: self.buffer.clone(),
            demo_client: match self.demo_client.clone() {
                Some(peer) => Some(peer),
                None => None,
            },
        }
    }
    pub fn demo(&mut self, peer: &str) {
        self.demo_client = Some(String::from(peer));
    }
}

impl ws::Factory for MessageFactory {
    type Handler = MessageHandler;

    fn connection_made(&mut self, ws: ws::Sender) -> Self::Handler {
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
            demo_client: self.demo_client.clone(),
            message_queue: VecDeque::new(),
        }
    }

    fn server_connected(&mut self, ws: ws::Sender) -> Self::Handler {
        ws.send(self.me.clone()).unwrap();
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
            demo_client: self.demo_client.clone(),
            message_queue: VecDeque::new(),
        }
    }

    fn client_connected(&mut self, ws: ws::Sender) -> Self::Handler {
        ws.send(self.me.clone()).unwrap();
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
            demo_client: self.demo_client.clone(),
            message_queue: VecDeque::new(),
        }
    }
}
<commit_msg>Remove decoding unwrap call<commit_after>extern crate ws;

use message::PeerMessage;

use std::cmp;
use std::collections::hash_map::HashMap;
use std::collections::VecDeque;
use std::sync::{Arc, Mutex};

use bincode::rustc_serialize::decode;

use ws::util::Token;

static LIB_NAME: &'static str = "ws-p2p";

const DELAYED_MESSAGE: Token = Token(1);

/// Connection handler for incoming messages.
pub struct MessageHandler {
    /// Sender that is used to communicate for the handler.
    pub ws: ws::Sender,
    /// An arc clone of my local vector clocks.
    pub clocks: Arc<Mutex<HashMap<String, u32>>>,
    /// My address/name.
    pub me: String,
    /// Buffer of messages that caused conflicts when initially received.
    pub buffer: Arc<Mutex<VecDeque<PeerMessage>>>,
    /// Delays messages received from client.
    pub demo_client: Option<String>,
    /// Holder for delayed messages.
    message_queue: VecDeque<PeerMessage>,
}

impl ws::Handler for MessageHandler {
    fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> {
        match msg {
            ws::Message::Binary(vector) => {
                let encoded_msg = &*vector.into_boxed_slice();
                if let Ok(message) = decode(encoded_msg) {
                    //let message: PeerMessage = decode(encoded_msg).unwrap();
                    let message: PeerMessage = message;

                    debug!(target: LIB_NAME, "I am using {:?}.", self.ws.token());

                    if let Some(demo_client) = self.demo_client.clone() {
                        if message.sender.as_str() == demo_client.as_str() {
                            info!(target: LIB_NAME, "Faking delay for messages from {}!", demo_client);
                            self.message_queue.push_back(message);
                            return self.ws.timeout(4000, DELAYED_MESSAGE);
                        }
                    }

                    self.message_handler(message);
                    Ok(())
                } else {
                    Err(ws::Error::new(ws::ErrorKind::Internal,
                                    "Failed to serialize the binary message."))
                }
            }
            ws::Message::Text(string) => {
                info!(target: LIB_NAME, "Received peer's name. Adding {} to client list", string);
                let mut clocks = self.clocks.lock().unwrap();
                clocks.insert(string, 0u32);
                Ok(())
            }
        }
    }
    fn on_timeout(&mut self, event: Token) -> ws::Result<()> {
        match event {
            DELAYED_MESSAGE => {
                let msg = self.message_queue.pop_front().unwrap();
                self.message_handler(msg);
                Ok(())
            }
            _ => Err(ws::Error::new(ws::ErrorKind::Internal,
                                    "Invalid timeout token encountered!")),
        }
    }
    fn on_close(&mut self, code: ws::CloseCode, reason: &str) {
        // TODO: Remove disconnected client's clock from our vclock copy.
        if reason.is_empty() {
            // This works: CloseCode::Abnormal
            info!(target: LIB_NAME, "Client disconnected with code: {:?}", code);
        } else {
            info!(target: LIB_NAME, "{} d/c with code: {:?} and reason: {}", self.me, code, reason);
        }
    }
    fn on_error(&mut self, err: ws::Error) {
        warn!(target: LIB_NAME, "Error family robinson! {:?}", err.kind);
    }
    fn on_shutdown(&mut self) {
        warn!(target: LIB_NAME, "Socket shutdown from {}", self.me);
    }
}

impl MessageHandler {
    fn buffer_check(&self) {
        let mut buffer = self.buffer.lock().unwrap();
        let buffer_clone = buffer.clone();
        for message in buffer_clone.iter() {
            let mut vclocks = self.clocks.lock().unwrap();
            for (key, val) in message.clocks.iter() {
                if key.as_str() == message.sender.as_str() {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        if *val != *lval + 1 {
                            debug!(target: LIB_NAME, "discrepency still exists");
                            return;
                        }
                    }
                } else {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        debug!(target: LIB_NAME, "key: {} val: {} and lval: {}", key, val, lval);
                        if val <= lval {
                            debug!(target: LIB_NAME, "val <= lval");
                            continue;
                        } else {
                            // There's a clock that is greater than what we have
                            debug!(target: LIB_NAME, "discrepency still exists");
                            return;
                        }
                    }
                }
            }

            // Update clocks
            for (key, val) in message.clocks.iter() {
                let lval = vclocks.get(&key.clone()).unwrap().clone();
                let max_val = cmp::max(val, &lval);
                vclocks.insert(key.clone(), *max_val);
            }
            info!(target: LIB_NAME, "buf_check: Peer {} with clocks: {:?} got message: {}",
                    message.sender, message.clocks, message.message);
            buffer.pop_front();
        }
    }
    fn message_handler(&self, message: PeerMessage) {
        {
            let mut vclocks = self.clocks.lock().unwrap();
            for (key, val) in message.clocks.iter() {
                if key.as_str() == message.sender.as_str() {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        if *val != *lval + 1 {
                            let mut buffer = self.buffer.lock().unwrap();
                            buffer.push_back(message.clone());
                            debug!(target: LIB_NAME, "clock discrepency with from incoming peer");
                            return;
                        }
                    }
                } else {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        debug!(target: LIB_NAME, "key: {} val: {} and lval: {}", key, val, lval);
                        if val <= lval {
                            debug!(target: LIB_NAME, "val <= lval");
                            continue;
                        } else {
                            // There's a clock that is greater than what we have
                            // Push to local buffer
                            let mut buffer = self.buffer.lock().unwrap();
                            buffer.push_back(message.clone());
                            debug!(target: LIB_NAME, "clock discrepency from other peer clocks");
                            return;
                        }
                    }
                }
            }

            // Update clocks
            debug!(target: LIB_NAME, "Updating clocks now because no discrepency");
            info!(target: LIB_NAME, "msg_handler: Peer {} with clocks: {:?} got message: {}",
                    message.sender, message.clocks, message.message);
            for (key, val) in message.clocks.iter() {
                vclocks.insert(key.clone(), *val);
            }
        }
        self.buffer_check();
    }
}

#[derive(Clone)]
pub struct MessageFactory {
    vclocks: Arc<Mutex<HashMap<String, u32>>>,
    me: String,
    buffer: Arc<Mutex<VecDeque<PeerMessage>>>,
    demo_client: Option<String>,
}

impl MessageFactory {
    pub fn build(vclocks: Arc<Mutex<HashMap<String, u32>>>) -> MessageFactory {
        MessageFactory {
            vclocks: vclocks.clone(),
            me: String::from("undefined"),
            buffer: Arc::new(Mutex::new(VecDeque::new())),
            demo_client: None,
        }
    }
    pub fn me(&self, me: &str) -> MessageFactory {
        MessageFactory {
            vclocks: self.vclocks.clone(),
            me: String::from(me),
            buffer: self.buffer.clone(),
            demo_client: match self.demo_client.clone() {
                Some(peer) => Some(peer),
                None => None,
            },
        }
    }
    pub fn demo(&mut self, peer: &str) {
        self.demo_client = Some(String::from(peer));
    }
}

impl ws::Factory for MessageFactory {
    type Handler = MessageHandler;

    fn connection_made(&mut self, ws: ws::Sender) -> Self::Handler {
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
            demo_client: self.demo_client.clone(),
            message_queue: VecDeque::new(),
        }
    }

    fn server_connected(&mut self, ws: ws::Sender) -> Self::Handler {
        ws.send(self.me.clone()).unwrap();
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
            demo_client: self.demo_client.clone(),
            message_queue: VecDeque::new(),
        }
    }

    fn client_connected(&mut self, ws: ws::Sender) -> Self::Handler {
        ws.send(self.me.clone()).unwrap();
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
            demo_client: self.demo_client.clone(),
            message_queue: VecDeque::new(),
        }
    }
}
<|endoftext|>


<commit_before>use ::arch::vga;
use core::ptr::Unique;
use core::mem;
use core::fmt::{Write, Result};
use spin::Mutex;

pub struct Terminal { buffer: Unique<vga::Buffer>
                    , x: usize
                    , y: usize
                    , colors: vga::Palette
                    }

impl Terminal {

    #[inline]
    fn buffer(&mut self) -> &mut vga::Buffer {
        unsafe { self.buffer.get_mut() }
    }

    fn scroll(&mut self) {
        let mut rows = self.buffer()
                           .iter_mut();

        let mut next = rows.next()
                           .unwrap();

        while let Some(thing) = rows.next() {
            mem::swap(next, thing);
            next = thing;
        }

        // empty last line
        unsafe { *next = mem::zeroed() }
    }

    pub fn clear(&mut self) {
        unsafe { *(self.buffer()) = mem::zeroed(); }
    }

    pub fn write_byte(&mut self, byte: u8) {
        if byte == b'\n' {
            self.x = 0;
            self.y += 1;
        } else {
            // set character at position
            self.buffer()[self.x][self.y]
                = vga::Char { ascii: byte
                            , colors: self.colors };
            self.x += 1;

            // check for line wrapping
            if self.x >= vga::X_MAX {
                self.x = 0;
                self.y += 1;
            }
        }
        // check for scrolling
        if self.y >= vga::Y_MAX {
            self.scroll();
            self.y = vga::Y_MAX- 1;
        }

    }

}

impl Write for Terminal {

    fn write_str(&mut self, s: &str) -> Result {
        for byte in s.as_bytes() {
            self.write_byte(*byte)
        }
        Ok(())
    }

}

/// The system's VGA terminal
pub static CONSOLE: Mutex<Terminal>
    = Mutex::new(Terminal {
        colors: vga::Palette::new( vga::Color::LightGreen
                                 , vga::Color::Black
                                 )
      , x: 0
      , y: 0
      , buffer: unsafe { Unique::new(0xB8000 as *mut _) },
    });
<commit_msg>Fix incorrect indexing of VGA buffer This resulted in an issue where lines of text were displayed vertically rather than horizontally. I am very dumb.<commit_after>use ::arch::vga;
use core::ptr::Unique;
use core::mem;
use core::fmt::{Write, Result};
use spin::Mutex;

pub struct Terminal { buffer: Unique<vga::Buffer>
                    , x: usize
                    , y: usize
                    , colors: vga::Palette
                    }

impl Terminal {

    #[inline]
    fn buffer(&mut self) -> &mut vga::Buffer {
        unsafe { self.buffer.get_mut() }
    }

    fn scroll(&mut self) {
        let mut rows = self.buffer()
                           .iter_mut();

        let mut next = rows.next()
                           .unwrap();

        while let Some(thing) = rows.next() {
            mem::swap(next, thing);
            next = thing;
        }

        // empty last line
        unsafe { *next = mem::zeroed() }
    }

    pub fn clear(&mut self) {
        unsafe { *(self.buffer()) = mem::zeroed(); }
    }

    pub fn write_byte(&mut self, byte: u8) {
        if byte == b'\n' {
            self.x = 0;
            self.y += 1;
        } else {
            // set character at position
            self.buffer()[self.y][self.x]
                = vga::Char { ascii: byte
                            , colors: self.colors };
            self.x += 1;

            // check for line wrapping
            if self.x >= vga::X_MAX {
                self.x = 0;
                self.y += 1;
            }
        }
        // check for scrolling
        if self.y >= vga::Y_MAX {
            self.scroll();
            self.y = vga::Y_MAX- 1;
        }

    }

}

impl Write for Terminal {

    fn write_str(&mut self, s: &str) -> Result {
        for byte in s.as_bytes() {
            self.write_byte(*byte)
        }
        Ok(())
    }

}

/// The system's VGA terminal
pub static CONSOLE: Mutex<Terminal>
    = Mutex::new(Terminal {
        colors: vga::Palette::new( vga::Color::LightGreen
                                 , vga::Color::Black
                                 )
      , x: 0
      , y: 0
      , buffer: unsafe { Unique::new(0xB8000 as *mut _) },
    });
<|endoftext|>


<commit_before>#![crate_id = "github.com/TomBebbington/js.rs#js:0.1"]
#![comment = "Javascript parsing, compilation and execution using LibJIT"]
#![license = "MIT"]
#![crate_type = "lib"]
#![doc(
    html_favicon_url = "http://tombebbington.github.io/favicon.png",
    html_root_url = "http://tombebbington.github.io/js.rs/"
)]
#![experimental]
#![feature(phase, macro_rules, globs)]
#![deny(non_uppercase_statics, missing_doc, unnecessary_parens, unrecognized_lint,
	unreachable_code, unnecessary_allocation, unnecessary_typecast, unnecessary_allocation,
	uppercase_variables, non_camel_case_types, unused_must_use)]
//! This is a library with seperate modules for Javascript parsing, the Javascript
//! standard library, and Javascript execution through LibJIT
extern crate collections;
extern crate jit;
#[phase(plugin, link)]
extern crate log;
extern crate serialize;
extern crate time;
extern crate url;
/// The backend-defining traits and the Javascript standard library
pub mod front {
	#[macro_escape]
	/// A macro which makes Javascript objects with pretty Rust syntax
	pub mod macro;
	/// Backend-defining traits
	pub mod run {
		/// For compiling Javascript values
		pub mod compiler;
		/// For executing the compiled Javascript values
		pub mod executor;
	}
	/// The Javascript standard library
	pub mod stdlib {
		/// The `Array` global object
		pub mod array;
		/// The `Boolean` global object
		pub mod boolean;
		/// The `console` global object
		pub mod console;
		/// The `Error` global objects
		pub mod error;
		/// The `Function` global object
		pub mod function;
		/// The `JSON` global object
		pub mod json;
		/// The `Math` global object
		pub mod math;
		/// The `Number` global object and related global methods
		pub mod number;
		/// The `Object` global object
		pub mod object;
		/// The `String` global object
		pub mod string;
		/// The global URI methods
		pub mod uri;
		/// An arbritary Javascript value
		pub mod value;
	}
}
/// The default backend implemented on top of LibJIT
pub mod back {
	/// The compiler, which transforms Javascript expressions to LibJIT IR
	pub mod compiler;
	/// The executor, which runs the LibJIT IR by compiling it then running it
	pub mod executor;
}
/// Javascript parsing and syntax
pub mod syntax {
	/// The Javascript Abstract Syntax Tree
	pub mod ast {
		/// Constants
		pub mod constant;
		/// Expressions
		pub mod expr;
		/// Keywords
		pub mod keyword;
		/// Operators
		pub mod op;
		/// Positions
		pub mod pos;
		/// Punctuators
		pub mod punc;
		/// Tokens
		pub mod token;
		/// An expression typer
		pub mod typer;
		/// Types
		pub mod types;
	}
	/// Parses a string stream into a sequence of tokens
	pub mod lexer;
	/// Parses a sequence of tokens into expressions
	pub mod parser;
}<commit_msg>Remove root url of docs<commit_after>#![crate_id = "github.com/TomBebbington/js.rs#js:0.1"]
#![comment = "Javascript parsing, compilation and execution using LibJIT"]
#![license = "MIT"]
#![crate_type = "lib"]
#![doc(
    html_favicon_url = "http://tombebbington.github.io/favicon.png"
#![experimental]
#![feature(phase, macro_rules, globs)]
#![deny(non_uppercase_statics, missing_doc, unnecessary_parens, unrecognized_lint,
	unreachable_code, unnecessary_allocation, unnecessary_typecast, unnecessary_allocation,
	uppercase_variables, non_camel_case_types, unused_must_use)]
//! This is a library with seperate modules for Javascript parsing, the Javascript
//! standard library, and Javascript execution through LibJIT
extern crate collections;
extern crate jit;
#[phase(plugin, link)]
extern crate log;
extern crate serialize;
extern crate time;
extern crate url;
/// The backend-defining traits and the Javascript standard library
pub mod front {
	#[macro_escape]
	/// A macro which makes Javascript objects with pretty Rust syntax
	pub mod macro;
	/// Backend-defining traits
	pub mod run {
		/// For compiling Javascript values
		pub mod compiler;
		/// For executing the compiled Javascript values
		pub mod executor;
	}
	/// The Javascript standard library
	pub mod stdlib {
		/// The `Array` global object
		pub mod array;
		/// The `Boolean` global object
		pub mod boolean;
		/// The `console` global object
		pub mod console;
		/// The `Error` global objects
		pub mod error;
		/// The `Function` global object
		pub mod function;
		/// The `JSON` global object
		pub mod json;
		/// The `Math` global object
		pub mod math;
		/// The `Number` global object and related global methods
		pub mod number;
		/// The `Object` global object
		pub mod object;
		/// The `String` global object
		pub mod string;
		/// The global URI methods
		pub mod uri;
		/// An arbritary Javascript value
		pub mod value;
	}
}
/// The default backend implemented on top of LibJIT
pub mod back {
	/// The compiler, which transforms Javascript expressions to LibJIT IR
	pub mod compiler;
	/// The executor, which runs the LibJIT IR by compiling it then running it
	pub mod executor;
}
/// Javascript parsing and syntax
pub mod syntax {
	/// The Javascript Abstract Syntax Tree
	pub mod ast {
		/// Constants
		pub mod constant;
		/// Expressions
		pub mod expr;
		/// Keywords
		pub mod keyword;
		/// Operators
		pub mod op;
		/// Positions
		pub mod pos;
		/// Punctuators
		pub mod punc;
		/// Tokens
		pub mod token;
		/// An expression typer
		pub mod typer;
		/// Types
		pub mod types;
	}
	/// Parses a string stream into a sequence of tokens
	pub mod lexer;
	/// Parses a sequence of tokens into expressions
	pub mod parser;
}<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use std::hash::Hash;
use std::rc::Rc;

struct CacheEntry<V> {
    val: V,
    instant: u64,
}

pub struct LRUCache<K: Eq + Hash, V> {
    capacity: usize,
    clock: u64,
    data: HashMap<Rc<K>, CacheEntry<V>>,
    order: BTreeMap<u64, Rc<K>>,
}

impl<K, V> LRUCache<K, V>
    where K: Eq + Hash
{
    pub fn new(capacity: usize) -> LRUCache<K, V> {
        LRUCache {
            capacity: capacity,
            clock: 0,
            data: HashMap::with_capacity(capacity),
            order: BTreeMap::new(),
        }
    }

    pub fn get(&mut self, k: K) -> Option<&V> {
        let now = self.clock;
        let k = Rc::new(k);
        let prev = match self.data.entry(k.clone()) {
            Entry::Occupied(mut e) => {
                self.clock += 1;
                let e = e.get_mut();
                let prev = e.instant;
                e.instant = now;
                Some(prev)
            }
            _ => None,
        };
        match prev {
            Some(t) => {
                let key = self.order.remove(&t);
                self.order.insert(now, key.unwrap());
                self.data.get(k.as_ref()).as_ref().map(|x| &x.val)
            }
            None => None,
        }
    }

    pub fn insert(&mut self, key: K, val: V) {
        let now = self.clock;
        self.clock += 1;
        let size = self.data.len();
        let key = Rc::new(key);
        let evict = match self.data.entry(key.clone()) {
            Entry::Occupied(mut e) => {
                let e = e.get_mut();
                let prev = e.instant;
                e.instant = now;
                e.val = val;
                self.order.remove(&prev);
                self.order.insert(now, key.clone());
                None
            }
            Entry::Vacant(e) => {
                let entry = CacheEntry {
                    val: val,
                    instant: now,
                };
                e.insert(entry);
                self.order.insert(now, key.clone());
                if size == self.capacity {
                    let oldest = self.order.keys().cloned().next().unwrap();
                    Some(self.order.remove(&oldest).unwrap())
                } else {
                    None
                }
            }
        };
        match evict {
            Some(k) => {
                self.data.remove(k.as_ref());
            }
            None => {}
        };
    }

    pub fn len(&self) -> usize {
        debug_assert!(self.data.len() == self.order.len());
        self.data.len()
    }

}

#[test]
fn lru_cache() {
    let mut cache = LRUCache::new(3);
    assert_eq!(0, cache.clock);
    assert_eq!(0, cache.len());

    cache.insert(1, 2);
    cache.insert(3, 4);
    cache.insert(5, 6);
    assert_eq!(3, cache.clock);
    assert_eq!(3, cache.len());
    assert_eq!(Some(&2), cache.get(1));
    assert_eq!(Some(&4), cache.get(3));
    assert_eq!(Some(&6), cache.get(5));
    assert_eq!(None, cache.get(7));
    assert_eq!(6, cache.clock);

    cache.insert(1, 1);
    cache.insert(3, 3);
    cache.insert(5, 6);
    assert_eq!(9, cache.clock);
    assert_eq!(3, cache.len());
    assert_eq!(Some(&1), cache.get(1));
    assert_eq!(Some(&3), cache.get(3));
    assert_eq!(Some(&6), cache.get(5));
    assert_eq!(None, cache.get(7));

    cache.insert(7, 8);
    assert_eq!(3, cache.len());
    assert_eq!(None, cache.get(1));
    assert_eq!(Some(&3), cache.get(3));
    assert_eq!(Some(&6), cache.get(5));
    assert_eq!(Some(&8), cache.get(7));
    assert_eq!(16, cache.clock);
}
<commit_msg>Cleanup function signatures.<commit_after>use std::collections::BTreeMap;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use std::hash::Hash;
use std::rc::Rc;

struct CacheEntry<V> {
    val: V,
    instant: u64,
}

pub struct LRUCache<K: Eq + Hash, V> {
    capacity: usize,
    clock: u64,
    data: HashMap<Rc<K>, CacheEntry<V>>,
    order: BTreeMap<u64, Rc<K>>,
}

impl<K, V> LRUCache<K, V>
    where K: Eq + Hash
{
    pub fn new(capacity: usize) -> LRUCache<K, V> {
        LRUCache {
            capacity: capacity,
            clock: 0,
            data: HashMap::with_capacity(capacity),
            order: BTreeMap::new(),
        }
    }

    pub fn get(&mut self, key: K) -> Option<&V> {
        let now = self.clock;
        let key = Rc::new(key);
        let prev = match self.data.entry(key.clone()) {
            Entry::Occupied(mut e) => {
                self.clock += 1;
                let e = e.get_mut();
                let prev = e.instant;
                e.instant = now;
                Some(prev)
            }
            _ => None,
        };
        match prev {
            Some(t) => {
                let k = self.order.remove(&t);
                self.order.insert(now, k.unwrap());
                self.data.get(key.as_ref()).as_ref().map(|x| &x.val)
            }
            None => None,
        }
    }

    pub fn insert(&mut self, key: K, val: V) {
        let now = self.clock;
        self.clock += 1;
        let size = self.data.len();
        let key = Rc::new(key);
        let evict = match self.data.entry(key.clone()) {
            Entry::Occupied(mut e) => {
                let e = e.get_mut();
                let prev = e.instant;
                e.instant = now;
                e.val = val;
                self.order.remove(&prev);
                self.order.insert(now, key.clone());
                None
            }
            Entry::Vacant(e) => {
                let entry = CacheEntry {
                    val: val,
                    instant: now,
                };
                e.insert(entry);
                self.order.insert(now, key.clone());
                if size == self.capacity {
                    let oldest = self.order.keys().cloned().next().unwrap();
                    Some(self.order.remove(&oldest).unwrap())
                } else {
                    None
                }
            }
        };
        match evict {
            Some(k) => {
                self.data.remove(k.as_ref());
            }
            None => {}
        };
    }

    pub fn len(&self) -> usize {
        debug_assert!(self.data.len() == self.order.len());
        self.data.len()
    }
}

#[test]
fn lru_cache() {
    let mut cache = LRUCache::new(3);
    assert_eq!(0, cache.clock);
    assert_eq!(0, cache.len());

    cache.insert(1, 2);
    cache.insert(3, 4);
    cache.insert(5, 6);
    assert_eq!(3, cache.clock);
    assert_eq!(3, cache.len());
    assert_eq!(Some(&2), cache.get(1));
    assert_eq!(Some(&4), cache.get(3));
    assert_eq!(Some(&6), cache.get(5));
    assert_eq!(None, cache.get(7));
    assert_eq!(6, cache.clock);

    cache.insert(1, 1);
    cache.insert(3, 3);
    cache.insert(5, 6);
    assert_eq!(9, cache.clock);
    assert_eq!(3, cache.len());
    assert_eq!(Some(&1), cache.get(1));
    assert_eq!(Some(&3), cache.get(3));
    assert_eq!(Some(&6), cache.get(5));
    assert_eq!(None, cache.get(7));

    cache.insert(7, 8);
    assert_eq!(3, cache.len());
    assert_eq!(None, cache.get(1));
    assert_eq!(Some(&3), cache.get(3));
    assert_eq!(Some(&6), cache.get(5));
    assert_eq!(Some(&8), cache.get(7));
    assert_eq!(16, cache.clock);
}
<|endoftext|>


<commit_before>// Copyright (C) 2014 The 6502-rs Developers
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
// 3. Neither the names of the copyright holders nor the names of any
//    contributors may be used to endorse or promote products derived from this
//    software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

use log;

use std;

use address::{AddressDiff};
use instruction;
use instruction::{DecodedInstr};
use memory::Memory;
use registers::{ Registers, Status, StatusArgs };
use registers::{ PS_NEGATIVE, PS_OVERFLOW, PS_ZERO, PS_CARRY };

pub struct Machine {
    pub registers: Registers,
    pub memory:    Memory
}

impl Machine {
    pub fn new() -> Machine {
    	Machine{
    	    registers: Registers::new(),
    	    memory:    Memory::new()
    	}
    }

    pub fn reset(&mut self) {
    	*self = Machine::new();
    }

    pub fn fetch_next_and_decode(&mut self) -> Option<DecodedInstr> {
        let x: u8 = self.memory.get_byte(self.registers.program_counter);

        match instruction::OPCODES[x as uint] {
            Some((instr, am)) => {
                let extra_bytes = am.extra_bytes();
                let num_bytes = AddressDiff(1) + extra_bytes;

                let data_start = self.registers.program_counter
                               + AddressDiff(1);

                let slice = self.memory.get_slice(data_start, extra_bytes);
                let am_out = am.process(self, slice);

                // Increment program counter
                self.registers.program_counter =
                    self.registers.program_counter + num_bytes;

                Some((instr, am_out))
            }
            _ => None
        }
    }

    pub fn execute_instruction(&mut self, decoded_instr: DecodedInstr) {
        match decoded_instr {
            (instruction::ADC, instruction::UseImmediate(val)) => {
                log!(log::DEBUG, "add with carry immediate: {}", val);
                self.add_with_carry(val as i8);
            },
            (instruction::ADC, instruction::UseAddress(addr)) => {
                let val = self.memory.get_byte(addr) as i8;
                log!(log::DEBUG, "add with carry. address: {}. value: {}",
                                 addr, val);
                self.add_with_carry(val);
            },

            (instruction::DEX, instruction::UseImplied) => {
                self.dec_x();
            }

            (instruction::LDA, instruction::UseImmediate(val)) => {
                log!(log::DEBUG, "load A immediate: {}", val);
                self.load_accumulator(val as i8);
            },
            (instruction::LDA, instruction::UseAddress(addr)) => {
                let val = self.memory.get_byte(addr);
                log!(log::DEBUG, "load A. address: {}. value: {}", addr, val);
                self.load_accumulator(val as i8);
            },

            (instruction::LDX, instruction::UseImmediate(val)) => {
                log!(log::DEBUG, "load X immediate: {}", val);
                self.load_x_register(val as i8);
            },
            (instruction::LDX, instruction::UseAddress(addr)) => {
                let val = self.memory.get_byte(addr);
                log!(log::DEBUG, "load X. address: {}. value: {}", addr, val);
                self.load_x_register(val as i8);
            },

            (instruction::LDY, instruction::UseImmediate(val)) => {
                log!(log::DEBUG, "load Y immediate: {}", val);
                self.load_y_register(val as i8);
            },
            (instruction::LDY, instruction::UseAddress(addr)) => {
                let val = self.memory.get_byte(addr);
                log!(log::DEBUG, "load Y. address: {}. value: {}", addr, val);
                self.load_y_register(val as i8);
            },

            (instruction::NOP, _) => {
                log!(log::DEBUG, "nop instr");
            },
            (_, _) => {
                log!(log::DEBUG, "attempting to execute unimplemented \
                                  instruction");
            },
        };
    }

    pub fn run(&mut self) {
        loop {
            if let Some(decoded_instr) = self.fetch_next_and_decode() {
                self.execute_instruction(decoded_instr);
            } else {
                break
            }
        }
    }

    fn load_register_with_flags(register: &mut i8,
                                status: &mut Status,
                                value: i8) {
        *register = value;

        let is_zero = value == 0;
        let is_negative = value < 0;

        status.set_with_mask(
            PS_ZERO | PS_NEGATIVE,
            Status::new(StatusArgs { zero: is_zero,
                                     negative: is_negative,
                                     ..StatusArgs::none() } ));
    }

    pub fn load_x_register(&mut self, value: i8) {
        Machine::load_register_with_flags(&mut self.registers.index_x,
                                          &mut self.registers.status,
                                          value);
    }

    pub fn load_y_register(&mut self, value: i8) {
        Machine::load_register_with_flags(&mut self.registers.index_y,
                                          &mut self.registers.status,
                                          value);
    }

    pub fn load_accumulator(&mut self, value: i8) {
        Machine::load_register_with_flags(&mut self.registers.accumulator,
                                          &mut self.registers.status,
                                          value);
    }

    // TODO akeeton: Implement binary-coded decimal.
    pub fn add_with_carry(&mut self, value: i8) {
        let a_before: i8 = self.registers.accumulator;
        let c_before: i8 = self.registers.status.get_carry();
        let a_after: i8 = a_before + c_before + value;

        debug_assert_eq!(a_after as u8, a_before as u8 + c_before as u8
                                        + value as u8);

        let did_carry = (a_after as u8) < (a_before as u8);

        let did_overflow   =
        	   (a_before < 0 && value < 0 && a_after >= 0)
        	|| (a_before > 0 && value > 0 && a_after <= 0);

        let mask = PS_CARRY | PS_OVERFLOW;

        self.registers.status.set_with_mask(mask,
            Status::new(StatusArgs { carry: did_carry,
                                     overflow: did_overflow,
                                     ..StatusArgs::none() } ));

        self.load_accumulator(a_after);

        log!(log::DEBUG, "accumulator: {}", self.registers.accumulator);
    }

    pub fn dec_x(&mut self) {
        let val = self.registers.index_x;
        self.load_x_register(val - 1);
    }
}

impl std::fmt::Show for Machine {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "Machine Dump:\n\nAccumulator: {}",
               self.registers.accumulator)
    }
}

#[test]
fn add_with_carry_test() {

    let mut machine = Machine::new();

    machine.add_with_carry(1);
    assert_eq!(machine.registers.accumulator, 1);
    assert_eq!(machine.registers.status.contains(PS_CARRY),    false);
    assert_eq!(machine.registers.status.contains(PS_ZERO),     false);
    assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false);
    assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);

    machine.add_with_carry(-1);
    assert_eq!(machine.registers.accumulator, 0);
    assert_eq!(machine.registers.status.contains(PS_CARRY),    true);
    assert_eq!(machine.registers.status.contains(PS_ZERO),     true);
    assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false);
    assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);

    machine.add_with_carry(1);
    assert_eq!(machine.registers.accumulator, 2);
    assert_eq!(machine.registers.status.contains(PS_CARRY),    false);
    assert_eq!(machine.registers.status.contains(PS_ZERO),     false);
    assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false);
    assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);

    let mut machine = Machine::new();

    machine.add_with_carry(127);
    assert_eq!(machine.registers.accumulator, 127);
    assert_eq!(machine.registers.status.contains(PS_CARRY),    false);
    assert_eq!(machine.registers.status.contains(PS_ZERO),     false);
    assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false);
    assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);

    machine.add_with_carry(-127);
    assert_eq!(machine.registers.accumulator, 0);
    assert_eq!(machine.registers.status.contains(PS_CARRY),     true);
    assert_eq!(machine.registers.status.contains(PS_ZERO),      true);
    assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false);
    assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);

    machine.registers.status.remove(PS_CARRY);
    machine.add_with_carry(-128);
    assert_eq!(machine.registers.accumulator, -128);
    assert_eq!(machine.registers.status.contains(PS_CARRY),    false);
    assert_eq!(machine.registers.status.contains(PS_ZERO),     false);
    assert_eq!(machine.registers.status.contains(PS_NEGATIVE),  true);
    assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);

    machine.add_with_carry(127);
    assert_eq!(machine.registers.accumulator, -1);
    assert_eq!(machine.registers.status.contains(PS_CARRY),    false);
    assert_eq!(machine.registers.status.contains(PS_ZERO),     false);
    assert_eq!(machine.registers.status.contains(PS_NEGATIVE),  true);
    assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);

    let mut machine = Machine::new();

    machine.add_with_carry(127);
    assert_eq!(machine.registers.accumulator, 127);
    assert_eq!(machine.registers.status.contains(PS_CARRY),    false);
    assert_eq!(machine.registers.status.contains(PS_ZERO),     false);
    assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false);
    assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);

    machine.add_with_carry(1);
    assert_eq!(machine.registers.accumulator, -128);
    assert_eq!(machine.registers.status.contains(PS_CARRY),    false);
    assert_eq!(machine.registers.status.contains(PS_ZERO),     false);
    assert_eq!(machine.registers.status.contains(PS_NEGATIVE),  true);
    assert_eq!(machine.registers.status.contains(PS_OVERFLOW),  true);
}

#[test]
fn dec_x_test() {
    let mut machine = Machine::new();

    machine.dec_x();
    assert_eq!(machine.registers.index_x, -1);
    assert_eq!(machine.registers.status.contains(PS_CARRY),    false);
    assert_eq!(machine.registers.status.contains(PS_ZERO),     false);
    assert_eq!(machine.registers.status.contains(PS_NEGATIVE), true);
    assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);

    machine.dec_x();
    assert_eq!(machine.registers.index_x, -2);
    assert_eq!(machine.registers.status.contains(PS_CARRY),    false);
    assert_eq!(machine.registers.status.contains(PS_ZERO),     false);
    assert_eq!(machine.registers.status.contains(PS_NEGATIVE), true);
    assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);

    machine.load_x_register(5);
    machine.dec_x();
    assert_eq!(machine.registers.index_x, 4);
    assert_eq!(machine.registers.status.contains(PS_CARRY),    false);
    assert_eq!(machine.registers.status.contains(PS_ZERO),     false);
    assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false);
    assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);

    machine.dec_x();
    machine.dec_x();
    machine.dec_x();
    machine.dec_x();

    assert_eq!(machine.registers.index_x, 0);
    assert_eq!(machine.registers.status.contains(PS_CARRY),    false);
    assert_eq!(machine.registers.status.contains(PS_ZERO),     true);
    assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false);
    assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);

    machine.dec_x();
    assert_eq!(machine.registers.index_x, -1);
    assert_eq!(machine.registers.status.contains(PS_CARRY),    false);
    assert_eq!(machine.registers.status.contains(PS_ZERO),     false);
    assert_eq!(machine.registers.status.contains(PS_NEGATIVE), true);
    assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);
}
<commit_msg>Implement JMP instruction.<commit_after>// Copyright (C) 2014 The 6502-rs Developers
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
// 3. Neither the names of the copyright holders nor the names of any
//    contributors may be used to endorse or promote products derived from this
//    software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

use log;

use std;

use address::{Address, AddressDiff};
use instruction;
use instruction::{DecodedInstr};
use memory::Memory;
use registers::{ Registers, Status, StatusArgs };
use registers::{ PS_NEGATIVE, PS_OVERFLOW, PS_ZERO, PS_CARRY };

pub struct Machine {
    pub registers: Registers,
    pub memory:    Memory
}

impl Machine {
    pub fn new() -> Machine {
    	Machine{
    	    registers: Registers::new(),
    	    memory:    Memory::new()
    	}
    }

    pub fn reset(&mut self) {
    	*self = Machine::new();
    }

    pub fn fetch_next_and_decode(&mut self) -> Option<DecodedInstr> {
        let x: u8 = self.memory.get_byte(self.registers.program_counter);

        match instruction::OPCODES[x as uint] {
            Some((instr, am)) => {
                let extra_bytes = am.extra_bytes();
                let num_bytes = AddressDiff(1) + extra_bytes;

                let data_start = self.registers.program_counter
                               + AddressDiff(1);

                let slice = self.memory.get_slice(data_start, extra_bytes);
                let am_out = am.process(self, slice);

                // Increment program counter
                self.registers.program_counter =
                    self.registers.program_counter + num_bytes;

                Some((instr, am_out))
            }
            _ => None
        }
    }

    pub fn execute_instruction(&mut self, decoded_instr: DecodedInstr) {
        match decoded_instr {
            (instruction::ADC, instruction::UseImmediate(val)) => {
                log!(log::DEBUG, "add with carry immediate: {}", val);
                self.add_with_carry(val as i8);
            },
            (instruction::ADC, instruction::UseAddress(addr)) => {
                let val = self.memory.get_byte(addr) as i8;
                log!(log::DEBUG, "add with carry. address: {}. value: {}",
                                 addr, val);
                self.add_with_carry(val);
            },

            (instruction::DEX, instruction::UseImplied) => {
                self.dec_x();
            },

            (instruction::JMP, instruction::UseAddress(addr)) => {
                self.jump(addr)
            },

            (instruction::LDA, instruction::UseImmediate(val)) => {
                log!(log::DEBUG, "load A immediate: {}", val);
                self.load_accumulator(val as i8);
            },
            (instruction::LDA, instruction::UseAddress(addr)) => {
                let val = self.memory.get_byte(addr);
                log!(log::DEBUG, "load A. address: {}. value: {}", addr, val);
                self.load_accumulator(val as i8);
            },

            (instruction::LDX, instruction::UseImmediate(val)) => {
                log!(log::DEBUG, "load X immediate: {}", val);
                self.load_x_register(val as i8);
            },
            (instruction::LDX, instruction::UseAddress(addr)) => {
                let val = self.memory.get_byte(addr);
                log!(log::DEBUG, "load X. address: {}. value: {}", addr, val);
                self.load_x_register(val as i8);
            },

            (instruction::LDY, instruction::UseImmediate(val)) => {
                log!(log::DEBUG, "load Y immediate: {}", val);
                self.load_y_register(val as i8);
            },
            (instruction::LDY, instruction::UseAddress(addr)) => {
                let val = self.memory.get_byte(addr);
                log!(log::DEBUG, "load Y. address: {}. value: {}", addr, val);
                self.load_y_register(val as i8);
            },

            (instruction::NOP, _) => {
                log!(log::DEBUG, "nop instr");
            },
            (_, _) => {
                log!(log::DEBUG, "attempting to execute unimplemented \
                                  instruction");
            },
        };
    }

    pub fn run(&mut self) {
        loop {
            if let Some(decoded_instr) = self.fetch_next_and_decode() {
                self.execute_instruction(decoded_instr);
            } else {
                break
            }
        }
    }

    fn load_register_with_flags(register: &mut i8,
                                status: &mut Status,
                                value: i8) {
        *register = value;

        let is_zero = value == 0;
        let is_negative = value < 0;

        status.set_with_mask(
            PS_ZERO | PS_NEGATIVE,
            Status::new(StatusArgs { zero: is_zero,
                                     negative: is_negative,
                                     ..StatusArgs::none() } ));
    }

    pub fn load_x_register(&mut self, value: i8) {
        Machine::load_register_with_flags(&mut self.registers.index_x,
                                          &mut self.registers.status,
                                          value);
    }

    pub fn load_y_register(&mut self, value: i8) {
        Machine::load_register_with_flags(&mut self.registers.index_y,
                                          &mut self.registers.status,
                                          value);
    }

    pub fn load_accumulator(&mut self, value: i8) {
        Machine::load_register_with_flags(&mut self.registers.accumulator,
                                          &mut self.registers.status,
                                          value);
    }

    // TODO akeeton: Implement binary-coded decimal.
    pub fn add_with_carry(&mut self, value: i8) {
        let a_before: i8 = self.registers.accumulator;
        let c_before: i8 = self.registers.status.get_carry();
        let a_after: i8 = a_before + c_before + value;

        debug_assert_eq!(a_after as u8, a_before as u8 + c_before as u8
                                        + value as u8);

        let did_carry = (a_after as u8) < (a_before as u8);

        let did_overflow   =
        	   (a_before < 0 && value < 0 && a_after >= 0)
        	|| (a_before > 0 && value > 0 && a_after <= 0);

        let mask = PS_CARRY | PS_OVERFLOW;

        self.registers.status.set_with_mask(mask,
            Status::new(StatusArgs { carry: did_carry,
                                     overflow: did_overflow,
                                     ..StatusArgs::none() } ));

        self.load_accumulator(a_after);

        log!(log::DEBUG, "accumulator: {}", self.registers.accumulator);
    }

    pub fn dec_x(&mut self) {
        let val = self.registers.index_x;
        self.load_x_register(val - 1);
    }

    pub fn jump(&mut self, addr: Address) {
        self.registers.program_counter = addr;
    }
}

impl std::fmt::Show for Machine {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "Machine Dump:\n\nAccumulator: {}",
               self.registers.accumulator)
    }
}

#[test]
fn add_with_carry_test() {

    let mut machine = Machine::new();

    machine.add_with_carry(1);
    assert_eq!(machine.registers.accumulator, 1);
    assert_eq!(machine.registers.status.contains(PS_CARRY),    false);
    assert_eq!(machine.registers.status.contains(PS_ZERO),     false);
    assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false);
    assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);

    machine.add_with_carry(-1);
    assert_eq!(machine.registers.accumulator, 0);
    assert_eq!(machine.registers.status.contains(PS_CARRY),    true);
    assert_eq!(machine.registers.status.contains(PS_ZERO),     true);
    assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false);
    assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);

    machine.add_with_carry(1);
    assert_eq!(machine.registers.accumulator, 2);
    assert_eq!(machine.registers.status.contains(PS_CARRY),    false);
    assert_eq!(machine.registers.status.contains(PS_ZERO),     false);
    assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false);
    assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);

    let mut machine = Machine::new();

    machine.add_with_carry(127);
    assert_eq!(machine.registers.accumulator, 127);
    assert_eq!(machine.registers.status.contains(PS_CARRY),    false);
    assert_eq!(machine.registers.status.contains(PS_ZERO),     false);
    assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false);
    assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);

    machine.add_with_carry(-127);
    assert_eq!(machine.registers.accumulator, 0);
    assert_eq!(machine.registers.status.contains(PS_CARRY),     true);
    assert_eq!(machine.registers.status.contains(PS_ZERO),      true);
    assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false);
    assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);

    machine.registers.status.remove(PS_CARRY);
    machine.add_with_carry(-128);
    assert_eq!(machine.registers.accumulator, -128);
    assert_eq!(machine.registers.status.contains(PS_CARRY),    false);
    assert_eq!(machine.registers.status.contains(PS_ZERO),     false);
    assert_eq!(machine.registers.status.contains(PS_NEGATIVE),  true);
    assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);

    machine.add_with_carry(127);
    assert_eq!(machine.registers.accumulator, -1);
    assert_eq!(machine.registers.status.contains(PS_CARRY),    false);
    assert_eq!(machine.registers.status.contains(PS_ZERO),     false);
    assert_eq!(machine.registers.status.contains(PS_NEGATIVE),  true);
    assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);

    let mut machine = Machine::new();

    machine.add_with_carry(127);
    assert_eq!(machine.registers.accumulator, 127);
    assert_eq!(machine.registers.status.contains(PS_CARRY),    false);
    assert_eq!(machine.registers.status.contains(PS_ZERO),     false);
    assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false);
    assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);

    machine.add_with_carry(1);
    assert_eq!(machine.registers.accumulator, -128);
    assert_eq!(machine.registers.status.contains(PS_CARRY),    false);
    assert_eq!(machine.registers.status.contains(PS_ZERO),     false);
    assert_eq!(machine.registers.status.contains(PS_NEGATIVE),  true);
    assert_eq!(machine.registers.status.contains(PS_OVERFLOW),  true);
}

#[test]
fn dec_x_test() {
    let mut machine = Machine::new();

    machine.dec_x();
    assert_eq!(machine.registers.index_x, -1);
    assert_eq!(machine.registers.status.contains(PS_CARRY),    false);
    assert_eq!(machine.registers.status.contains(PS_ZERO),     false);
    assert_eq!(machine.registers.status.contains(PS_NEGATIVE), true);
    assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);

    machine.dec_x();
    assert_eq!(machine.registers.index_x, -2);
    assert_eq!(machine.registers.status.contains(PS_CARRY),    false);
    assert_eq!(machine.registers.status.contains(PS_ZERO),     false);
    assert_eq!(machine.registers.status.contains(PS_NEGATIVE), true);
    assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);

    machine.load_x_register(5);
    machine.dec_x();
    assert_eq!(machine.registers.index_x, 4);
    assert_eq!(machine.registers.status.contains(PS_CARRY),    false);
    assert_eq!(machine.registers.status.contains(PS_ZERO),     false);
    assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false);
    assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);

    machine.dec_x();
    machine.dec_x();
    machine.dec_x();
    machine.dec_x();

    assert_eq!(machine.registers.index_x, 0);
    assert_eq!(machine.registers.status.contains(PS_CARRY),    false);
    assert_eq!(machine.registers.status.contains(PS_ZERO),     true);
    assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false);
    assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);

    machine.dec_x();
    assert_eq!(machine.registers.index_x, -1);
    assert_eq!(machine.registers.status.contains(PS_CARRY),    false);
    assert_eq!(machine.registers.status.contains(PS_ZERO),     false);
    assert_eq!(machine.registers.status.contains(PS_NEGATIVE), true);
    assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);
}

#[test]
fn jump_test() {
    let mut machine = Machine::new();
    let     addr    = Address(0xA1B1);

    machine.jump(addr);
    assert_eq!(machine.registers.program_counter, addr);
}
<|endoftext|>


<commit_before>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

//!
//! These functions deal with establishing how much of a particular stream (or string) matches a particular pattern. The
//! most important function is `matches`, which takes a stream and a pattern and returns the number of characters from the
//! stream that matches the pattern. Use it like this:
//!
//! ```
//! # use concordance::*;
//! # assert!(matches("abcabc", "abc".repeat_forever(1)) == Some(6));
//! # assert!(matches("abcabcabc", "abc".repeat_forever(1)).is_some());
//! # assert!(matches("abc", "abc").is_some());
//! # assert!(matches("def", "abc".repeat_forever(1)).is_none());
//! if matches("abcabc", "abc".repeat_forever(1)).is_some() { /* ... */ }
//! ```
//!
//! To determine if a string exactly matches a pattern, compare to the string length like this:
//!
//! ```
//! # use concordance::*;
//! let input_string = "abcabc";
//! let pattern      = "abc".repeat_forever(1);
//!
//! if matches(input_string, pattern) == Some(input_string.len()) { }
//! # assert!(matches(input_string, "abc".repeat_forever(1)) == Some(input_string.len()));
//! ```
//!

use super::symbol_range_dfa::*;
use super::symbol_reader::*;
use super::pattern_matcher::*;
use super::prepare::*;

///
/// Runs a DFA against a symbol stream and returns its final state
///
/// This takes a DFA match action as an initial state (such as that returned by `SymbolRangeDfa::start()`) and runs it until it accepts
/// or rejects the pattern passed to it.
///
/// This call is useful for cases where there is more than one output symbol (as the output symbol that was matched can be retrieved)
/// or for working with pattern matchers other than the default one.
///
/// ```
/// # use concordance::*;
/// let input_string = "abcabc";
/// let pattern      = "abc".repeat_forever(1);
/// let matcher      = pattern.prepare_to_match();
///
/// let match_result = match_pattern(matcher.start(), &mut input_string.read_symbols()); // == Accept(6, &true)
/// # assert!(match match_result { Accept(count, val) => count == 6 && val == &true, _ => false });
/// ```
///
pub fn match_pattern<'a, InputSymbol: Ord, OutputSymbol, State>(start_state: MatchAction<'a, OutputSymbol, State>, symbol_reader: &mut SymbolReader<InputSymbol>) -> MatchAction<'a, OutputSymbol, State>
where State: MatchingState<'a, InputSymbol, OutputSymbol> {
    let mut current_state = start_state;

    while let More(this_state) = current_state {
        let next_state =
            if let Some(next_char) = symbol_reader.next_symbol() {
                this_state.next(next_char)
            } else {
                this_state.finish()
            };

        current_state = next_state;
    }

    current_state
}

///
/// Runs a pattern matcher against a stream, and returns the number of characters matching if it accepted the stream
///
fn matches_symbol_range<InputSymbol: Ord, OutputSymbol: 'static>(dfa: &SymbolRangeDfa<InputSymbol, OutputSymbol>, symbol_reader: &mut SymbolReader<InputSymbol>) -> Option<usize> {
    // Run the DFA
    let final_state = match_pattern(dfa.start(), symbol_reader);

    if let Accept(count, _) = final_state {
        Some(count)
    } else {
        None
    }
}

///
/// Matches a source stream against a pattern
///
/// This is the basic pattern matcher. It matches against the left-hand side of the source, and if there is a string of any
/// length that can match the passed in pattern it will return the length of that string. Pattern matchers should be greedy,
/// so this will return the length of the longest string that can match the given pattern.
///
/// ```
/// # use concordance::*;
/// matches("abc", "abc");                      // Returns Some(3)
/// matches("abcabc", "abc");                   // Also returns Some(3) as 'abc' matches the pattern
/// matches("abcabc", "abc".repeat_forever(0)); // Returns Some(6)
/// matches("ab", "abc");                       // Doesn't match: returns None
/// ```
///
/// It's worth noting that this is not just limited to strings and characters. For example, vectors will work too:
///
/// ```
/// # use concordance::*;
/// matches(&vec![1,2,3,1,2,3], vec![1,2,3].repeat_forever(1)); // == Some(6)
/// # assert!(matches(&vec![1,2,3,1,2,3], vec![1,2,3].repeat_forever(1)) == Some(6));
/// ```
///
pub fn matches<'a, Symbol, OutputSymbol, Prepare, Reader, Source>(source: Source, pattern: Prepare) -> Option<usize>
where   Prepare: PrepareToMatch<SymbolRangeDfa<Symbol, OutputSymbol>>
,       Reader: SymbolReader<Symbol>+'a
,       Source: SymbolSource<'a, Symbol, SymbolReader=Reader>
,       Symbol: Ord
,       OutputSymbol: 'static {
    let matcher    = pattern.prepare_to_match();
    let mut reader = source.read_symbols();

    matches_symbol_range(&matcher, &mut reader)
}

///
/// Matches a source stream against a prepared pattern
///
/// If it's necessary to match a pattern against a lot of different things, then preparing it by calling `pattern.prepare_to_match()`
/// will increase the performance of the matcher for every match after the first one. This call is otherwise identical to `matches`.
///
/// ```
/// # use concordance::*;
/// let prepared = "abc".repeat_forever(1).prepare_to_match();
///
/// matches_prepared("abcabc", &prepared);      // == Some(6)
/// matches_prepared("abc", &prepared);         // == Some(3)
/// matches_prepared("abcabcabc", &prepared);   // == Some(9)
/// ```
///
pub fn matches_prepared<'a, Symbol, OutputSymbol, Reader, Source>(source: Source, matcher: &SymbolRangeDfa<Symbol, OutputSymbol>) -> Option<usize>
where   Reader: SymbolReader<Symbol>+'a
,       Source: SymbolSource<'a, Symbol, SymbolReader=Reader>
,       Symbol: Ord
,       OutputSymbol: 'static {
    let mut reader = source.read_symbols();

    matches_symbol_range(&matcher, &mut reader)
}

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

    #[test]
    fn match_multiple_repeats() {
        assert!(matches("abcabc", "abc".repeat_forever(1)).is_some());
    }

    #[test]
    fn match_prepared() {
        let prepared = "abc".repeat_forever(1).prepare_to_match();

        assert!(matches_prepared("abcabc", &prepared) == Some(6));
        assert!(matches_prepared("abc", &prepared) == Some(3));
        assert!(matches_prepared("abcabcabc", &prepared) == Some(9));
    }

    #[test]
    fn match_single_repeat() {
        assert!(matches("abc", "abc".repeat_forever(1)).is_some());
    }

    #[test]
    fn match_with_zero_or_more() {
        assert!(matches("abc", "abc".repeat_forever(0)).is_some());
        assert!(matches("abcabc", "abc".repeat_forever(0)).is_some());
        assert!(matches("abcabcabc", "abc".repeat_forever(0)).is_some());
    }

    #[test]
    fn match_with_zero_or_more_following() {
        assert!(matches("abc", "abc".repeat_forever(0).append("def")).is_none());
        assert!(matches("abcabc", "abc".repeat_forever(0).append("def")).is_none());

        assert!(matches("abcdef", "abc".repeat_forever(0).append("def")).is_some());
        assert!(matches("abcabcdef", "abc".repeat_forever(0).append("def")).is_some());
    }

    #[test]
    fn match_limited_range() {
        assert!(matches("abc", "abc".repeat(2..4)).is_none());
        assert!(matches("abcabc", "abc".repeat(2..4)).is_some());
        assert!(matches("abcabcabc", "abc".repeat(2..4)) == Some(3*3));
        assert!(matches("abcabcabcabc", "abc".repeat(2..4)) == Some(3*3));
    }

    #[test]
    fn match_zero_repeats() {
        assert!(matches("", "abc".repeat_forever(0)).is_some());
    }
}
<commit_msg>Test for exact lengths here<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

//!
//! These functions deal with establishing how much of a particular stream (or string) matches a particular pattern. The
//! most important function is `matches`, which takes a stream and a pattern and returns the number of characters from the
//! stream that matches the pattern. Use it like this:
//!
//! ```
//! # use concordance::*;
//! # assert!(matches("abcabc", "abc".repeat_forever(1)) == Some(6));
//! # assert!(matches("abcabcabc", "abc".repeat_forever(1)).is_some());
//! # assert!(matches("abc", "abc").is_some());
//! # assert!(matches("def", "abc".repeat_forever(1)).is_none());
//! if matches("abcabc", "abc".repeat_forever(1)).is_some() { /* ... */ }
//! ```
//!
//! To determine if a string exactly matches a pattern, compare to the string length like this:
//!
//! ```
//! # use concordance::*;
//! let input_string = "abcabc";
//! let pattern      = "abc".repeat_forever(1);
//!
//! if matches(input_string, pattern) == Some(input_string.len()) { }
//! # assert!(matches(input_string, "abc".repeat_forever(1)) == Some(input_string.len()));
//! ```
//!

use super::symbol_range_dfa::*;
use super::symbol_reader::*;
use super::pattern_matcher::*;
use super::prepare::*;

///
/// Runs a DFA against a symbol stream and returns its final state
///
/// This takes a DFA match action as an initial state (such as that returned by `SymbolRangeDfa::start()`) and runs it until it accepts
/// or rejects the pattern passed to it.
///
/// This call is useful for cases where there is more than one output symbol (as the output symbol that was matched can be retrieved)
/// or for working with pattern matchers other than the default one.
///
/// ```
/// # use concordance::*;
/// let input_string = "abcabc";
/// let pattern      = "abc".repeat_forever(1);
/// let matcher      = pattern.prepare_to_match();
///
/// let match_result = match_pattern(matcher.start(), &mut input_string.read_symbols()); // == Accept(6, &true)
/// # assert!(match match_result { Accept(count, val) => count == 6 && val == &true, _ => false });
/// ```
///
pub fn match_pattern<'a, InputSymbol: Ord, OutputSymbol, State>(start_state: MatchAction<'a, OutputSymbol, State>, symbol_reader: &mut SymbolReader<InputSymbol>) -> MatchAction<'a, OutputSymbol, State>
where State: MatchingState<'a, InputSymbol, OutputSymbol> {
    let mut current_state = start_state;

    while let More(this_state) = current_state {
        let next_state =
            if let Some(next_char) = symbol_reader.next_symbol() {
                this_state.next(next_char)
            } else {
                this_state.finish()
            };

        current_state = next_state;
    }

    current_state
}

///
/// Runs a pattern matcher against a stream, and returns the number of characters matching if it accepted the stream
///
fn matches_symbol_range<InputSymbol: Ord, OutputSymbol: 'static>(dfa: &SymbolRangeDfa<InputSymbol, OutputSymbol>, symbol_reader: &mut SymbolReader<InputSymbol>) -> Option<usize> {
    // Run the DFA
    let final_state = match_pattern(dfa.start(), symbol_reader);

    if let Accept(count, _) = final_state {
        Some(count)
    } else {
        None
    }
}

///
/// Matches a source stream against a pattern
///
/// This is the basic pattern matcher. It matches against the left-hand side of the source, and if there is a string of any
/// length that can match the passed in pattern it will return the length of that string. Pattern matchers should be greedy,
/// so this will return the length of the longest string that can match the given pattern.
///
/// ```
/// # use concordance::*;
/// matches("abc", "abc");                      // Returns Some(3)
/// matches("abcabc", "abc");                   // Also returns Some(3) as 'abc' matches the pattern
/// matches("abcabc", "abc".repeat_forever(0)); // Returns Some(6)
/// matches("ab", "abc");                       // Doesn't match: returns None
/// ```
///
/// It's worth noting that this is not just limited to strings and characters. For example, vectors will work too:
///
/// ```
/// # use concordance::*;
/// matches(&vec![1,2,3,1,2,3], vec![1,2,3].repeat_forever(1)); // == Some(6)
/// # assert!(matches(&vec![1,2,3,1,2,3], vec![1,2,3].repeat_forever(1)) == Some(6));
/// ```
///
pub fn matches<'a, Symbol, OutputSymbol, Prepare, Reader, Source>(source: Source, pattern: Prepare) -> Option<usize>
where   Prepare: PrepareToMatch<SymbolRangeDfa<Symbol, OutputSymbol>>
,       Reader: SymbolReader<Symbol>+'a
,       Source: SymbolSource<'a, Symbol, SymbolReader=Reader>
,       Symbol: Ord
,       OutputSymbol: 'static {
    let matcher    = pattern.prepare_to_match();
    let mut reader = source.read_symbols();

    matches_symbol_range(&matcher, &mut reader)
}

///
/// Matches a source stream against a prepared pattern
///
/// If it's necessary to match a pattern against a lot of different things, then preparing it by calling `pattern.prepare_to_match()`
/// will increase the performance of the matcher for every match after the first one. This call is otherwise identical to `matches`.
///
/// ```
/// # use concordance::*;
/// let prepared = "abc".repeat_forever(1).prepare_to_match();
///
/// matches_prepared("abcabc", &prepared);      // == Some(6)
/// matches_prepared("abc", &prepared);         // == Some(3)
/// matches_prepared("abcabcabc", &prepared);   // == Some(9)
/// ```
///
pub fn matches_prepared<'a, Symbol, OutputSymbol, Reader, Source>(source: Source, matcher: &SymbolRangeDfa<Symbol, OutputSymbol>) -> Option<usize>
where   Reader: SymbolReader<Symbol>+'a
,       Source: SymbolSource<'a, Symbol, SymbolReader=Reader>
,       Symbol: Ord
,       OutputSymbol: 'static {
    let mut reader = source.read_symbols();

    matches_symbol_range(&matcher, &mut reader)
}

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

    #[test]
    fn match_multiple_repeats() {
        assert!(matches("abcabc", "abc".repeat_forever(1)).is_some());
    }

    #[test]
    fn match_prepared() {
        let prepared = "abc".repeat_forever(1).prepare_to_match();

        assert!(matches_prepared("abcabc", &prepared) == Some(6));
        assert!(matches_prepared("abc", &prepared) == Some(3));
        assert!(matches_prepared("abcabcabc", &prepared) == Some(9));
    }

    #[test]
    fn match_single_repeat() {
        assert!(matches("abc", "abc".repeat_forever(1)).is_some());
    }

    #[test]
    fn match_with_zero_or_more() {
        assert!(matches("abc", "abc".repeat_forever(0)) == Some(3));
        assert!(matches("abcabc", "abc".repeat_forever(0)) == Some(6));
        assert!(matches("abcabcabc", "abc".repeat_forever(0)) == Some(9));
    }

    #[test]
    fn match_with_zero_or_more_following() {
        assert!(matches("abc", "abc".repeat_forever(0).append("def")).is_none());
        assert!(matches("abcabc", "abc".repeat_forever(0).append("def")).is_none());

        assert!(matches("abcdef", "abc".repeat_forever(0).append("def")).is_some());
        assert!(matches("abcabcdef", "abc".repeat_forever(0).append("def")).is_some());
    }

    #[test]
    fn match_limited_range() {
        assert!(matches("abc", "abc".repeat(2..4)).is_none());
        assert!(matches("abcabc", "abc".repeat(2..4)).is_some());
        assert!(matches("abcabcabc", "abc".repeat(2..4)) == Some(3*3));
        assert!(matches("abcabcabcabc", "abc".repeat(2..4)) == Some(3*3));
    }

    #[test]
    fn match_zero_repeats() {
        assert!(matches("", "abc".repeat_forever(0)).is_some());
    }
}
<|endoftext|>