<commit_before>use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::error::Error;
use std::fmt;

use iron::{Request, Response, Handler, IronResult, IronError};
use iron::{status, method, headers};
use iron::typemap::Key;

use recognizer::Router as Recognizer;
use recognizer::{Match, Params};

static METHODS: &'static [method::Method] =
    &[method::Get, method::Post, method::Post,
      method::Put, method::Delete, method::Head,
      method::Patch];

/// `Router` provides an interface for creating complex routes as middleware
/// for the Iron framework.
pub struct Router {
    // The routers, specialized by method.
    routers: HashMap<method::Method, Recognizer<Box<Handler>>>
}

#[derive(Debug)]
/// The error thrown by router if there is no matching route.
pub struct NoRoute;

impl fmt::Display for NoRoute {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("No matching route found.")
    }
}

impl Error for NoRoute {
    fn description(&self) -> &str { "No Route" }
}

impl Router {
    /// `new` constructs a new, blank `Router`.
    pub fn new() -> Router { Router { routers: HashMap::new() } }
    /// Add a new route to a `Router`, matching both a method and glob pattern.
    ///
    /// `route` supports glob patterns: `*` for a single wildcard segment and
    /// `:param` for matching storing that segment of the request url in the `Params`
    /// object, which is stored in the request `extensions`.
    ///
    /// For instance, to route `Get` requests on any route matching
    /// `/users/:userid/:friend` and store `userid` and `friend` in
    /// the exposed Params object:
    ///
    /// ```ignore
    /// # use iron::method;
    /// router.route(method::Get, "/users/:userid/:friendid", controller);
    /// ```
    ///
    /// The controller provided to route can be any `Handler`, which allows
    /// extreme flexibility when handling routes. For instance, you could provide
    /// a `Chain`, a `Handler`, which contains an authorization middleware and
    /// a controller function, so that you can confirm that the request is
    /// authorized for this route before handling it.
    pub fn route<H, S>(&mut self, method: method::Method,
                       glob: S, handler: H) -> &mut Router
    where H: Handler, S: Str {
        match self.routers.entry(method) {
            Vacant(entry)   => entry.insert(Recognizer::new()),
            Occupied(entry) => entry.into_mut()
        }.add(glob.as_slice(), Box::new(handler) as Box<Handler>);
        self
    }

    /// Like route, but specialized to the `Get` method.
    pub fn get<H: Handler, S: Str>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Get, glob, handler)
    }

    /// Like route, but specialized to the `Post` method.
    pub fn post<H: Handler, S: Str>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Post, glob, handler)
    }

    /// Like route, but specialized to the `Put` method.
    pub fn put<H: Handler, S: Str>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Put, glob, handler)
    }

    /// Like route, but specialized to the `Delete` method.
    pub fn delete<H: Handler, S: Str>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Delete, glob, handler)
    }

    /// Like route, but specialized to the `Head` method.
    pub fn head<H: Handler, S: Str>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Head, glob, handler)
    }

    /// Like route, but specialized to the `Patch` method.
    pub fn patch<H: Handler, S: Str>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Patch, glob, handler)
    }

    /// Like route, but specialized to the `Options` method.
    pub fn options<H: Handler, S: Str>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Options, glob, handler)
    }

    fn recognize<'a>(&'a self, method: &method::Method, path: &str)
                     -> Option<Match<&'a Box<Handler>>> {
        self.routers.get(method).and_then(|router| router.recognize(path).ok())
    }

    fn handle_options(&self, req: &mut Request, path: &str) -> IronResult<Response> {
        // If there is an override, use it.
        if let Some(matched) = self.recognize(&method::Options, path) {
            req.extensions.insert::<Router>(matched.params);
            return matched.handler.handle(req);
        }

        // Else, get all the available methods and return them.
        let mut options = vec![];

        for method in METHODS.iter() {
            self.routers.get(method).map(|router| {
                if let Some(_) = router.recognize(path).ok() {
                    options.push(method.clone());
                }
            });
        }

        let mut res = Response::with(status::Ok);
        res.headers.set(headers::Allow(options));
        Ok(res)
    }
}

impl Key for Router { type Value = Params; }

impl Handler for Router {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        let path = req.url.path.connect("/");

        if let method::Options = req.method {
            return self.handle_options(req, &path[]);
        }

        let matched = match self.recognize(&req.method, &path[]) {
            Some(matched) => matched,
            // No match.
            None => return Err(IronError {
                error: Box::new(NoRoute),
                response: Response::with(status::NotFound)
            })
        };

        req.extensions.insert::<Router>(matched.params);
        matched.handler.handle(req)
    }
}

<commit_msg>(fix) Allow urls with trailing slashes.<commit_after>use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::error::Error;
use std::fmt;

use iron::{Request, Response, Handler, IronResult, IronError};
use iron::{status, method, headers};
use iron::typemap::Key;

use recognizer::Router as Recognizer;
use recognizer::{Match, Params};

static METHODS: &'static [method::Method] =
    &[method::Get, method::Post, method::Post,
      method::Put, method::Delete, method::Head,
      method::Patch];

/// `Router` provides an interface for creating complex routes as middleware
/// for the Iron framework.
pub struct Router {
    // The routers, specialized by method.
    routers: HashMap<method::Method, Recognizer<Box<Handler>>>
}

#[derive(Debug)]
/// The error thrown by router if there is no matching route.
pub struct NoRoute;

impl fmt::Display for NoRoute {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("No matching route found.")
    }
}

impl Error for NoRoute {
    fn description(&self) -> &str { "No Route" }
}

impl Router {
    /// `new` constructs a new, blank `Router`.
    pub fn new() -> Router { Router { routers: HashMap::new() } }
    /// Add a new route to a `Router`, matching both a method and glob pattern.
    ///
    /// `route` supports glob patterns: `*` for a single wildcard segment and
    /// `:param` for matching storing that segment of the request url in the `Params`
    /// object, which is stored in the request `extensions`.
    ///
    /// For instance, to route `Get` requests on any route matching
    /// `/users/:userid/:friend` and store `userid` and `friend` in
    /// the exposed Params object:
    ///
    /// ```ignore
    /// # use iron::method;
    /// router.route(method::Get, "/users/:userid/:friendid", controller);
    /// ```
    ///
    /// The controller provided to route can be any `Handler`, which allows
    /// extreme flexibility when handling routes. For instance, you could provide
    /// a `Chain`, a `Handler`, which contains an authorization middleware and
    /// a controller function, so that you can confirm that the request is
    /// authorized for this route before handling it.
    pub fn route<H, S>(&mut self, method: method::Method,
                       glob: S, handler: H) -> &mut Router
    where H: Handler, S: Str {
        match self.routers.entry(method) {
            Vacant(entry)   => entry.insert(Recognizer::new()),
            Occupied(entry) => entry.into_mut()
        }.add(glob.as_slice().trim_right_matches('/'),
              Box::new(handler) as Box<Handler>);
        self
    }

    /// Like route, but specialized to the `Get` method.
    pub fn get<H: Handler, S: Str>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Get, glob, handler)
    }

    /// Like route, but specialized to the `Post` method.
    pub fn post<H: Handler, S: Str>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Post, glob, handler)
    }

    /// Like route, but specialized to the `Put` method.
    pub fn put<H: Handler, S: Str>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Put, glob, handler)
    }

    /// Like route, but specialized to the `Delete` method.
    pub fn delete<H: Handler, S: Str>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Delete, glob, handler)
    }

    /// Like route, but specialized to the `Head` method.
    pub fn head<H: Handler, S: Str>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Head, glob, handler)
    }

    /// Like route, but specialized to the `Patch` method.
    pub fn patch<H: Handler, S: Str>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Patch, glob, handler)
    }

    /// Like route, but specialized to the `Options` method.
    pub fn options<H: Handler, S: Str>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Options, glob, handler)
    }

    fn recognize<'a>(&'a self, method: &method::Method, path: &str)
                     -> Option<Match<&'a Box<Handler>>> {
        self.routers.get(method).and_then(|router| router.recognize(path).ok())
    }

    fn handle_options(&self, req: &mut Request, path: &str) -> IronResult<Response> {
        // If there is an override, use it.
        if let Some(matched) = self.recognize(&method::Options, path) {
            req.extensions.insert::<Router>(matched.params);
            return matched.handler.handle(req);
        }

        // Else, get all the available methods and return them.
        let mut options = vec![];

        for method in METHODS.iter() {
            self.routers.get(method).map(|router| {
                if let Some(_) = router.recognize(path).ok() {
                    options.push(method.clone());
                }
            });
        }

        let mut res = Response::with(status::Ok);
        res.headers.set(headers::Allow(options));
        Ok(res)
    }
}

impl Key for Router { type Value = Params; }

impl Handler for Router {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        let path_string = req.url.path.connect("/");
        let path = path_string.trim_right_matches('/');

        if let method::Options = req.method {
            return self.handle_options(req, path);
        }

        let matched = match self.recognize(&req.method, path) {
            Some(matched) => matched,
            // No match.
            None => return Err(IronError {
                error: Box::new(NoRoute),
                response: Response::with(status::NotFound)
            })
        };

        req.extensions.insert::<Router>(matched.params);
        matched.handler.handle(req)
    }
}

<|endoftext|>


<commit_before>extern crate rustbox;

use std::iter;
use std::error::Error;
use self::rustbox::{Color, RustBox, Key};

pub struct Screen {
    rustbox: RustBox
}

impl Screen {

    pub fn new() -> Screen {
        let rustbox = match RustBox::init(Default::default()) {
            Result::Ok(v) => v,
            Result::Err(e) => panic!("{}", e),
        };

        Screen { rustbox: rustbox }
    }

    pub fn draw_help(&self) {

        self.rustbox.clear();

        let width = self.rustbox.width();
        let dummy_str = iter::repeat(" ").take(width).collect::<String>();

        self.rustbox.clear();
        self.rustbox.print(0, 0, rustbox::RB_BOLD, Color::White, Color::Black, &dummy_str);
        self.rustbox.print(0, 0, rustbox::RB_BOLD, Color::White, Color::Black, "> Hello!");
        self.rustbox.print(0, 1, rustbox::RB_BOLD, Color::White, Color::Default, "> Press 'q' to quit.");
        self.rustbox.print(0, 2, rustbox::RB_BOLD, Color::White, Color::Default, "> Press 'l' to show kinesis streams.");
        self.rustbox.present();
    }

    pub fn draw_strem_names(&self, stream_names: &Vec<String>) {

        self.rustbox.clear();

        self.rustbox.print(0, 0, rustbox::RB_BOLD, Color::Green, Color::Black, "Kinesis Stream List");

        for (num, stream_name) in stream_names.iter().enumerate() {
            self.rustbox.print(0, num + 1, rustbox::RB_BOLD, Color::White, Color::Black, &format!("[{0}]: {1}", num, &stream_name));
        }

        self.rustbox.present();
    }

    pub fn draw_shards(&self, shards: &Vec<String>) {

        self.rustbox.clear();

        self.rustbox.print(0, 0, rustbox::RB_BOLD, Color::Green, Color::Black, "Kinesis Shard List");

        for (num, shards) in shards.iter().enumerate() {
            self.rustbox.print(0, num + 1, rustbox::RB_BOLD, Color::White, Color::Black, &format!("[{0}]: {1}", num, &shards));
        }

        self.rustbox.present();
    }

    pub fn draw_records(&self, records: &Vec<String>) {

        self.rustbox.clear();

        self.rustbox.print(0, 0, rustbox::RB_BOLD, Color::Green, Color::Black, "Kinesis Record List");

        for (num, record) in records.iter().enumerate() {
            self.rustbox.print(0, num + 1, rustbox::RB_BOLD, Color::White, Color::Black, &format!("[{0}]: {1}", num, &record));
        }

        self.rustbox.present();
    }

    pub fn poll_event(&self) -> Key {
        match self.rustbox.poll_event(false) {
            Ok(rustbox::Event::KeyEvent(key)) => key,
            Err(e) => panic!("{}", e.description()),
            _ => panic!("error")
        }
    }
}

<commit_msg>💄 Cosme<commit_after>extern crate rustbox;

use std::error::Error;
use self::rustbox::{Color, RustBox, Key};

trait PrintLine {
    fn print_line(&self, y: usize, item: &str, fg: Color, bg: Color);
}

impl PrintLine for RustBox {

    fn print_line(&self, y: usize, item: &str, fg: Color, bg: Color) {
        for x in 0..(self.width()) {
            let ch = item.chars().nth(x).unwrap_or(' ');
            self.print_char(x, y, rustbox::RB_NORMAL, fg, bg, ch);
        }
    }
}

pub struct Screen {
    rustbox: RustBox
}

impl Screen {

    pub fn new() -> Screen {
        let rustbox = match RustBox::init(Default::default()) {
            Result::Ok(v) => v,
            Result::Err(e) => panic!("{}", e),
        };

        Screen { rustbox: rustbox }
    }

    pub fn draw_help(&self) {
        self.rustbox.clear();
        self.rustbox.print_line(0, "☰ Hello! this is kinesis helper tool.", Color::Black, Color::Green);
        self.rustbox.print_line(1, "☰ Press 'l' to show kinesis streams.", Color::Blue, Color::Black);
        self.rustbox.print_line(2, "☰ Press 'q' to quit.", Color::Blue, Color::Black);
        self.rustbox.present();
    }

    pub fn draw_strem_names(&self, stream_names: &Vec<String>) {

        self.rustbox.clear();

        self.rustbox.print_line(0, "☰ Kinesis > Streams", Color::Black, Color::Green);

        for (num, stream_name) in stream_names.iter().enumerate() {
            self.rustbox.print_line(num + 1, &format!("☰ [{0}]: {1}", num, &stream_name), Color::Blue, Color::Black);
        }

        self.rustbox.present();
    }

    pub fn draw_shards(&self, shards: &Vec<String>) {

        self.rustbox.clear();

        self.rustbox.print_line(0, "☰ Kinesis > Streams > Shards", Color::Black, Color::Green);

        for (num, shards) in shards.iter().enumerate() {
            self.rustbox.print_line(num + 1, &format!("☰ [{0}]: {1}", num, &shards), Color::Blue, Color::Black);
        }

        self.rustbox.present();
    }

    pub fn draw_records(&self, records: &Vec<String>) {

        self.rustbox.clear();

        self.rustbox.print_line(0, "☰ Kinesis > Streams > Shards > Records", Color::Black, Color::Green);

        for (num, record) in records.iter().enumerate() {
            self.rustbox.print_line(num + 1, &format!("☰ [{0}]: {1}", num, &record), Color::Blue, Color::Black);
        }

        self.rustbox.present();
    }

    pub fn poll_event(&self) -> Key {
        match self.rustbox.poll_event(false) {
            Ok(rustbox::Event::KeyEvent(key)) => key,
            Err(e) => panic!("{}", e.description()),
            _ => panic!("error")
        }
    }
}

<|endoftext|>


<commit_before>/*
 * Copyright 2020 Google LLC All Rights Reserved.
 *
 * 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.
 */

use std::io::Error;
use std::net::{Ipv4Addr, SocketAddrV4, UdpSocket};
use std::sync::Arc;

use slog::{info, o, Logger};

use crate::config::{Config, ConnectionConfig};

/// Server is the UDP server main implementation
pub struct Server {
    log: Logger,
}

impl Server {
    pub fn new(base: Logger) -> Self {
        let log = base.new(o!("source" => "server::Server"));
        return Server { log };
    }

    /// start the async processing of UDP packets
    pub async fn run(self, config: Arc<Config>) -> Result<(), Error> {
        let Server { log } = self;
        info!(log, "Starting on port {}", config.local.port);

        match &config.connections {
            ConnectionConfig::Sender { address, .. } => {
                info!(log, "Sender configuration"; "address" => address)
            }
            ConnectionConfig::Receiver { endpoints } => {
                info!(log, "Receiver configuration"; "endpoints" => endpoints.len())
            }
        };

        return Ok(());
    }

    async fn bind(self, config: &Config) -> Result<UdpSocket, Error> {
        let addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), config.local.port);
        return UdpSocket::bind(addr);
    }
}
<commit_msg>Binding for the local port.<commit_after>/*
 * Copyright 2020 Google LLC All Rights Reserved.
 *
 * 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.
 */

use std::io::Error;
use std::net::{Ipv4Addr, SocketAddrV4, UdpSocket};
use std::sync::Arc;

use slog::{info, o, Logger};

use crate::config::{Config, ConnectionConfig};

/// Server is the UDP server main implementation
pub struct Server {
    log: Logger,
}

impl Server {
    pub fn new(base: Logger) -> Self {
        let log = base.new(o!("source" => "server::Server"));
        return Server { log };
    }

    /// start the async processing of UDP packets
    pub async fn run(self, config: Arc<Config>) -> Result<(), Error> {
        let Server { log } = self;
        info!(log, "Starting on port {}", config.local.port);

        let _socket = bind(&config).await?;

        match &config.connections {
            ConnectionConfig::Sender { address, .. } => {
                info!(log, "Sender configuration"; "address" => address)
            }
            ConnectionConfig::Receiver { endpoints } => {
                info!(log, "Receiver configuration"; "endpoints" => endpoints.len())
            }
        };

        return Ok(());
    }
}

/// bind binds to the local socket provided in config.local.port
async fn bind(config: &Config) -> Result<UdpSocket, Error> {
    let addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), config.local.port);
    return UdpSocket::bind(addr);
}
<|endoftext|>


<commit_before>use message;

pub struct Server {
    id: i32,
}

static CONNACK_OK : [u8; 4] = [32, 2, 0, 0];
static PING_RESP : [u8; 2] = [0xd0, 0];

impl Server {
    pub fn new() -> Self {
        Server { id: 4 }
    }

    pub fn new_message<C: Client>(&mut self, client: &mut C, bytes: &[u8]) {
        let message_type = message::message_type(bytes);
        match message_type {
            message::MqttType::Connect => {
                client.send(&CONNACK_OK);
            },
            message::MqttType::PingReq => {
                client.send(&PING_RESP);
            },
            _ => panic!("Unknown message type")
        }
    }

    pub fn new_bytes<C: Client>(&mut self, client: &mut C, bytes: &[u8]) {
        let mut slice = bytes;

        while slice.len() > 0 {
            let remaining_len = message::remaining_length(bytes);
            let total_len = remaining_len + 2;

            if slice.len() >= total_len {
                let msg = &slice[0 .. total_len];
                slice = &slice[total_len ..];
                self.new_message(client, msg);
            } else {
                slice = &[];
            }
        }
    }
}

pub trait Client {
    fn send(&mut self, bytes: &[u8]);
}

struct TestClient {
    msgs: Vec<Vec<u8>>,
}

impl TestClient {
    fn new() -> Self {
        TestClient { msgs: vec!() }
    }

    fn last_msg(&self) -> &[u8] {
        self.msgs.last().unwrap()
    }
}

impl Client for TestClient {
    fn send(&mut self, bytes: &[u8]) {
        self.msgs.push(bytes.to_vec());
    }
}

#[test]
fn test_connect() {
    let connect_bytes = &[
        0x10u8, 0x2a, // fixed header
        0x00, 0x06, 'M' as u8, 'Q' as u8, 'I' as u8, 's' as u8, 'd' as u8, 'p' as u8,
        0x03, // protocol version
        0xcc, // connection flags 1100111x user, pw, !wr, w(01), w, !c, x
        0x00, 0x0a, // keepalive of 100
        0x00, 0x03, 'c' as u8, 'i' as u8, 'd' as u8, // client ID
        0x00, 0x04, 'w' as u8, 'i' as u8, 'l' as u8, 'l' as u8, // will topic
        0x00, 0x04, 'w' as u8, 'm' as u8, 's' as u8, 'g' as u8, // will msg
        0x00, 0x07, 'g' as u8, 'l' as u8, 'i' as u8, 'f' as u8, 't' as u8, 'e' as u8, 'l' as u8, // username
        0x00, 0x02, 'p' as u8, 'w' as u8, // password
        ][0..];

    let mut server = Server::new();
    let mut client = TestClient::new();

    server.new_message(&mut client, connect_bytes);
    assert_eq!(client.last_msg(), &CONNACK_OK);
}

#[test]
fn test_ping() {
    let ping_bytes =  &[0xc0u8, 0][0..];

    let mut server = Server::new();
    let mut client = TestClient::new();

    server.new_message(&mut client, ping_bytes);

    assert_eq!(client.last_msg(), &PING_RESP);
}

#[test]
fn test_pings() {
    let ping_bytes = &[0xc0u8, 0, 0xc0, 0, 0xc0, 0, 0xc0, 0][0..];

    let mut server = Server::new();
    let mut client = TestClient::new();

    server.new_bytes(&mut client, ping_bytes);

    assert_eq!(client.last_msg(), &PING_RESP);
    assert_eq!(client.msgs.len(), 4);
    for msg in client.msgs {
        assert_eq!(msg, &PING_RESP);
    }

}
<commit_msg>UT for Multiple MQTT messages in multiple streams but no leftover state<commit_after>use message;

pub struct Server {
    id: i32,
}

static CONNACK_OK : [u8; 4] = [32, 2, 0, 0];
static PING_RESP : [u8; 2] = [0xd0, 0];

impl Server {
    pub fn new() -> Self {
        Server { id: 4 }
    }

    pub fn new_message<C: Client>(&mut self, client: &mut C, bytes: &[u8]) {
        let message_type = message::message_type(bytes);
        match message_type {
            message::MqttType::Connect => {
                client.send(&CONNACK_OK);
            },
            message::MqttType::PingReq => {
                client.send(&PING_RESP);
            },
            _ => panic!("Unknown message type")
        }
    }

    pub fn new_bytes<C: Client>(&mut self, client: &mut C, bytes: &[u8]) {
        let mut slice = bytes;

        while slice.len() > 0 {
            let remaining_len = message::remaining_length(bytes);
            let total_len = remaining_len + 2;

            if slice.len() >= total_len {
                let msg = &slice[0 .. total_len];
                slice = &slice[total_len ..];
                self.new_message(client, msg);
            } else {
                slice = &[];
            }
        }
    }
}

pub trait Client {
    fn send(&mut self, bytes: &[u8]);
}

struct TestClient {
    msgs: Vec<Vec<u8>>,
}

impl TestClient {
    fn new() -> Self {
        TestClient { msgs: vec!() }
    }

    fn last_msg(&self) -> &[u8] {
        self.msgs.last().unwrap()
    }
}

impl Client for TestClient {
    fn send(&mut self, bytes: &[u8]) {
        self.msgs.push(bytes.to_vec());
    }
}

#[test]
fn test_connect() {
    let connect_bytes = &[
        0x10u8, 0x2a, // fixed header
        0x00, 0x06, 'M' as u8, 'Q' as u8, 'I' as u8, 's' as u8, 'd' as u8, 'p' as u8,
        0x03, // protocol version
        0xcc, // connection flags 1100111x user, pw, !wr, w(01), w, !c, x
        0x00, 0x0a, // keepalive of 100
        0x00, 0x03, 'c' as u8, 'i' as u8, 'd' as u8, // client ID
        0x00, 0x04, 'w' as u8, 'i' as u8, 'l' as u8, 'l' as u8, // will topic
        0x00, 0x04, 'w' as u8, 'm' as u8, 's' as u8, 'g' as u8, // will msg
        0x00, 0x07, 'g' as u8, 'l' as u8, 'i' as u8, 'f' as u8, 't' as u8, 'e' as u8, 'l' as u8, // username
        0x00, 0x02, 'p' as u8, 'w' as u8, // password
        ][0..];

    let mut server = Server::new();
    let mut client = TestClient::new();

    server.new_message(&mut client, connect_bytes);
    assert_eq!(client.last_msg(), &CONNACK_OK);
}

#[test]
fn test_ping() {
    let ping_bytes =  &[0xc0u8, 0][0..];

    let mut server = Server::new();
    let mut client = TestClient::new();

    server.new_message(&mut client, ping_bytes);

    assert_eq!(client.last_msg(), &PING_RESP);
}

#[test]
fn test_pings_all_at_once() {
    let ping_bytes = &[0xc0u8, 0, 0xc0, 0, 0xc0, 0, 0xc0, 0][0..];

    let mut server = Server::new();
    let mut client = TestClient::new();

    server.new_bytes(&mut client, ping_bytes);

    assert_eq!(client.last_msg(), &PING_RESP);
    assert_eq!(client.msgs.len(), 4);
    for msg in client.msgs {
        assert_eq!(msg, &PING_RESP);
    }
}

#[test]
fn test_pings_multiple_time_unbroken() {
    let ping_bytes = &[0xc0u8, 0, 0xc0, 0][0..];

    let mut server = Server::new();
    let mut client = TestClient::new();

    server.new_bytes(&mut client, ping_bytes);
    assert_eq!(client.msgs.len(), 2);

    server.new_bytes(&mut client, ping_bytes);
    assert_eq!(client.msgs.len(), 4);
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

use ::{Logic,Expect};
use eval::Eval;
use var::{Var,Mut};
use parse::{Parser,Map,Def,IR};

/// Source block statement types
#[derive(Debug,PartialEq)]
pub enum Src {
    /// Standard logic, eg: has_sword_item i
    Logic(String, Logic),

    /// References logic in env and emits varkinds
    ///
    /// Logic must resolve to true
    /// eg: if item_logic give_quest
    /// Can optionally end execution and begin next node
    If(Expect, Vec<Var>, Option<Next>),

    /// Or must follow an previous If
    ///
    /// Or only fires when previous If logic fails
    Or(Vec<Var>,Option<Next>),

    /// Just emits variables
    Emit(Vec<Var>),

    /// A composite logic type to group logic statements together
    Composite(String,Expect,Vec<String>),

    /// Ends execution and begins next node
    Next(Next),

    /// Mutate type, var being mutated, argument vars
    Mut(Mut, String, Vec<Var>),

    /// Match-like behavior for Mutations
    ///
    /// Map format should have Logic-Tested for the key
    /// and Mutation Function Signature for the value
    When(WhenMap),
}

/// Internal type to hold a specialized When-Mutate Map
pub type WhenMap = HashMap<String,(Mut,String,Vec<Var>)>;

/// Next-node action types
#[derive(Debug,PartialEq,Clone)]
pub enum Next {
    /// Instantly advances
    Now(String),

    /// Awaits for manual advancement, failure to advance continues current node
    Await(String),

    /// Select from a group, based on decision
    Select(Map),
}
impl Next {
    pub fn parse(exp: &mut Vec<IR>) -> Result<Next,&'static str> {
        let mut select_idx = None;
        for (i,n) in exp.iter().enumerate() {
            match n {
                &IR::Sym(ref s) => {
                    if s == &"next:select" {
                        select_idx = Some(i);
                        break
                    }
                },
                _ => {},
            }
        }

        // handle nested selects as a special case
        if let Some(idx) = select_idx {
            let map_ir = exp.remove(idx+1);
            let _ = exp.remove(idx); // next:select statement
            if let Ok(map) = Parser::parse_map(map_ir) {
                return Ok(Next::Select(map))
            }
            else { return Err("Cannot parse map") }
        }

        let next;
        if let Some(node) = exp.pop() {
            if let Some(tag) = exp.pop() {
                match tag {
                    IR::Sym(tag) => {
                        let mut next_tag = tag.split_terminator(':');
                        let is_next = next_tag.next() == Some("next");

                        if is_next {
                            let next_tag = next_tag.next();
                            match next_tag {
                                Some("now") => { next = Next::Now(node.into()) },
                                Some("await") => { next = Next::Await(node.into()) },
                                _ => { return Err("Invalid Next Type Found") },
                            }
                        }
                        else if next_tag.next().is_some() {
                            return Err("Unknown Tag encountered")
                        }
                        else {
                            exp.push(IR::Sym(tag.to_owned()));
                            exp.push(node);
                            return Err("Invalid Tag type")
                        }
                    },
                    _ => {
                        exp.push(tag);
                        exp.push(node);
                        return Err("Invalid Tag type")
                    }
                }
            }
            else {
                exp.push(node);
                return Err("Missing Tag type")
            }
        }
        else { return Err("No Next type found") }

        Ok(next)
    }
}

impl Src {
    pub fn eval<D:Eval> (&self, state: &mut HashMap<String,bool>,
                         data: &mut D,
                         def: &mut Def)
                         -> (Vec<Var>,Option<Next>)
    {
        match self {
            &Src::Mut(ref m, ref v, ref a) => {
                match m {
                    &Mut::Add | &Mut::Sub | &Mut::Mul | &Mut::Div => {
                        let mut num = None;

                        let var_name = Var::Sym(v.to_owned());
                        let mut v1 = Var::get_num(&var_name, def);
                        let is_def = v1.is_ok();
                        if !is_def { v1 = Var::get_num(&var_name, data); }

                        if let Ok(v1) = v1 {
                            let var_name = &a[0];
                            let mut v2 = Var::get_num(&var_name, def);
                            if v2.is_err() { v2 = Var::get_num(&var_name, data); }

                            if let Ok(v2) = v2 {
                                match m {
                                    &Mut::Add => {
                                        num = Some(v1+v2);
                                    },
                                    &Mut::Sub => {
                                        num = Some(v1-v2);
                                    },
                                    &Mut::Mul => {
                                        num = Some(v1*v2);
                                    },
                                    &Mut::Div => {
                                        num = Some(v1/v2);
                                    },
                                    _ => {},
                                }
                            }
                        }

                        if let Some(num) = num {
                            if is_def { def.set_path(&v, Var::Num(num)); }
                            else { data.set_path(&v, Var::Num(num)); }
                        }
                    },
                    &Mut::Swap => {
                        let val = a[0].clone();
                        if def.get_path(v).is_some() {
                            def.set_path(v,val);
                        }
                        else { data.set_path(&v, val); }
                    },
                    &Mut::Fn(ref fun) => {
                        if let Some(var) = data.get_path(&v) {
                            if let Some(r) = data.call(var, fun, a) {
                                data.set_path(&v, r);
                            }
                        }
                    },
                }

                return (vec![],None)
            }
            &Src::Next(ref next) => {
                return (vec![],Some(next.clone()))
            },
            &Src::Or(ref vars, ref next) => {
                return (vars.clone(), next.clone())
            },
            &Src::Emit(ref vars) => {
                return (vars.clone(),None)
            },
            &Src::Logic(ref name, ref logic) => { //logic updates state
                let name = name.clone();
                match logic {
                    &Logic::Is(ref lookup) => {
                        if let Some(r) = data.get_path(&lookup) {
                            match r {
                                Var::Bool(v) => { state.insert(name,v); },
                                _ => { state.insert(name,true); }, //if exists?
                            }
                        }
                        else { //check state table: some_thing !some_otherthing
                            let mut val = None;
                            if let Some(r) = state.get(lookup) {
                                val = Some(*r);
                            }

                            if let Some(val) = val {
                                state.insert(name,val);
                            }
                        }
                    },
                    &Logic::IsNot(ref lookup) => { //inverse state
                        let r = data.get_path(&lookup);

                        if r.is_some() {
                            match r.unwrap() {
                                Var::Bool(v) => {
                                    if !v { state.insert(name,true); }
                                },
                                _ => { state.insert(name,false); },
                            }
                        }
                        else {
                            let mut val = None;
                            if let Some(r) = state.get(lookup) {
                                val = Some(!r);
                            }

                            if let Some(val) = val {
                                state.insert(name,val);
                            }
                        }
                    },

                    &Logic::GT(ref left, ref right) => {
                        let right = Var::get_num::<D>(right,data);
                        let left = Var::get_num::<D>(left,data);

                        if left.is_ok() && right.is_ok() {
                            state.insert(name, left.unwrap() > right.unwrap());
                        }
                    },
                    &Logic::LT(ref left, ref right) => {
                        let right = Var::get_num::<D>(right,data);
                        let left = Var::get_num::<D>(left,data);

                        if left.is_ok() && right.is_ok() {
                            state.insert(name, left.unwrap() < right.unwrap());
                        }
                    },
                }

                return (vec![],None) // logic does not return anything
            },
            &Src::Composite(ref name, ref x, ref lookups) => {
                // track if any lookups are false or true
                let mut comp_false = false;
                let mut comp_true = false;

                for lookup in lookups.iter() {
                    let val = state.get(lookup);
                    if val.is_some() && *val.unwrap() {
                        comp_true = true;
                    }
                    else {
                        if val.is_some() { //found it but it's false
                            comp_false = true;
                        }
                        else { //check data for delayed reference
                            if let Some(val) = data.get_path(lookup) {
                                match val {
                                    Var::Bool(b) => {
                                        if b { comp_true = true; }
                                        else { comp_false = true; }
                                    }
                                    _ => { comp_true = true; } //identity/exists, true
                                }
                            }
                        }
                    }
                }

                match x {
                    &Expect::All => { // all must pass as true
                        if comp_true && !comp_false {
                            state.insert(name.clone(),true);
                        }
                    },
                    &Expect::Any => { // first truth passes for set
                        if comp_true {
                            state.insert(name.clone(),true);
                        }
                    },
                    &Expect::None => { // inverse of any, none must be true
                        if !comp_true && comp_false {
                            state.insert(name.clone(),true);
                        }
                    },
                    &Expect::Ref(_) => {} // this should never hit
                }

                return (vec![],None) // composite does not return anything
            },
            &Src::If(ref x, ref v, ref next) => {
                let mut if_value = false;
                match x {
                    &Expect::All => {
                        for n in state.values() {
                            if !n { if_value = false; break }
                            else { if_value = true; }
                        }
                    },
                    &Expect::Any => {
                        for n in state.values() {
                            if *n { if_value = true; break }
                        }
                    },
                    &Expect::None => {
                        for n in state.values() {
                            if !n { if_value = true; }
                            else { if_value = true; break }
                        }
                    },
                    &Expect::Ref(ref lookup) => {
                        let has_val = {
                            let val = state.get(lookup);
                            if let Some(val) = val {
                                if_value = *val;
                            }

                            val.is_some()
                        };

                        if !has_val {
                            if let Some(val) = data.get_path(lookup) {
                                match val {
                                    Var::Bool(v) => { if_value = v; },
                                    _ => { if_value = true; }
                                }
                            }
                        }
                    },
                }

                if if_value { return ((*v).clone(), next.clone()) }
                else { return (vec![],None) }
            },
            &Src::When(ref map) => {
                for (k, &(ref m, ref v, ref a)) in map.iter() {
                    let mut is_true = false;
                    if let Some(b) = state.get(k) { is_true = *b }
                    if is_true {
                        Src::eval(&Src::Mut(m.clone(), v.clone(), a.clone()), state, data, def);
                    }
                }

                return (vec![],None)
            },
        }
    }

    pub fn parse(mut exp: Vec<IR>) -> Result<Src,&'static str> {
        let ir = exp.remove(0);
        match ir {
            IR::Sym(ref sym) => {
                if sym.chars().next() == Some('@') { //mutating statement
                    exp.insert(0,IR::Sym(sym.to_owned()));
                    let (m, v, a) = try!(Mut::parse(&mut exp));
                    return Ok(Src::Mut(m,v,a))
                }
                else if sym == "when" {
                    if exp.len() != 1 { return Err("Invalid WHEN Logic") }
                    if let Ok(mut map) = Parser::parse_map(exp.pop().unwrap()) {
                        let mut when_map: WhenMap = HashMap::new();
                        for (k,mut v) in map.drain() {
                            let v_ir = v.drain(..).map(|n| n.into()).collect();
                            let m = try!(Src::parse(v_ir));
                            match m {
                                Src::Mut(m,v,a) => {
                                    when_map.insert(k, (m,v,a));
                                },
                                _ => { return Err("Invalid WHEN Logic"); }
                            }
                        }

                        if when_map.is_empty() { return Err("Unable to parse WHEN Map into Mut") }
                        Ok(Src::When(when_map))
                    }
                    else { Err(" Invalid WHEN Logic") }
                }
                else if sym == "if" {
                    if exp.len() < 2 { return Err("Invalid IF Logic") }

                    let x = exp.remove(0);
                    let next = Next::parse(&mut exp);

                    let mut v = vec![];
                    for n in exp.drain(..) {
                        let r = try!(Var::parse(n));
                        v.push(r);
                    }

                    Ok(Src::If(Expect::parse(x.into()),
                               v, next.ok()))
                }
                else if sym == "or" {
                    if exp.len() < 1 { return Err("Invalid OR Logic") }

                    let next = Next::parse(&mut exp);

                    let mut v = vec![];
                    for n in exp.drain(..) {
                        let r = try!(Var::parse(n));
                        v.push(r);
                    }

                    Ok(Src::Or(v,next.ok()))
                }
                else if &sym.split_terminator(':').next() == &Some("next") {
                    exp.insert(0, IR::Sym(sym.to_owned()));
                    if let Ok(next) = Next::parse(&mut exp) {
                        Ok(Src::Next(next))
                    }
                    else { Err("Invalid NEXT Logic") }
                }
                else if sym == "emit" {
                    if exp.len() > 0 {
                        let mut v = vec![];
                        for e in exp.drain(..) {
                            let r = try!(Var::parse(e));
                            v.push(r);
                        }

                        Ok(Src::Emit(v))
                    }
                    else { Err("Missing EMIT Logic") }
                }
                else {
                    let mut keys: Vec<&str> = sym.split_terminator(':').collect();
                    if keys.len() < 2 { // regular logic
                        let r = try!(Logic::parse(exp));
                        Ok(Src::Logic(sym.to_owned(),
                                      r))
                    }
                    else { // composite type
                        let kind = Expect::parse(keys.pop().unwrap().to_owned());
                        match kind { // only formal expected types allowed
                            Expect::Ref(_) => { return Err("Informal Expect found") },
                            _ => {}
                        }

                        let exp = exp.drain(..).map(|n| n.into()).collect();
                        Ok(Src::Composite(keys.pop().unwrap().to_owned(),
                                          kind,
                                          exp))
                    }
                }
            },
            _ => { Err("Encountered Non-Symbol Token") },
        }
    }
}
<commit_msg>reference local scopes on fn muts<commit_after>use std::collections::HashMap;

use ::{Logic,Expect};
use eval::Eval;
use var::{Var,Mut};
use parse::{Parser,Map,Def,IR};

/// Source block statement types
#[derive(Debug,PartialEq)]
pub enum Src {
    /// Standard logic, eg: has_sword_item i
    Logic(String, Logic),

    /// References logic in env and emits varkinds
    ///
    /// Logic must resolve to true
    /// eg: if item_logic give_quest
    /// Can optionally end execution and begin next node
    If(Expect, Vec<Var>, Option<Next>),

    /// Or must follow an previous If
    ///
    /// Or only fires when previous If logic fails
    Or(Vec<Var>,Option<Next>),

    /// Just emits variables
    Emit(Vec<Var>),

    /// A composite logic type to group logic statements together
    Composite(String,Expect,Vec<String>),

    /// Ends execution and begins next node
    Next(Next),

    /// Mutate type, var being mutated, argument vars
    Mut(Mut, String, Vec<Var>),

    /// Match-like behavior for Mutations
    ///
    /// Map format should have Logic-Tested for the key
    /// and Mutation Function Signature for the value
    When(WhenMap),
}

/// Internal type to hold a specialized When-Mutate Map
pub type WhenMap = HashMap<String,(Mut,String,Vec<Var>)>;

/// Next-node action types
#[derive(Debug,PartialEq,Clone)]
pub enum Next {
    /// Instantly advances
    Now(String),

    /// Awaits for manual advancement, failure to advance continues current node
    Await(String),

    /// Select from a group, based on decision
    Select(Map),
}
impl Next {
    pub fn parse(exp: &mut Vec<IR>) -> Result<Next,&'static str> {
        let mut select_idx = None;
        for (i,n) in exp.iter().enumerate() {
            match n {
                &IR::Sym(ref s) => {
                    if s == &"next:select" {
                        select_idx = Some(i);
                        break
                    }
                },
                _ => {},
            }
        }

        // handle nested selects as a special case
        if let Some(idx) = select_idx {
            let map_ir = exp.remove(idx+1);
            let _ = exp.remove(idx); // next:select statement
            if let Ok(map) = Parser::parse_map(map_ir) {
                return Ok(Next::Select(map))
            }
            else { return Err("Cannot parse map") }
        }

        let next;
        if let Some(node) = exp.pop() {
            if let Some(tag) = exp.pop() {
                match tag {
                    IR::Sym(tag) => {
                        let mut next_tag = tag.split_terminator(':');
                        let is_next = next_tag.next() == Some("next");

                        if is_next {
                            let next_tag = next_tag.next();
                            match next_tag {
                                Some("now") => { next = Next::Now(node.into()) },
                                Some("await") => { next = Next::Await(node.into()) },
                                _ => { return Err("Invalid Next Type Found") },
                            }
                        }
                        else if next_tag.next().is_some() {
                            return Err("Unknown Tag encountered")
                        }
                        else {
                            exp.push(IR::Sym(tag.to_owned()));
                            exp.push(node);
                            return Err("Invalid Tag type")
                        }
                    },
                    _ => {
                        exp.push(tag);
                        exp.push(node);
                        return Err("Invalid Tag type")
                    }
                }
            }
            else {
                exp.push(node);
                return Err("Missing Tag type")
            }
        }
        else { return Err("No Next type found") }

        Ok(next)
    }
}

impl Src {
    pub fn eval<D:Eval> (&self, state: &mut HashMap<String,bool>,
                         data: &mut D,
                         def: &mut Def)
                         -> (Vec<Var>,Option<Next>)
    {
        match self {
            &Src::Mut(ref m, ref v, ref a) => {
                match m {
                    &Mut::Add | &Mut::Sub | &Mut::Mul | &Mut::Div => {
                        let mut num = None;

                        let var_name = Var::Sym(v.to_owned());
                        let mut v1 = Var::get_num(&var_name, def);
                        let is_def = v1.is_ok();
                        if !is_def { v1 = Var::get_num(&var_name, data); }

                        if let Ok(v1) = v1 {
                            let var_name = &a[0];
                            let mut v2 = Var::get_num(&var_name, def);
                            if v2.is_err() { v2 = Var::get_num(&var_name, data); }

                            if let Ok(v2) = v2 {
                                match m {
                                    &Mut::Add => {
                                        num = Some(v1+v2);
                                    },
                                    &Mut::Sub => {
                                        num = Some(v1-v2);
                                    },
                                    &Mut::Mul => {
                                        num = Some(v1*v2);
                                    },
                                    &Mut::Div => {
                                        num = Some(v1/v2);
                                    },
                                    _ => {},
                                }
                            }
                        }

                        if let Some(num) = num {
                            if is_def { def.set_path(&v, Var::Num(num)); }
                            else { data.set_path(&v, Var::Num(num)); }
                        }
                    },
                    &Mut::Swap => {
                        let val = a[0].clone();
                        if def.get_path(v).is_some() {
                            def.set_path(v,val);
                        }
                        else { data.set_path(&v, val); }
                    },
                    &Mut::Fn(ref fun) => {
                        if let Some(var) = def.get_path(v) {
                            if let Some(r) = data.call(var, fun, a) {
                                def.set_path(&v, r);
                            }
                        }
                        else if let Some(var) = data.get_path(&v) {
                            if let Some(r) = data.call(var, fun, a) {
                                data.set_path(&v, r);
                            }
                        }
                    },
                }

                return (vec![],None)
            }
            &Src::Next(ref next) => {
                return (vec![],Some(next.clone()))
            },
            &Src::Or(ref vars, ref next) => {
                return (vars.clone(), next.clone())
            },
            &Src::Emit(ref vars) => {
                return (vars.clone(),None)
            },
            &Src::Logic(ref name, ref logic) => { //logic updates state
                let name = name.clone();
                match logic {
                    &Logic::Is(ref lookup) => {
                        if let Some(r) = data.get_path(&lookup) {
                            match r {
                                Var::Bool(v) => { state.insert(name,v); },
                                _ => { state.insert(name,true); }, //if exists?
                            }
                        }
                        else { //check state table: some_thing !some_otherthing
                            let mut val = None;
                            if let Some(r) = state.get(lookup) {
                                val = Some(*r);
                            }

                            if let Some(val) = val {
                                state.insert(name,val);
                            }
                        }
                    },
                    &Logic::IsNot(ref lookup) => { //inverse state
                        let r = data.get_path(&lookup);

                        if r.is_some() {
                            match r.unwrap() {
                                Var::Bool(v) => {
                                    if !v { state.insert(name,true); }
                                },
                                _ => { state.insert(name,false); },
                            }
                        }
                        else {
                            let mut val = None;
                            if let Some(r) = state.get(lookup) {
                                val = Some(!r);
                            }

                            if let Some(val) = val {
                                state.insert(name,val);
                            }
                        }
                    },

                    &Logic::GT(ref left, ref right) => {
                        let right = Var::get_num::<D>(right,data);
                        let left = Var::get_num::<D>(left,data);

                        if left.is_ok() && right.is_ok() {
                            state.insert(name, left.unwrap() > right.unwrap());
                        }
                    },
                    &Logic::LT(ref left, ref right) => {
                        let right = Var::get_num::<D>(right,data);
                        let left = Var::get_num::<D>(left,data);

                        if left.is_ok() && right.is_ok() {
                            state.insert(name, left.unwrap() < right.unwrap());
                        }
                    },
                }

                return (vec![],None) // logic does not return anything
            },
            &Src::Composite(ref name, ref x, ref lookups) => {
                // track if any lookups are false or true
                let mut comp_false = false;
                let mut comp_true = false;

                for lookup in lookups.iter() {
                    let val = state.get(lookup);
                    if val.is_some() && *val.unwrap() {
                        comp_true = true;
                    }
                    else {
                        if val.is_some() { //found it but it's false
                            comp_false = true;
                        }
                        else { //check data for delayed reference
                            if let Some(val) = data.get_path(lookup) {
                                match val {
                                    Var::Bool(b) => {
                                        if b { comp_true = true; }
                                        else { comp_false = true; }
                                    }
                                    _ => { comp_true = true; } //identity/exists, true
                                }
                            }
                        }
                    }
                }

                match x {
                    &Expect::All => { // all must pass as true
                        if comp_true && !comp_false {
                            state.insert(name.clone(),true);
                        }
                    },
                    &Expect::Any => { // first truth passes for set
                        if comp_true {
                            state.insert(name.clone(),true);
                        }
                    },
                    &Expect::None => { // inverse of any, none must be true
                        if !comp_true && comp_false {
                            state.insert(name.clone(),true);
                        }
                    },
                    &Expect::Ref(_) => {} // this should never hit
                }

                return (vec![],None) // composite does not return anything
            },
            &Src::If(ref x, ref v, ref next) => {
                let mut if_value = false;
                match x {
                    &Expect::All => {
                        for n in state.values() {
                            if !n { if_value = false; break }
                            else { if_value = true; }
                        }
                    },
                    &Expect::Any => {
                        for n in state.values() {
                            if *n { if_value = true; break }
                        }
                    },
                    &Expect::None => {
                        for n in state.values() {
                            if !n { if_value = true; }
                            else { if_value = true; break }
                        }
                    },
                    &Expect::Ref(ref lookup) => {
                        let has_val = {
                            let val = state.get(lookup);
                            if let Some(val) = val {
                                if_value = *val;
                            }

                            val.is_some()
                        };

                        if !has_val {
                            if let Some(val) = data.get_path(lookup) {
                                match val {
                                    Var::Bool(v) => { if_value = v; },
                                    _ => { if_value = true; }
                                }
                            }
                        }
                    },
                }

                if if_value { return ((*v).clone(), next.clone()) }
                else { return (vec![],None) }
            },
            &Src::When(ref map) => {
                for (k, &(ref m, ref v, ref a)) in map.iter() {
                    let mut is_true = false;
                    if let Some(b) = state.get(k) { is_true = *b }
                    if is_true {
                        Src::eval(&Src::Mut(m.clone(), v.clone(), a.clone()), state, data, def);
                    }
                }

                return (vec![],None)
            },
        }
    }

    pub fn parse(mut exp: Vec<IR>) -> Result<Src,&'static str> {
        let ir = exp.remove(0);
        match ir {
            IR::Sym(ref sym) => {
                if sym.chars().next() == Some('@') { //mutating statement
                    exp.insert(0,IR::Sym(sym.to_owned()));
                    let (m, v, a) = try!(Mut::parse(&mut exp));
                    return Ok(Src::Mut(m,v,a))
                }
                else if sym == "when" {
                    if exp.len() != 1 { return Err("Invalid WHEN Logic") }
                    if let Ok(mut map) = Parser::parse_map(exp.pop().unwrap()) {
                        let mut when_map: WhenMap = HashMap::new();
                        for (k,mut v) in map.drain() {
                            let v_ir = v.drain(..).map(|n| n.into()).collect();
                            let m = try!(Src::parse(v_ir));
                            match m {
                                Src::Mut(m,v,a) => {
                                    when_map.insert(k, (m,v,a));
                                },
                                _ => { return Err("Invalid WHEN Logic"); }
                            }
                        }

                        if when_map.is_empty() { return Err("Unable to parse WHEN Map into Mut") }
                        Ok(Src::When(when_map))
                    }
                    else { Err(" Invalid WHEN Logic") }
                }
                else if sym == "if" {
                    if exp.len() < 2 { return Err("Invalid IF Logic") }

                    let x = exp.remove(0);
                    let next = Next::parse(&mut exp);

                    let mut v = vec![];
                    for n in exp.drain(..) {
                        let r = try!(Var::parse(n));
                        v.push(r);
                    }

                    Ok(Src::If(Expect::parse(x.into()),
                               v, next.ok()))
                }
                else if sym == "or" {
                    if exp.len() < 1 { return Err("Invalid OR Logic") }

                    let next = Next::parse(&mut exp);

                    let mut v = vec![];
                    for n in exp.drain(..) {
                        let r = try!(Var::parse(n));
                        v.push(r);
                    }

                    Ok(Src::Or(v,next.ok()))
                }
                else if &sym.split_terminator(':').next() == &Some("next") {
                    exp.insert(0, IR::Sym(sym.to_owned()));
                    if let Ok(next) = Next::parse(&mut exp) {
                        Ok(Src::Next(next))
                    }
                    else { Err("Invalid NEXT Logic") }
                }
                else if sym == "emit" {
                    if exp.len() > 0 {
                        let mut v = vec![];
                        for e in exp.drain(..) {
                            let r = try!(Var::parse(e));
                            v.push(r);
                        }

                        Ok(Src::Emit(v))
                    }
                    else { Err("Missing EMIT Logic") }
                }
                else {
                    let mut keys: Vec<&str> = sym.split_terminator(':').collect();
                    if keys.len() < 2 { // regular logic
                        let r = try!(Logic::parse(exp));
                        Ok(Src::Logic(sym.to_owned(),
                                      r))
                    }
                    else { // composite type
                        let kind = Expect::parse(keys.pop().unwrap().to_owned());
                        match kind { // only formal expected types allowed
                            Expect::Ref(_) => { return Err("Informal Expect found") },
                            _ => {}
                        }

                        let exp = exp.drain(..).map(|n| n.into()).collect();
                        Ok(Src::Composite(keys.pop().unwrap().to_owned(),
                                          kind,
                                          exp))
                    }
                }
            },
            _ => { Err("Encountered Non-Symbol Token") },
        }
    }
}
<|endoftext|>


<commit_before>use nom;
use nom::{Err, IResult};

use metadata;
use frame;
use subframe;

use metadata::{Metadata, StreamInfo, metadata_parser};
use frame::{frame_parser, Frame};
use utility::{ErrorKind, ByteStream, ReadStream, StreamProducer};

use std::io;
use std::usize;
use std::fs::File;

enum ParserState {
  Marker,
  Metadata,
  Frame,
}

/// FLAC stream that decodes and hold file information.
pub struct Stream {
  info: StreamInfo,
  metadata: Vec<Metadata>,
  frames: Vec<Frame>,
  state: ParserState,
  output: Vec<i32>,
  frame_index: usize,
}

named!(pub stream_parser <&[u8], Stream>,
  chain!(
    blocks: metadata_parser ~
    frames: many1!(apply!(frame_parser, &blocks.0)),
    move|| {
      Stream {
        info: blocks.0,
        metadata: blocks.1,
        frames: frames,
        state: ParserState::Marker,
        output: Vec::new(),
        frame_index: 0,
      }
    }
  )
);

impl Stream {
  /// Constructor for the default state of a FLAC stream.
  ///
  /// This doesn't actually decode anything, it just hold the default values
  /// of each field.
  pub fn new() -> Stream {
    Stream {
      info: StreamInfo::new(),
      metadata: Vec::new(),
      frames: Vec::new(),
      state: ParserState::Marker,
      output: Vec::new(),
      frame_index: 0,
    }
  }

  /// Returns information for the current stream.
  pub fn info(&self) -> StreamInfo {
    self.info
  }

  /// Returns a slice of `Metadata`
  ///
  /// This slice excludes `StreamInfo`, which is located in `Stream::info`.
  /// Everything else is related to metadata for the FLAC stream is in the
  /// slice.
  pub fn metadata(&self) -> &[Metadata] {
    &self.metadata
  }

  /// Constructs a decoder with the given file name.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::NotFound` is returned when the given filename isn't found.
  /// * `ErrorKind::InvalidData` is returned when the data within the file
  ///   isn't valid FLAC data.
  pub fn from_file(filename: &str) -> io::Result<Stream> {
    File::open(filename).and_then(|file| {
      let mut producer = ReadStream::new(file);
      let error_str    = format!("parser: couldn't parse the given file {}",
                                 filename);

      Stream::from_stream_producer(&mut producer, &error_str)
    })
  }

  /// Constructs a decoder with the given buffer.
  ///
  /// This constructor assumes that an entire FLAC file is in the buffer.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::InvalidData` is returned when the data within the buffer
  ///   isn't valid FLAC data.
  pub fn from_buffer(buffer: &[u8]) -> io::Result<Stream> {
    let mut producer = ByteStream::new(buffer);
    let error_str    = "parser: couldn't parse the buffer";

    Stream::from_stream_producer(&mut producer, error_str)
  }

  fn from_stream_producer<P>(producer: &mut P, error_str: &str)
                             -> io::Result<Stream>
   where P: StreamProducer {
    let mut is_error = false;
    let mut stream   = Stream {
      info: StreamInfo::new(),
      metadata: Vec::new(),
      frames: Vec::new(),
      state: ParserState::Marker,
      output: Vec::new(),
      frame_index: 0,
    };

    loop {
      match stream.handle(producer) {
        Ok(_)                         => break,
        Err(ErrorKind::EndOfInput)    => break,
        Err(ErrorKind::Consumed(_))   => continue,
        Err(ErrorKind::Incomplete(_)) => continue,
        Err(_)                        => {
          is_error = true;

          break;
        }
      }
    }

    if !is_error {
      let channels    = stream.info.channels as usize;
      let block_size  = stream.info.max_block_size as usize;
      let output_size = block_size * channels;

      stream.output.reserve_exact(output_size);

      unsafe { stream.output.set_len(output_size) }

      Ok(stream)
    } else {
      Err(io::Error::new(io::ErrorKind::InvalidData, error_str))
    }
  }

  /// Returns an iterator over the decoded samples.
  pub fn iter(&mut self) -> Iter {
    Iter::new(self)
  }

  fn next_frame<'a>(&'a mut self) -> Option<&'a [i32]> {
    if self.frames.is_empty() || self.frame_index >= self.frames.len() {
      None
    } else {
      let frame       = &self.frames[self.frame_index];
      let channels    = frame.header.channels as usize;
      let block_size  = frame.header.block_size as usize;
      let mut channel = 0;

      for subframe in &frame.subframes[0..channels] {
        let start  = channel * block_size;
        let end    = (channel + 1) * block_size;
        let output = &mut self.output[start..end];

        subframe::decode(&subframe, output);

        channel += 1;
      }

      frame::decode(frame.header.channel_assignment, &mut self.output);

      self.frame_index += 1;

      Some(&self.output[0..(block_size * channels)])
    }
  }

  fn handle_marker<'a>(&mut self, input: &'a [u8]) -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(0);

    match tag!(input, "fLaC") {
      IResult::Done(i, _)    => {
        self.state = ParserState::Metadata;

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle_metadata<'a>(&mut self, input: &'a [u8])
                         -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(1);

    match metadata::block(input) {
      IResult::Done(i, block) => {
        let is_last = block.is_last;

        if let metadata::Data::StreamInfo(info) = block.data {
          self.info = info;
        } else {
          self.metadata.push(block);
        }

        if is_last {
          self.state = ParserState::Frame;
        }

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle_frame<'a>(&mut self, input: &'a [u8]) -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(2);

    match frame_parser(input, &self.info) {
      IResult::Done(i, frame) => {
        self.frames.push(frame);

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle<S: StreamProducer>(&mut self, stream: &mut S)
                               -> Result<(), ErrorKind> {
    stream.parse(|input| {
      match self.state {
        ParserState::Marker   => self.handle_marker(input),
        ParserState::Metadata => self.handle_metadata(input),
        ParserState::Frame    => self.handle_frame(input),
      }
    })
  }
}

pub struct Iter<'a> {
  stream: &'a mut Stream,
  channel: usize,
  frame_index: usize,
  block_size: usize,
  sample_index: usize,
  samples_left: u64,
}

impl<'a> Iter<'a> {
  pub fn new(stream: &'a mut Stream) -> Iter<'a> {
    let samples_left = stream.info.total_samples;

    Iter {
      stream: stream,
      channel: 0,
      frame_index: 0,
      block_size: 0,
      sample_index: 0,
      samples_left: samples_left,
    }
  }
}

impl<'a> Iterator for Iter<'a> {
  type Item = i32;

  fn next(&mut self) -> Option<Self::Item> {
    if self.block_size == 0 || self.sample_index == self.block_size {
      if self.stream.next_frame().is_none() {
        return None;
      } else {
        let frame = &self.stream.frames[self.frame_index];

        self.sample_index = 0;
        self.block_size   = frame.header.block_size as usize;
      }
    }

    let channels = self.stream.info.channels as usize;
    let index    = self.sample_index + (self.channel * self.block_size);
    let sample   = self.stream.output[index];

    self.channel      += 1;
    self.samples_left -= 1;

    // Reset current channel
    if self.channel == channels {
      self.channel       = 0;
      self.sample_index += 1;
    }

    Some(sample)
  }

  fn size_hint(&self) -> (usize, Option<usize>) {
    let samples_left = self.samples_left as usize;
    let max_value    = usize::max_value() as u64;

    // There is a chance that samples_left will be larger than a usize since
    // it is a u64. Make the upper bound None when it is.
    if self.samples_left > max_value {
      (samples_left, None)
    } else {
      (samples_left, Some(samples_left))
    }
  }
}

impl<'a> IntoIterator for &'a mut Stream {
  type Item     = i32;
  type IntoIter = Iter<'a>;

  fn into_iter(self) -> Self::IntoIter {
    self.iter()
  }
}
<commit_msg>Add documentation for the `Iter` struct<commit_after>use nom;
use nom::{Err, IResult};

use metadata;
use frame;
use subframe;

use metadata::{Metadata, StreamInfo, metadata_parser};
use frame::{frame_parser, Frame};
use utility::{ErrorKind, ByteStream, ReadStream, StreamProducer};

use std::io;
use std::usize;
use std::fs::File;

enum ParserState {
  Marker,
  Metadata,
  Frame,
}

/// FLAC stream that decodes and hold file information.
pub struct Stream {
  info: StreamInfo,
  metadata: Vec<Metadata>,
  frames: Vec<Frame>,
  state: ParserState,
  output: Vec<i32>,
  frame_index: usize,
}

named!(pub stream_parser <&[u8], Stream>,
  chain!(
    blocks: metadata_parser ~
    frames: many1!(apply!(frame_parser, &blocks.0)),
    move|| {
      Stream {
        info: blocks.0,
        metadata: blocks.1,
        frames: frames,
        state: ParserState::Marker,
        output: Vec::new(),
        frame_index: 0,
      }
    }
  )
);

impl Stream {
  /// Constructor for the default state of a FLAC stream.
  ///
  /// This doesn't actually decode anything, it just hold the default values
  /// of each field.
  pub fn new() -> Stream {
    Stream {
      info: StreamInfo::new(),
      metadata: Vec::new(),
      frames: Vec::new(),
      state: ParserState::Marker,
      output: Vec::new(),
      frame_index: 0,
    }
  }

  /// Returns information for the current stream.
  pub fn info(&self) -> StreamInfo {
    self.info
  }

  /// Returns a slice of `Metadata`
  ///
  /// This slice excludes `StreamInfo`, which is located in `Stream::info`.
  /// Everything else is related to metadata for the FLAC stream is in the
  /// slice.
  pub fn metadata(&self) -> &[Metadata] {
    &self.metadata
  }

  /// Constructs a decoder with the given file name.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::NotFound` is returned when the given filename isn't found.
  /// * `ErrorKind::InvalidData` is returned when the data within the file
  ///   isn't valid FLAC data.
  pub fn from_file(filename: &str) -> io::Result<Stream> {
    File::open(filename).and_then(|file| {
      let mut producer = ReadStream::new(file);
      let error_str    = format!("parser: couldn't parse the given file {}",
                                 filename);

      Stream::from_stream_producer(&mut producer, &error_str)
    })
  }

  /// Constructs a decoder with the given buffer.
  ///
  /// This constructor assumes that an entire FLAC file is in the buffer.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::InvalidData` is returned when the data within the buffer
  ///   isn't valid FLAC data.
  pub fn from_buffer(buffer: &[u8]) -> io::Result<Stream> {
    let mut producer = ByteStream::new(buffer);
    let error_str    = "parser: couldn't parse the buffer";

    Stream::from_stream_producer(&mut producer, error_str)
  }

  fn from_stream_producer<P>(producer: &mut P, error_str: &str)
                             -> io::Result<Stream>
   where P: StreamProducer {
    let mut is_error = false;
    let mut stream   = Stream {
      info: StreamInfo::new(),
      metadata: Vec::new(),
      frames: Vec::new(),
      state: ParserState::Marker,
      output: Vec::new(),
      frame_index: 0,
    };

    loop {
      match stream.handle(producer) {
        Ok(_)                         => break,
        Err(ErrorKind::EndOfInput)    => break,
        Err(ErrorKind::Consumed(_))   => continue,
        Err(ErrorKind::Incomplete(_)) => continue,
        Err(_)                        => {
          is_error = true;

          break;
        }
      }
    }

    if !is_error {
      let channels    = stream.info.channels as usize;
      let block_size  = stream.info.max_block_size as usize;
      let output_size = block_size * channels;

      stream.output.reserve_exact(output_size);

      unsafe { stream.output.set_len(output_size) }

      Ok(stream)
    } else {
      Err(io::Error::new(io::ErrorKind::InvalidData, error_str))
    }
  }

  /// Returns an iterator over the decoded samples.
  pub fn iter(&mut self) -> Iter {
    Iter::new(self)
  }

  fn next_frame<'a>(&'a mut self) -> Option<&'a [i32]> {
    if self.frames.is_empty() || self.frame_index >= self.frames.len() {
      None
    } else {
      let frame       = &self.frames[self.frame_index];
      let channels    = frame.header.channels as usize;
      let block_size  = frame.header.block_size as usize;
      let mut channel = 0;

      for subframe in &frame.subframes[0..channels] {
        let start  = channel * block_size;
        let end    = (channel + 1) * block_size;
        let output = &mut self.output[start..end];

        subframe::decode(&subframe, output);

        channel += 1;
      }

      frame::decode(frame.header.channel_assignment, &mut self.output);

      self.frame_index += 1;

      Some(&self.output[0..(block_size * channels)])
    }
  }

  fn handle_marker<'a>(&mut self, input: &'a [u8]) -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(0);

    match tag!(input, "fLaC") {
      IResult::Done(i, _)    => {
        self.state = ParserState::Metadata;

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle_metadata<'a>(&mut self, input: &'a [u8])
                         -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(1);

    match metadata::block(input) {
      IResult::Done(i, block) => {
        let is_last = block.is_last;

        if let metadata::Data::StreamInfo(info) = block.data {
          self.info = info;
        } else {
          self.metadata.push(block);
        }

        if is_last {
          self.state = ParserState::Frame;
        }

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle_frame<'a>(&mut self, input: &'a [u8]) -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(2);

    match frame_parser(input, &self.info) {
      IResult::Done(i, frame) => {
        self.frames.push(frame);

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle<S: StreamProducer>(&mut self, stream: &mut S)
                               -> Result<(), ErrorKind> {
    stream.parse(|input| {
      match self.state {
        ParserState::Marker   => self.handle_marker(input),
        ParserState::Metadata => self.handle_metadata(input),
        ParserState::Frame    => self.handle_frame(input),
      }
    })
  }
}

/// An iterator over a reference of the decoded FLAC stream.
pub struct Iter<'a> {
  stream: &'a mut Stream,
  channel: usize,
  frame_index: usize,
  block_size: usize,
  sample_index: usize,
  samples_left: u64,
}

impl<'a> Iter<'a> {
  pub fn new(stream: &'a mut Stream) -> Iter<'a> {
    let samples_left = stream.info.total_samples;

    Iter {
      stream: stream,
      channel: 0,
      frame_index: 0,
      block_size: 0,
      sample_index: 0,
      samples_left: samples_left,
    }
  }
}

impl<'a> Iterator for Iter<'a> {
  type Item = i32;

  fn next(&mut self) -> Option<Self::Item> {
    if self.block_size == 0 || self.sample_index == self.block_size {
      if self.stream.next_frame().is_none() {
        return None;
      } else {
        let frame = &self.stream.frames[self.frame_index];

        self.sample_index = 0;
        self.block_size   = frame.header.block_size as usize;
      }
    }

    let channels = self.stream.info.channels as usize;
    let index    = self.sample_index + (self.channel * self.block_size);
    let sample   = self.stream.output[index];

    self.channel      += 1;
    self.samples_left -= 1;

    // Reset current channel
    if self.channel == channels {
      self.channel       = 0;
      self.sample_index += 1;
    }

    Some(sample)
  }

  fn size_hint(&self) -> (usize, Option<usize>) {
    let samples_left = self.samples_left as usize;
    let max_value    = usize::max_value() as u64;

    // There is a chance that samples_left will be larger than a usize since
    // it is a u64. Make the upper bound None when it is.
    if self.samples_left > max_value {
      (samples_left, None)
    } else {
      (samples_left, Some(samples_left))
    }
  }
}

impl<'a> IntoIterator for &'a mut Stream {
  type Item     = i32;
  type IntoIter = Iter<'a>;

  fn into_iter(self) -> Self::IntoIter {
    self.iter()
  }
}
<|endoftext|>


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

use std::collections::HashMap;

use common::INSTRUCTIONS;

// Opcodes
const HALT: i64 = 0x00;
const IN_N: i64 = 0x01;
const OUT_N: i64 = 0x02;
const IN_S: i64 = 0x03;
const OUT_S: i64 = 0x04;
const ADD: i64 = 0x05;
const SUB: i64 = 0x06;
const MUL: i64 = 0x07;
const DIV: i64 = 0x08;
const CON: i64 = 0x09;
const PUSH: i64 = 0x0A;
const POP: i64 = 0x0B;
const LD: i64 = 0x0C;
const ST: i64 = 0x0D;
const JMP: i64 = 0x0E;
const JGR: i64 = 0x0F;
const JGE: i64 = 0x10;
const JEQ: i64 = 0x11;
const JNE: i64 = 0x12;
const JLE: i64 = 0x13;
const JLS: i64 = 0x14;

const REG_NUM: usize = 8;
const INS_MEM_CAP: usize = 50000;

pub struct Vm {
    pc: usize,
    sp: usize,
    acc: i64,
    reg: [i64; REG_NUM],
    ins_mem: [i64; INS_MEM_CAP],
}

impl Vm {
    pub fn new() -> Box<Vm> {
        Box::new(Vm {
            pc: 0,
            sp: 0,
            acc: 0,
            reg: [0; REG_NUM],
            ins_mem: [0; INS_MEM_CAP],
        })
    }

    pub fn load_code(&self, code: Vec<String>) {
        println!("{}", code.len());

        let mut opcode_map: HashMap<&'static str, i64> = HashMap::new();

        opcode_map.insert(INSTRUCTIONS.halt, HALT);
        opcode_map.insert(INSTRUCTIONS.in_n, IN_N);
        opcode_map.insert(INSTRUCTIONS.out_n, OUT_N);
        opcode_map.insert(INSTRUCTIONS.in_s, IN_S);
        opcode_map.insert(INSTRUCTIONS.out_s, OUT_S);
        opcode_map.insert(INSTRUCTIONS.add, ADD);
        opcode_map.insert(INSTRUCTIONS.sub, SUB);
        opcode_map.insert(INSTRUCTIONS.mul, MUL);
        opcode_map.insert(INSTRUCTIONS.div, DIV);
        opcode_map.insert(INSTRUCTIONS.con, CON);
        opcode_map.insert(INSTRUCTIONS.push, PUSH);
        opcode_map.insert(INSTRUCTIONS.pop, POP);
        opcode_map.insert(INSTRUCTIONS.ld, LD);
        opcode_map.insert(INSTRUCTIONS.st, ST);
        opcode_map.insert(INSTRUCTIONS.jmp, JMP);
        opcode_map.insert(INSTRUCTIONS.jgr, JGR);
        opcode_map.insert(INSTRUCTIONS.jge, JGE);
        opcode_map.insert(INSTRUCTIONS.jeq, JEQ);
        opcode_map.insert(INSTRUCTIONS.jne, JNE);
        opcode_map.insert(INSTRUCTIONS.jle, JLE);
        opcode_map.insert(INSTRUCTIONS.jls, JLS);

        for instruction in code {
            println!("{}", instruction);
        }
    }

    pub fn execute(&self) {
        loop {
            let inst = self.ins_mem[self.pc];

            match inst {
                HALT => break,
                IN_N => self.process_in_n(),
                OUT_N => self.process_out_n(),
                IN_S => self.process_in_s(),
                OUT_S => self.process_out_s(),
                ADD => self.process_add(),
                SUB => self.process_sub(),
                MUL => self.process_mul(),
                DIV => self.process_div(),
                CON => self.process_con(),
                PUSH => self.process_push(),
                POP => self.process_pop(),
                LD => self.process_ld(),
                ST => self.process_st(),
                JMP => self.process_jmp(),
                JGR => self.process_jgr(),
                JGE => self.process_jge(),
                JEQ => self.process_jeq(),
                JNE => self.process_jne(),
                JLE => self.process_jle(),
                JLS => self.process_jls(),
                _ => {
                    println!("Unknow instruction. Aborting.");
                    break;
                }
            }
        }
    }

    fn process_in_n(&self) {}

    fn process_out_n(&self) {}

    fn process_in_s(&self) {}

    fn process_out_s(&self) {}

    fn process_add(&self) {}

    fn process_sub(&self) {}

    fn process_mul(&self) {}

    fn process_div(&self) {}

    fn process_con(&self) {}

    fn process_push(&self) {}

    fn process_pop(&self) {}

    fn process_ld(&self) {}

    fn process_st(&self) {}

    fn process_jmp(&self) {}

    fn process_jgr(&self) {}

    fn process_jge(&self) {}

    fn process_jeq(&self) {}

    fn process_jne(&self) {}

    fn process_jle(&self) {}

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

use std::collections::HashMap;

use common::INSTRUCTIONS;

// Bit Masks
const INST_MASK: u64 = 0xFF;

// Opcodes
const HALT: u64 = 0x00;
const IN_N: u64 = 0x01;
const OUT_N: u64 = 0x02;
const IN_S: u64 = 0x03;
const OUT_S: u64 = 0x04;
const ADD: u64 = 0x05;
const SUB: u64 = 0x06;
const MUL: u64 = 0x07;
const DIV: u64 = 0x08;
const CON: u64 = 0x09;
const PUSH: u64 = 0x0A;
const POP: u64 = 0x0B;
const LD: u64 = 0x0C;
const ST: u64 = 0x0D;
const JMP: u64 = 0x0E;
const JGR: u64 = 0x0F;
const JGE: u64 = 0x10;
const JEQ: u64 = 0x11;
const JNE: u64 = 0x12;
const JLE: u64 = 0x13;
const JLS: u64 = 0x14;

const REG_NUM: usize = 8;
const INS_MEM_CAP: usize = 50000;

pub struct Vm {
    pc: usize,
    sp: usize,
    acc: u64,
    reg: [u64; REG_NUM],
    ins_mem: [u64; INS_MEM_CAP],
}

impl Vm {
    pub fn new() -> Box<Vm> {
        Box::new(Vm {
            pc: 0,
            sp: 0,
            acc: 0,
            reg: [0; REG_NUM],
            ins_mem: [0; INS_MEM_CAP],
        })
    }

    pub fn load_code(&self, code: Vec<String>) {
        println!("{}", code.len());

        let mut opcode_map: HashMap<&'static str, u64> = HashMap::new();

        opcode_map.insert(INSTRUCTIONS.halt, HALT);
        opcode_map.insert(INSTRUCTIONS.in_n, IN_N);
        opcode_map.insert(INSTRUCTIONS.out_n, OUT_N);
        opcode_map.insert(INSTRUCTIONS.in_s, IN_S);
        opcode_map.insert(INSTRUCTIONS.out_s, OUT_S);
        opcode_map.insert(INSTRUCTIONS.add, ADD);
        opcode_map.insert(INSTRUCTIONS.sub, SUB);
        opcode_map.insert(INSTRUCTIONS.mul, MUL);
        opcode_map.insert(INSTRUCTIONS.div, DIV);
        opcode_map.insert(INSTRUCTIONS.con, CON);
        opcode_map.insert(INSTRUCTIONS.push, PUSH);
        opcode_map.insert(INSTRUCTIONS.pop, POP);
        opcode_map.insert(INSTRUCTIONS.ld, LD);
        opcode_map.insert(INSTRUCTIONS.st, ST);
        opcode_map.insert(INSTRUCTIONS.jmp, JMP);
        opcode_map.insert(INSTRUCTIONS.jgr, JGR);
        opcode_map.insert(INSTRUCTIONS.jge, JGE);
        opcode_map.insert(INSTRUCTIONS.jeq, JEQ);
        opcode_map.insert(INSTRUCTIONS.jne, JNE);
        opcode_map.insert(INSTRUCTIONS.jle, JLE);
        opcode_map.insert(INSTRUCTIONS.jls, JLS);

        for instruction in code {
            println!("{}", instruction);
        }
    }

    pub fn execute(&self) {
        loop {
            let inst = self.ins_mem[self.pc];
            let opcode = (inst.rotate_left(8) & INST_MASK);

            match opcode {
                HALT => break,
                IN_N => self.process_in_n(),
                OUT_N => self.process_out_n(),
                IN_S => self.process_in_s(),
                OUT_S => self.process_out_s(),
                ADD => self.process_add(),
                SUB => self.process_sub(),
                MUL => self.process_mul(),
                DIV => self.process_div(),
                CON => self.process_con(),
                PUSH => self.process_push(),
                POP => self.process_pop(),
                LD => self.process_ld(),
                ST => self.process_st(),
                JMP => self.process_jmp(),
                JGR => self.process_jgr(),
                JGE => self.process_jge(),
                JEQ => self.process_jeq(),
                JNE => self.process_jne(),
                JLE => self.process_jle(),
                JLS => self.process_jls(),
                _ => {
                    println!("Unknow instruction. Aborting.");
                    break;
                }
            }
        }
    }

    fn process_in_n(&self) {}

    fn process_out_n(&self) {}

    fn process_in_s(&self) {}

    fn process_out_s(&self) {}

    fn process_add(&self) {}

    fn process_sub(&self) {}

    fn process_mul(&self) {}

    fn process_div(&self) {}

    fn process_con(&self) {}

    fn process_push(&self) {}

    fn process_pop(&self) {}

    fn process_ld(&self) {}

    fn process_st(&self) {}

    fn process_jmp(&self) {}

    fn process_jgr(&self) {}

    fn process_jge(&self) {}

    fn process_jeq(&self) {}

    fn process_jne(&self) {}

    fn process_jle(&self) {}

    fn process_jls(&self) {}
}
<|endoftext|>