<commit_before>// Copyright (c) 2016
// Jeff Nettleton
//
// Licensed under the MIT license (http://opensource.org/licenses/MIT). This
// file may not be copied, modified, or distributed except according to those
// terms

//! # Canteen
//!
//! ## Description
//!
//! A pure Rust clone of [Flask](http://flask.pocoo.org), a simple but powerful Python
//! web framework.
//!
//! ## Example
//!
//! The principle behind Canteen is simple -- handler functions are defined as simple
//! Rust functions that take a `Request` and return a `Response`. Handlers are then attached
//! to one or more routes and HTTP methods/verbs. Routes are specified using a simple
//! syntax that lets you define variables within them; variables that can then be
//! extracted to perform various operations. Currently, the following variable types can
//! be used:
//!
//! - `<str:name>` will match anything inside a path segment, returns a `String`
//! - `<int:name>` will return a signed integer (`i32`) from a path segment
//!   - ex: `cnt.add_route("/api/foo/<int:foo_id>", &[Method::Get], my_handler)` will match
//!   `"/api/foo/123"` but not `"/api/foo/123.34"` or `"/api/foo/bar"`
//! - `<uint:name>` will return an unsigned integer (`u32`)
//! - `<float:name>` does the same thing as the `int` parameter definition, but matches numbers
//! with decimal points and returns an `f32`
//! - `<path:name>` will greedily take all path data contained, returns a `String`
//!   - ex: `cnt.add_route("/static/<path:name>", &[Method::Get], utils::static_file)` will
//!   serve anything in the `/static/` directory as a file
//!
//! ```rust
//! extern crate canteen;
//!
//! use canteen::{Canteen, Request, Response, Method};
//! use canteen::utils;
//!
//! fn hello_handler(req: &Request) -> Response {
//!     let mut res = Response::new();
//!
//!     res.set_status(200);
//!     res.set_content_type("text/plain");
//!     res.append("Hello, world!");
//!
//!     res
//! }
//!
//! fn double_handler(req: &Request) -> Response {
//!     let to_dbl: i32 = req.get("to_dbl");
//!
//!     /* simpler response generation syntax */
//!     utils::make_response(format!("{}", to_dbl * 2), "text/plain", 200)
//! }
//!
//! fn main() {
//!     let mut cnt = Canteen::new(("127.0.0.1", 8080));
//!
//!     // set the default route handler to show a 404 message
//!     cnt.set_default(utils::err_404);
//!
//!     // respond to requests to / with "Hello, world!"
//!     cnt.add_route("/", &[Method::Get], hello_handler);
//!
//!     // pull a variable from the path and do something with it
//!     cnt.add_route("/double/<int:to_dbl>", &[Method::Get], double_handler);
//!
//!     // serve raw files from the /static/ directory
//!     cnt.add_route("/static/<path:path>", &[Method::Get], utils::static_file);
//!
//!     /* cnt.run() */;
//! }
//! ```

extern crate mio;
extern crate regex;
extern crate chrono;
extern crate rustc_serialize;

pub mod utils;
pub mod route;
pub mod request;
pub mod response;

use std::io::Result;
use std::io::prelude::*;
use std::net::ToSocketAddrs;
use std::collections::HashMap;
use std::collections::HashSet;
use mio::tcp::{TcpListener, TcpStream};
use mio::util::Slab;
use mio::*;

pub use request::*;
pub use response::*;

struct Client {
    sock:   TcpStream,
    token:  Token,
    events: EventSet,
    i_buf:  Vec<u8>,
    o_buf:  Vec<u8>,
}

impl Client {
    fn new(sock: TcpStream, token: Token) -> Client {
        Client {
            sock:   sock,
            token:  token,
            events: EventSet::hup(),
            i_buf:  Vec::with_capacity(2048),
            o_buf:  Vec::new(),
        }
    }

    fn receive(&mut self) -> Result<bool> {
        let mut buf: Vec<u8> = Vec::with_capacity(2048);

        match self.sock.try_read_buf(&mut buf) {
            Ok(size)  => {
                match size {
                    Some(_) => {
                        self.events.remove(EventSet::readable());
                        self.events.insert(EventSet::writable());
                        self.i_buf.extend(buf);
                        return Ok(true);
                    },
                    None    => {
                        return Ok(false);
                    },
                }
            },
            Err(e)  => {
                panic!("failed to read from socket! <token: {:?}> <error: {:?}>", self.token, e);
            },
        }

        Ok(false)
    }

    // write the client's output buffer to the socket.
    //
    // the following return values mean:
    //  - Ok(true):  we can close the connection
    //  - Ok(false): keep listening for writeable event and continue next time
    //  - Err(e):    something dun fucked up
    fn send(&mut self) -> Result<bool> {
        while self.o_buf.len() > 0 {
            match self.sock.write(&self.o_buf.as_slice()) {
                Ok(sz)  => {
                    if sz == self.o_buf.len() {
                        // we did it!
                        self.events.remove(EventSet::writable());
                        break;
                    } else {
                        // keep going
                        self.o_buf = self.o_buf.split_off(sz);
                    }
                },
                Err(e)  => {
                    panic!("failed to write to socket! <token: {:?}> <error: {:?}>", self.token, e);
                }
            }
        }

        Ok(true)
    }

    fn register(&mut self, evl: &mut EventLoop<Canteen>) -> Result<()> {
        self.events.insert(EventSet::readable());

        evl.register(&self.sock, self.token, self.events, PollOpt::edge() | PollOpt::oneshot())
           .or_else(|e| {
               panic!("failed to register client! <token: {:?}> <error: {:?}>", self.token, e);
           })
    }

    fn reregister(&mut self, evl: &mut EventLoop<Canteen>) -> Result<()> {
        evl.reregister(&self.sock, self.token, self.events, PollOpt::edge() | PollOpt::oneshot())
           .or_else(|e| {
               panic!("failed to re-register client! <token: {:?}> <error: {:?}>", self.token, e);
           })
    }
}

/// The primary struct provided by the library. The aim is to have a similar
/// interface to Flask, the Python microframework.
pub struct Canteen {
    routes:  HashMap<route::RouteDef, route::Route>,
    rcache:  HashMap<route::RouteDef, route::RouteDef>,
    server:  TcpListener,
    token:   Token,
    conns:   Slab<Client>,
    default: fn(&Request) -> Response,
}

impl Handler for Canteen {
    type Timeout = ();
    type Message = u32;

    fn ready(&mut self, evl: &mut EventLoop<Canteen>, token: Token, events: EventSet) {
        if events.is_error() || events.is_hup() {
            self.reset_connection(token);
            return;
        }

        if events.is_readable() {
            if self.token == token {
                self.accept(evl);
            } else {
                self.readable(evl, token)
                    .and_then(|_| self.get_client(token)
                                      .reregister(evl))
                    .unwrap_or_else(|e| {
                        panic!("read event failed! <token: {:?}> <error: {:?}>", token, e);
                    });
            }

            return;
        }

        if events.is_writable() {
            match self.get_client(token).send() {
                Ok(true)    => { self.reset_connection(token); },
                Ok(false)   => { let _ = self.get_client(token).reregister(evl); },
                Err(_)      => { panic!("something really bad happened!"); },
            }
        }
    }
}

impl Canteen {
    /// Creates a new Canteen instance.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::Canteen;
    ///
    /// let cnt = Canteen::new(("127.0.0.1", 8081));
    /// ```
    pub fn new<A: ToSocketAddrs>(addr: A) -> Canteen {
        Canteen {
            routes:  HashMap::new(),
            rcache:  HashMap::new(),
            server:  TcpListener::bind(&addr.to_socket_addrs().unwrap().next().unwrap()).unwrap(),
            token:   Token(1),
            conns:   Slab::new_starting_at(Token(2), 2048),
            default: utils::err_404,
        }
    }

    /// Adds a new route definition to be handled by Canteen.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::{Canteen, Request, Response, Method};
    /// use canteen::utils;
    ///
    /// fn handler(_: &Request) -> Response {
    ///     utils::make_response("<b>Hello, world!</b>", "text/html", 200)
    /// }
    ///
    /// fn main() {
    ///     let mut cnt = Canteen::new(("127.0.0.1", 8082));
    ///     cnt.add_route("/hello", &[Method::Get], handler);
    /// }
    /// ```
    pub fn add_route(&mut self, path: &str, mlist: &[Method],
                     handler: fn(&Request) -> Response) -> &mut Canteen {
        let mut methods: HashSet<Method> = HashSet::new();

        // make them unique
        for m in mlist {
            methods.insert(*m);
        }

        for m in methods {
            let rd = route::RouteDef {
                pathdef:    String::from(path),
                method:     m,
            };

            if self.routes.contains_key(&rd) {
                panic!("a route handler for {} has already been defined!", path);
            }

            self.routes.insert(rd, route::Route::new(&path, m, handler));
        }

        self
    }

    /// Defines a default route for undefined paths.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::Canteen;
    /// use canteen::utils;
    ///
    /// let mut cnt = Canteen::new(("127.0.0.1", 8083));
    /// cnt.set_default(utils::err_404);
    /// ```
    pub fn set_default(&mut self, handler: fn(&Request) -> Response) {
        self.default = handler;
    }

    fn get_client<'a>(&'a mut self, token: Token) -> &'a mut Client {
        &mut self.conns[token]
    }

    fn accept(&mut self, evl: &mut EventLoop<Canteen>) {
        let (sock, _) = match self.server.accept() {
            Ok(s)   => {
                match s {
                    Some(sock)  => sock,
                    None        => {
                        panic!("failed to accept new connection!");
                    }
                }
            },
            Err(e)  => {
                panic!("failed to accept new connection! <error: {:?}>", e);
            },
        };

        match self.conns.insert_with(|token| Client::new(sock, token)) {
            Some(token) => {
                match self.get_client(token).register(evl) {
                    Ok(_)   => {},
                    Err(e)  => {
                        panic!("failed to register client! <token: {:?}> <error: {:?}>", token, e);
                    },
                }
            },
            None        => {
                panic!("failed to add client connection!");
            },
        }

        self.reregister(evl);
    }

    fn handle_request(&mut self, rqstr: &str) -> Vec<u8> {
        let mut req = Request::from_str(&rqstr);
        let resolved = route::RouteDef { pathdef: req.path.clone(), method: req.method };
        let mut handler: fn(&Request) -> Response = self.default;

        if self.rcache.contains_key(&resolved) {
            let ref route = self.routes[&self.rcache[&resolved]];

            handler = route.handler;
            req.params = route.parse(&req.path);
        } else {
            for (path, route) in &self.routes {
                match (route).is_match(&req) {
                    true  => {
                        handler = route.handler;
                        req.params = route.parse(&req.path);
                        self.rcache.insert(resolved, (*path).clone());
                        break;
                    },
                    false => continue,
                }
            }
        }

        handler(&req).gen_output()
    }

    fn readable(&mut self, evl: &mut EventLoop<Canteen>, token: Token) -> Result<bool> {
        match self.get_client(token).receive() {
            Ok(true)    => {
                let buf = self.get_client(token).i_buf.clone();
                let rqstr = String::from_utf8(buf).unwrap();
                self.get_client(token).o_buf = self.handle_request(&rqstr);
            },
            Ok(false)   => {},
            Err(e)      => {
                panic!("message wasn't actually readable! <error: {:?}>", e);
            },
        };

        let _ = self.get_client(token).reregister(evl);

        Ok(true)
    }

    fn reset_connection(&mut self, token: Token) {
        // kill the connection
        self.conns.remove(token);
    }

    fn register(&mut self, evl: &mut EventLoop<Canteen>) -> Result<()> {
        evl.register(&self.server, self.token, EventSet::readable(), PollOpt::edge() | PollOpt::oneshot())
           .or_else(|e| {
               panic!("failed to register server! <token: {:?}> <error: {:?}>", self.token, e);
           })
    }

    fn reregister(&mut self, evl: &mut EventLoop<Canteen>) {
        match evl.reregister(&self.server, self.token,
                             EventSet::readable(),
                             PollOpt::edge() | PollOpt::oneshot()) {
            Ok(_)   => {},
            Err(e)  => {
               panic!("failed to register server! <token: {:?}> <error: {:?}>", self.token, e);
           }
        };
    }

    /// Creates the listener and starts a Canteen server's event loop.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::Canteen;
    ///
    /// let cnt = Canteen::new(("127.0.0.1", 8084));
    /// /* cnt.run(); */
    /// ```
    pub fn run(&mut self) {
        let mut evl = EventLoop::new().unwrap();
        self.register(&mut evl).ok();
        evl.run(self).unwrap();
    }
}
<commit_msg>ditch unused var in doctest<commit_after>// Copyright (c) 2016
// Jeff Nettleton
//
// Licensed under the MIT license (http://opensource.org/licenses/MIT). This
// file may not be copied, modified, or distributed except according to those
// terms

//! # Canteen
//!
//! ## Description
//!
//! A pure Rust clone of [Flask](http://flask.pocoo.org), a simple but powerful Python
//! web framework.
//!
//! ## Example
//!
//! The principle behind Canteen is simple -- handler functions are defined as simple
//! Rust functions that take a `Request` and return a `Response`. Handlers are then attached
//! to one or more routes and HTTP methods/verbs. Routes are specified using a simple
//! syntax that lets you define variables within them; variables that can then be
//! extracted to perform various operations. Currently, the following variable types can
//! be used:
//!
//! - `<str:name>` will match anything inside a path segment, returns a `String`
//! - `<int:name>` will return a signed integer (`i32`) from a path segment
//!   - ex: `cnt.add_route("/api/foo/<int:foo_id>", &[Method::Get], my_handler)` will match
//!   `"/api/foo/123"` but not `"/api/foo/123.34"` or `"/api/foo/bar"`
//! - `<uint:name>` will return an unsigned integer (`u32`)
//! - `<float:name>` does the same thing as the `int` parameter definition, but matches numbers
//! with decimal points and returns an `f32`
//! - `<path:name>` will greedily take all path data contained, returns a `String`
//!   - ex: `cnt.add_route("/static/<path:name>", &[Method::Get], utils::static_file)` will
//!   serve anything in the `/static/` directory as a file
//!
//! ```rust
//! extern crate canteen;
//!
//! use canteen::{Canteen, Request, Response, Method};
//! use canteen::utils;
//!
//! fn hello_handler(_: &Request) -> Response {
//!     let mut res = Response::new();
//!
//!     res.set_status(200);
//!     res.set_content_type("text/plain");
//!     res.append("Hello, world!");
//!
//!     res
//! }
//!
//! fn double_handler(req: &Request) -> Response {
//!     let to_dbl: i32 = req.get("to_dbl");
//!
//!     /* simpler response generation syntax */
//!     utils::make_response(format!("{}", to_dbl * 2), "text/plain", 200)
//! }
//!
//! fn main() {
//!     let mut cnt = Canteen::new(("127.0.0.1", 8080));
//!
//!     // set the default route handler to show a 404 message
//!     cnt.set_default(utils::err_404);
//!
//!     // respond to requests to / with "Hello, world!"
//!     cnt.add_route("/", &[Method::Get], hello_handler);
//!
//!     // pull a variable from the path and do something with it
//!     cnt.add_route("/double/<int:to_dbl>", &[Method::Get], double_handler);
//!
//!     // serve raw files from the /static/ directory
//!     cnt.add_route("/static/<path:path>", &[Method::Get], utils::static_file);
//!
//!     /* cnt.run() */;
//! }
//! ```

extern crate mio;
extern crate regex;
extern crate chrono;
extern crate rustc_serialize;

pub mod utils;
pub mod route;
pub mod request;
pub mod response;

use std::io::Result;
use std::io::prelude::*;
use std::net::ToSocketAddrs;
use std::collections::HashMap;
use std::collections::HashSet;
use mio::tcp::{TcpListener, TcpStream};
use mio::util::Slab;
use mio::*;

pub use request::*;
pub use response::*;

struct Client {
    sock:   TcpStream,
    token:  Token,
    events: EventSet,
    i_buf:  Vec<u8>,
    o_buf:  Vec<u8>,
}

impl Client {
    fn new(sock: TcpStream, token: Token) -> Client {
        Client {
            sock:   sock,
            token:  token,
            events: EventSet::hup(),
            i_buf:  Vec::with_capacity(2048),
            o_buf:  Vec::new(),
        }
    }

    fn receive(&mut self) -> Result<bool> {
        let mut buf: Vec<u8> = Vec::with_capacity(2048);

        match self.sock.try_read_buf(&mut buf) {
            Ok(size)  => {
                match size {
                    Some(_) => {
                        self.events.remove(EventSet::readable());
                        self.events.insert(EventSet::writable());
                        self.i_buf.extend(buf);
                        return Ok(true);
                    },
                    None    => {
                        return Ok(false);
                    },
                }
            },
            Err(e)  => {
                panic!("failed to read from socket! <token: {:?}> <error: {:?}>", self.token, e);
            },
        }

        Ok(false)
    }

    // write the client's output buffer to the socket.
    //
    // the following return values mean:
    //  - Ok(true):  we can close the connection
    //  - Ok(false): keep listening for writeable event and continue next time
    //  - Err(e):    something dun fucked up
    fn send(&mut self) -> Result<bool> {
        while self.o_buf.len() > 0 {
            match self.sock.write(&self.o_buf.as_slice()) {
                Ok(sz)  => {
                    if sz == self.o_buf.len() {
                        // we did it!
                        self.events.remove(EventSet::writable());
                        break;
                    } else {
                        // keep going
                        self.o_buf = self.o_buf.split_off(sz);
                    }
                },
                Err(e)  => {
                    panic!("failed to write to socket! <token: {:?}> <error: {:?}>", self.token, e);
                }
            }
        }

        Ok(true)
    }

    fn register(&mut self, evl: &mut EventLoop<Canteen>) -> Result<()> {
        self.events.insert(EventSet::readable());

        evl.register(&self.sock, self.token, self.events, PollOpt::edge() | PollOpt::oneshot())
           .or_else(|e| {
               panic!("failed to register client! <token: {:?}> <error: {:?}>", self.token, e);
           })
    }

    fn reregister(&mut self, evl: &mut EventLoop<Canteen>) -> Result<()> {
        evl.reregister(&self.sock, self.token, self.events, PollOpt::edge() | PollOpt::oneshot())
           .or_else(|e| {
               panic!("failed to re-register client! <token: {:?}> <error: {:?}>", self.token, e);
           })
    }
}

/// The primary struct provided by the library. The aim is to have a similar
/// interface to Flask, the Python microframework.
pub struct Canteen {
    routes:  HashMap<route::RouteDef, route::Route>,
    rcache:  HashMap<route::RouteDef, route::RouteDef>,
    server:  TcpListener,
    token:   Token,
    conns:   Slab<Client>,
    default: fn(&Request) -> Response,
}

impl Handler for Canteen {
    type Timeout = ();
    type Message = u32;

    fn ready(&mut self, evl: &mut EventLoop<Canteen>, token: Token, events: EventSet) {
        if events.is_error() || events.is_hup() {
            self.reset_connection(token);
            return;
        }

        if events.is_readable() {
            if self.token == token {
                self.accept(evl);
            } else {
                self.readable(evl, token)
                    .and_then(|_| self.get_client(token)
                                      .reregister(evl))
                    .unwrap_or_else(|e| {
                        panic!("read event failed! <token: {:?}> <error: {:?}>", token, e);
                    });
            }

            return;
        }

        if events.is_writable() {
            match self.get_client(token).send() {
                Ok(true)    => { self.reset_connection(token); },
                Ok(false)   => { let _ = self.get_client(token).reregister(evl); },
                Err(_)      => { panic!("something really bad happened!"); },
            }
        }
    }
}

impl Canteen {
    /// Creates a new Canteen instance.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::Canteen;
    ///
    /// let cnt = Canteen::new(("127.0.0.1", 8081));
    /// ```
    pub fn new<A: ToSocketAddrs>(addr: A) -> Canteen {
        Canteen {
            routes:  HashMap::new(),
            rcache:  HashMap::new(),
            server:  TcpListener::bind(&addr.to_socket_addrs().unwrap().next().unwrap()).unwrap(),
            token:   Token(1),
            conns:   Slab::new_starting_at(Token(2), 2048),
            default: utils::err_404,
        }
    }

    /// Adds a new route definition to be handled by Canteen.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::{Canteen, Request, Response, Method};
    /// use canteen::utils;
    ///
    /// fn handler(_: &Request) -> Response {
    ///     utils::make_response("<b>Hello, world!</b>", "text/html", 200)
    /// }
    ///
    /// fn main() {
    ///     let mut cnt = Canteen::new(("127.0.0.1", 8082));
    ///     cnt.add_route("/hello", &[Method::Get], handler);
    /// }
    /// ```
    pub fn add_route(&mut self, path: &str, mlist: &[Method],
                     handler: fn(&Request) -> Response) -> &mut Canteen {
        let mut methods: HashSet<Method> = HashSet::new();

        // make them unique
        for m in mlist {
            methods.insert(*m);
        }

        for m in methods {
            let rd = route::RouteDef {
                pathdef:    String::from(path),
                method:     m,
            };

            if self.routes.contains_key(&rd) {
                panic!("a route handler for {} has already been defined!", path);
            }

            self.routes.insert(rd, route::Route::new(&path, m, handler));
        }

        self
    }

    /// Defines a default route for undefined paths.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::Canteen;
    /// use canteen::utils;
    ///
    /// let mut cnt = Canteen::new(("127.0.0.1", 8083));
    /// cnt.set_default(utils::err_404);
    /// ```
    pub fn set_default(&mut self, handler: fn(&Request) -> Response) {
        self.default = handler;
    }

    fn get_client<'a>(&'a mut self, token: Token) -> &'a mut Client {
        &mut self.conns[token]
    }

    fn accept(&mut self, evl: &mut EventLoop<Canteen>) {
        let (sock, _) = match self.server.accept() {
            Ok(s)   => {
                match s {
                    Some(sock)  => sock,
                    None        => {
                        panic!("failed to accept new connection!");
                    }
                }
            },
            Err(e)  => {
                panic!("failed to accept new connection! <error: {:?}>", e);
            },
        };

        match self.conns.insert_with(|token| Client::new(sock, token)) {
            Some(token) => {
                match self.get_client(token).register(evl) {
                    Ok(_)   => {},
                    Err(e)  => {
                        panic!("failed to register client! <token: {:?}> <error: {:?}>", token, e);
                    },
                }
            },
            None        => {
                panic!("failed to add client connection!");
            },
        }

        self.reregister(evl);
    }

    fn handle_request(&mut self, rqstr: &str) -> Vec<u8> {
        let mut req = Request::from_str(&rqstr);
        let resolved = route::RouteDef { pathdef: req.path.clone(), method: req.method };
        let mut handler: fn(&Request) -> Response = self.default;

        if self.rcache.contains_key(&resolved) {
            let ref route = self.routes[&self.rcache[&resolved]];

            handler = route.handler;
            req.params = route.parse(&req.path);
        } else {
            for (path, route) in &self.routes {
                match (route).is_match(&req) {
                    true  => {
                        handler = route.handler;
                        req.params = route.parse(&req.path);
                        self.rcache.insert(resolved, (*path).clone());
                        break;
                    },
                    false => continue,
                }
            }
        }

        handler(&req).gen_output()
    }

    fn readable(&mut self, evl: &mut EventLoop<Canteen>, token: Token) -> Result<bool> {
        match self.get_client(token).receive() {
            Ok(true)    => {
                let buf = self.get_client(token).i_buf.clone();
                let rqstr = String::from_utf8(buf).unwrap();
                self.get_client(token).o_buf = self.handle_request(&rqstr);
            },
            Ok(false)   => {},
            Err(e)      => {
                panic!("message wasn't actually readable! <error: {:?}>", e);
            },
        };

        let _ = self.get_client(token).reregister(evl);

        Ok(true)
    }

    fn reset_connection(&mut self, token: Token) {
        // kill the connection
        self.conns.remove(token);
    }

    fn register(&mut self, evl: &mut EventLoop<Canteen>) -> Result<()> {
        evl.register(&self.server, self.token, EventSet::readable(), PollOpt::edge() | PollOpt::oneshot())
           .or_else(|e| {
               panic!("failed to register server! <token: {:?}> <error: {:?}>", self.token, e);
           })
    }

    fn reregister(&mut self, evl: &mut EventLoop<Canteen>) {
        match evl.reregister(&self.server, self.token,
                             EventSet::readable(),
                             PollOpt::edge() | PollOpt::oneshot()) {
            Ok(_)   => {},
            Err(e)  => {
               panic!("failed to register server! <token: {:?}> <error: {:?}>", self.token, e);
           }
        };
    }

    /// Creates the listener and starts a Canteen server's event loop.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::Canteen;
    ///
    /// let cnt = Canteen::new(("127.0.0.1", 8084));
    /// /* cnt.run(); */
    /// ```
    pub fn run(&mut self) {
        let mut evl = EventLoop::new().unwrap();
        self.register(&mut evl).ok();
        evl.run(self).unwrap();
    }
}
<|endoftext|>


<commit_before>//! CHIP-8 emulator backend.
//! You can develop your own frontends for it.
//!
//! The reference frontend is
//! [crusty-chip-sfml](https://github.com/crumblingstatue/crusty-chip-sfml).
//!
//! The CHIP-8 technical documentation in the comments is copied from
//! http://devernay.free.fr/hacks/chip8/C8TECH10.HTM,
//! Copyright (c) Thomas P. Greene.

#![feature(core)]

use std::slice::bytes::copy_memory;
use std::num::Wrapping;

mod ops;

const START_ADDR: u16 = 0x200;
const MEM_SIZE: usize = 4096;
pub const DISPLAY_WIDTH: usize = 64;
pub const DISPLAY_HEIGHT: usize = 32;

static FONTSET: [u8; 5 * 0x10] = [
    0xF0, 0x90, 0x90, 0x90, 0xF0, // 0
    0x20, 0x60, 0x20, 0x20, 0x70, // 1
    0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2
    0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3
    0x90, 0x90, 0xF0, 0x10, 0x10, // 4
    0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5
    0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6
    0xF0, 0x10, 0x20, 0x40, 0x40, // 7
    0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8
    0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9
    0xF0, 0x90, 0xF0, 0x90, 0x90, // A
    0xE0, 0x90, 0xE0, 0x90, 0xE0, // B
    0xF0, 0x80, 0x80, 0x80, 0xF0, // C
    0xE0, 0x90, 0x90, 0x90, 0xE0, // D
    0xF0, 0x80, 0xF0, 0x80, 0xF0, // E
    0xF0, 0x80, 0xF0, 0x80, 0x80, // F
];

struct KeypressWait {
    wait: bool,
    vx: usize
}

/// CHIP-8 virtual machine
pub struct VirtualMachine {
    ram: [u8; MEM_SIZE],
    v: [Wrapping<u8>; 16],
    i: u16,
    delay_timer: u8,
    sound_timer: u8,
    pc: u16,
    sp: u8,
    stack: [u16; 16],
    display: [u8; DISPLAY_WIDTH * DISPLAY_HEIGHT],
    display_updated: bool,
    keys: [bool; 16],
    keypress_wait: KeypressWait
}

impl VirtualMachine {

    /// Constructs a new `VirtualMachine`.
    pub fn new() -> VirtualMachine {
        let mut ch8 = VirtualMachine {
            ram: [0; MEM_SIZE],
            v: [Wrapping(0); 16],
            i: 0,
            delay_timer: 0,
            sound_timer: 0,
            pc: START_ADDR,
            sp: 0,
            stack: [0; 16],
            display: [0; DISPLAY_WIDTH * DISPLAY_HEIGHT],
            display_updated: false,
            keys: [false; 16],
            keypress_wait: KeypressWait {
                wait: false,
                vx: 0
            }
        };
        copy_memory(&FONTSET, &mut ch8.ram[0usize..5 * 0x10]);
        ch8
    }

    /// Load a ROM
    ///
    /// ## Arguments ##
    /// * rom - ROM to load
    pub fn load_rom(&mut self, rom: &[u8]) {
        let len = self.ram.len();
        copy_memory(rom, &mut self.ram[START_ADDR as usize .. len]);
    }

    /// Do an emulation cycle.
    pub fn do_cycle(&mut self) {
        self.display_updated = false;
        if self.keypress_wait.wait {
            return;
        }

        let ins = self.fetch_ins();
        self.dispatch(ins);
    }

    // Decode instruction and execute it
    fn dispatch(&mut self, ins: u16) {
        // A 12-bit value, the lowest 12 bits of the instruction
        let nnn = ins & 0x0FFF;
        // A 4-bit value, the lowest 4 bits of the instruction
        let n = ins & 0x000F;
        // A 4-bit value, the lower 4 bits of the high byte of the instruction
        let x = (ins & 0x0F00) >> 8;
        // A 4-bit value, the upper 4 bits of the low byte of the instruction
        let y = (ins & 0x00F0) >> 4;
        // kk or byte - An 8-bit value, the lowest 8 bits of the instruction
        let kk = (ins & 0x00FF) as u8;

        match (ins & 0xF000) >> 12 {
            0x0 => match nnn {
                0x0E0 => ops::clear_display(self, ),
                0x0EE => ops::ret_from_subroutine(self, ),
                _ => ops::jump_to_sys_routine(self, 0)
            },
            0x1 => ops::jump_addr(self, nnn),
            0x2 => ops::call_subroutine(self, nnn as usize),
            0x3 => ops::skip_next_vx_eq(self, x as usize, kk),
            0x4 => ops::skip_next_vx_ne(self, x as usize, kk),
            0x5 => match n {
                0x0 => ops::skip_next_vx_eq_vy(self, x as usize, y as usize),
                _ => panic!("Unknown 0x5XXX instruction: {:x}", ins)
            },
            0x6 => ops::set_vx_byte(self, x as usize, kk),
            0x7 => ops::add_vx_byte(self, x as usize, kk),
            0x8 => {
                let (x, y) = (x as usize, y as usize);
                match n {
                    0x0 => ops::set_vx_to_vy(self, x, y),
                    0x1 => ops::set_vx_to_vx_or_vy(self, x, y),
                    0x2 => ops::set_vx_to_vx_and_vy(self, x, y),
                    0x3 => ops::set_vx_to_vx_xor_vy(self, x, y),
                    0x4 => ops::add_vx_vy(self, x, y),
                    0x5 => ops::sub_vx_vy(self, x, y),
                    0x6 => ops::set_vx_to_vx_shr_1(self, x),
                    0xE => ops::set_vx_to_vx_shl_1(self, x),
                    _ => panic!("Unknown 0x8XXX instruction: {:x}", ins)
                }
            },
            0x9 => match n {
                0x0 => ops::skip_next_vx_ne_vy(self, x as usize, y as usize),
                _ => panic!("Unknown 0x9XXX instruction: {:x}", ins)
            },
            0xA => ops::set_i(self, nnn),
            0xC => ops::set_vx_rand_and(self, x as usize, kk),
            0xD => ops::display_sprite(self, x as usize, y as usize, n as usize),
            0xE => match kk {
                0xA1 => ops::skip_next_key_vx_not_pressed(self, x as usize),
                0x9E => ops::skip_next_key_vx_pressed(self, x as usize),
                _ => panic!("Unknown 0xEXXX instruction: {:x}", ins)
            },
            0xF => {
                match kk {
                    0x07 => ops::set_vx_to_delay_timer(self, x as usize),
                    0x0A => ops::wait_for_keypress_store_in_vx(self, x as usize),
                    0x15 => ops::set_delay_timer(self, x as usize),
                    0x18 => ops::set_sound_timer(self, x as usize),
                    0x1E => ops::add_vx_to_i(self, x as usize),
                    0x29 => ops::set_i_to_loc_of_digit_vx(self, x as usize),
                    0x33 => ops::store_bcd_of_vx_to_i(self, x as usize),
                    0x55 => ops::copy_v0_through_vx_to_mem(self, x as usize),
                    0x65 => ops::read_v0_through_vx_from_mem(self, x as usize),
                    _ => panic!("Unknown 0xFXXX instruction: {:x}", ins)
                }
            },
            _ => panic!("Unknown instruction: {:04x}", ins)
        }
    }

    fn fetch_ins(&mut self) -> u16 {
        let b1 = self.ram[self.pc as usize];
        let b2 = self.ram[(self.pc + 1) as usize];
        self.pc += 2;
        (b1 as u16) << 8 | b2 as u16
    }

    /// Press a key on the hexadecimal keypad
    ///
    /// `key` should be in the range `0..15`
    pub fn press_key(&mut self, key: usize) {
        assert!(key <= 15);
        self.keys[key] = true;
        if self.keypress_wait.wait {
            self.v[self.keypress_wait.vx].0 = key as u8;
            self.keypress_wait.wait = false;
        }
    }

    /// Release a key on the hexadecimal keypad
    ///
    /// `key` should be in the range `0..15`
    pub fn release_key(&mut self, key: usize) {
        assert!(key <= 15);
        self.keys[key] = false;
    }

    /// Decrement the sound and delay timers
    ///
    /// They should be decremented at a rate of 60 Hz
    pub fn decrement_timers(&mut self) {
        if self.delay_timer > 0 {
            self.delay_timer -= 1;
        }
        if self.sound_timer > 0 {
            self.sound_timer -= 1;
        }
    }

    pub fn display_updated(&self) -> bool { self.display_updated }
    pub fn display(&self) -> &[u8] { &self.display }
}
<commit_msg>Make VirtualMachine copyable<commit_after>//! CHIP-8 emulator backend.
//! You can develop your own frontends for it.
//!
//! The reference frontend is
//! [crusty-chip-sfml](https://github.com/crumblingstatue/crusty-chip-sfml).
//!
//! The CHIP-8 technical documentation in the comments is copied from
//! http://devernay.free.fr/hacks/chip8/C8TECH10.HTM,
//! Copyright (c) Thomas P. Greene.

#![feature(core)]

use std::slice::bytes::copy_memory;
use std::num::Wrapping;
use std::ops::{Deref, DerefMut};

mod ops;

const START_ADDR: u16 = 0x200;
const MEM_SIZE: usize = 4096;
pub const DISPLAY_WIDTH: usize = 64;
pub const DISPLAY_HEIGHT: usize = 32;

static FONTSET: [u8; 5 * 0x10] = [
    0xF0, 0x90, 0x90, 0x90, 0xF0, // 0
    0x20, 0x60, 0x20, 0x20, 0x70, // 1
    0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2
    0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3
    0x90, 0x90, 0xF0, 0x10, 0x10, // 4
    0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5
    0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6
    0xF0, 0x10, 0x20, 0x40, 0x40, // 7
    0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8
    0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9
    0xF0, 0x90, 0xF0, 0x90, 0x90, // A
    0xE0, 0x90, 0xE0, 0x90, 0xE0, // B
    0xF0, 0x80, 0x80, 0x80, 0xF0, // C
    0xE0, 0x90, 0x90, 0x90, 0xE0, // D
    0xF0, 0x80, 0xF0, 0x80, 0xF0, // E
    0xF0, 0x80, 0xF0, 0x80, 0x80, // F
];

#[derive(Clone, Copy)]
struct KeypressWait {
    wait: bool,
    vx: usize
}

macro_rules! array_wrap (
    ($name:ident, $typ:ty) => (
        #[derive(Copy)]
        struct $name($typ);
        impl Clone for $name {
            fn clone(&self) -> $name { *self }
        }
        impl Deref for $name {
            type Target = $typ;
            fn deref(&self) -> &$typ { &self.0 }
        }
        impl DerefMut for $name {
            fn deref_mut(&mut self) -> &mut $typ { &mut self.0 }
        }
    )
);

array_wrap!(DisplayArray, [u8; DISPLAY_WIDTH * DISPLAY_HEIGHT]);
array_wrap!(MemArray, [u8; MEM_SIZE]);

/// CHIP-8 virtual machine
#[derive(Clone, Copy)]
pub struct VirtualMachine {
    ram: MemArray,
    v: [Wrapping<u8>; 16],
    i: u16,
    delay_timer: u8,
    sound_timer: u8,
    pc: u16,
    sp: u8,
    stack: [u16; 16],
    display: DisplayArray,
    display_updated: bool,
    keys: [bool; 16],
    keypress_wait: KeypressWait
}

impl VirtualMachine {

    /// Constructs a new `VirtualMachine`.
    pub fn new() -> VirtualMachine {
        let mut ch8 = VirtualMachine {
            ram: MemArray([0; MEM_SIZE]),
            v: [Wrapping(0); 16],
            i: 0,
            delay_timer: 0,
            sound_timer: 0,
            pc: START_ADDR,
            sp: 0,
            stack: [0; 16],
            display: DisplayArray([0; DISPLAY_WIDTH * DISPLAY_HEIGHT]),
            display_updated: false,
            keys: [false; 16],
            keypress_wait: KeypressWait {
                wait: false,
                vx: 0
            }
        };
        copy_memory(&FONTSET, &mut ch8.ram[0usize..5 * 0x10]);
        ch8
    }

    /// Load a ROM
    ///
    /// ## Arguments ##
    /// * rom - ROM to load
    pub fn load_rom(&mut self, rom: &[u8]) {
        let len = self.ram.len();
        copy_memory(rom, &mut self.ram[START_ADDR as usize .. len]);
    }

    /// Do an emulation cycle.
    pub fn do_cycle(&mut self) {
        self.display_updated = false;
        if self.keypress_wait.wait {
            return;
        }

        let ins = self.fetch_ins();
        self.dispatch(ins);
    }

    // Decode instruction and execute it
    fn dispatch(&mut self, ins: u16) {
        // A 12-bit value, the lowest 12 bits of the instruction
        let nnn = ins & 0x0FFF;
        // A 4-bit value, the lowest 4 bits of the instruction
        let n = ins & 0x000F;
        // A 4-bit value, the lower 4 bits of the high byte of the instruction
        let x = (ins & 0x0F00) >> 8;
        // A 4-bit value, the upper 4 bits of the low byte of the instruction
        let y = (ins & 0x00F0) >> 4;
        // kk or byte - An 8-bit value, the lowest 8 bits of the instruction
        let kk = (ins & 0x00FF) as u8;

        match (ins & 0xF000) >> 12 {
            0x0 => match nnn {
                0x0E0 => ops::clear_display(self, ),
                0x0EE => ops::ret_from_subroutine(self, ),
                _ => ops::jump_to_sys_routine(self, 0)
            },
            0x1 => ops::jump_addr(self, nnn),
            0x2 => ops::call_subroutine(self, nnn as usize),
            0x3 => ops::skip_next_vx_eq(self, x as usize, kk),
            0x4 => ops::skip_next_vx_ne(self, x as usize, kk),
            0x5 => match n {
                0x0 => ops::skip_next_vx_eq_vy(self, x as usize, y as usize),
                _ => panic!("Unknown 0x5XXX instruction: {:x}", ins)
            },
            0x6 => ops::set_vx_byte(self, x as usize, kk),
            0x7 => ops::add_vx_byte(self, x as usize, kk),
            0x8 => {
                let (x, y) = (x as usize, y as usize);
                match n {
                    0x0 => ops::set_vx_to_vy(self, x, y),
                    0x1 => ops::set_vx_to_vx_or_vy(self, x, y),
                    0x2 => ops::set_vx_to_vx_and_vy(self, x, y),
                    0x3 => ops::set_vx_to_vx_xor_vy(self, x, y),
                    0x4 => ops::add_vx_vy(self, x, y),
                    0x5 => ops::sub_vx_vy(self, x, y),
                    0x6 => ops::set_vx_to_vx_shr_1(self, x),
                    0xE => ops::set_vx_to_vx_shl_1(self, x),
                    _ => panic!("Unknown 0x8XXX instruction: {:x}", ins)
                }
            },
            0x9 => match n {
                0x0 => ops::skip_next_vx_ne_vy(self, x as usize, y as usize),
                _ => panic!("Unknown 0x9XXX instruction: {:x}", ins)
            },
            0xA => ops::set_i(self, nnn),
            0xC => ops::set_vx_rand_and(self, x as usize, kk),
            0xD => ops::display_sprite(self, x as usize, y as usize, n as usize),
            0xE => match kk {
                0xA1 => ops::skip_next_key_vx_not_pressed(self, x as usize),
                0x9E => ops::skip_next_key_vx_pressed(self, x as usize),
                _ => panic!("Unknown 0xEXXX instruction: {:x}", ins)
            },
            0xF => {
                match kk {
                    0x07 => ops::set_vx_to_delay_timer(self, x as usize),
                    0x0A => ops::wait_for_keypress_store_in_vx(self, x as usize),
                    0x15 => ops::set_delay_timer(self, x as usize),
                    0x18 => ops::set_sound_timer(self, x as usize),
                    0x1E => ops::add_vx_to_i(self, x as usize),
                    0x29 => ops::set_i_to_loc_of_digit_vx(self, x as usize),
                    0x33 => ops::store_bcd_of_vx_to_i(self, x as usize),
                    0x55 => ops::copy_v0_through_vx_to_mem(self, x as usize),
                    0x65 => ops::read_v0_through_vx_from_mem(self, x as usize),
                    _ => panic!("Unknown 0xFXXX instruction: {:x}", ins)
                }
            },
            _ => panic!("Unknown instruction: {:04x}", ins)
        }
    }

    fn fetch_ins(&mut self) -> u16 {
        let b1 = self.ram[self.pc as usize];
        let b2 = self.ram[(self.pc + 1) as usize];
        self.pc += 2;
        (b1 as u16) << 8 | b2 as u16
    }

    /// Press a key on the hexadecimal keypad
    ///
    /// `key` should be in the range `0..15`
    pub fn press_key(&mut self, key: usize) {
        assert!(key <= 15);
        self.keys[key] = true;
        if self.keypress_wait.wait {
            self.v[self.keypress_wait.vx].0 = key as u8;
            self.keypress_wait.wait = false;
        }
    }

    /// Release a key on the hexadecimal keypad
    ///
    /// `key` should be in the range `0..15`
    pub fn release_key(&mut self, key: usize) {
        assert!(key <= 15);
        self.keys[key] = false;
    }

    /// Decrement the sound and delay timers
    ///
    /// They should be decremented at a rate of 60 Hz
    pub fn decrement_timers(&mut self) {
        if self.delay_timer > 0 {
            self.delay_timer -= 1;
        }
        if self.sound_timer > 0 {
            self.sound_timer -= 1;
        }
    }

    pub fn display_updated(&self) -> bool { self.display_updated }
    pub fn display(&self) -> &[u8] { &*self.display }
}
<|endoftext|>


<commit_before>/// 2D coordinate
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Coord {
    pub x: usize,
    pub y: usize
}

/// 2D dimensions
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Size {
    pub width: usize,
    pub height: usize
}

impl Coord {
    /// Create a coordinate at (x, y)
    pub fn new(x: usize, y: usize) -> Coord {
        Coord {
            x: x,
            y: y
        }
    }
}

impl Size {
    /// Create a 2D size of (width, height)
    pub fn new(width: usize, height: usize) -> Size {
        Size {
            width: width,
            height: height
        }
    }

    pub fn area(&self) -> usize {
        self.width * self.height
    }

    /// Return true if the coordinate fits within self's width and
    /// height, false otherwise.
    pub fn contains_coord(&self, coord: Coord) -> bool {
        coord.x < self.width && coord.y < self.height
    }
}

/// Rectangle defined by inclusive minimum and maximum coordinates
#[derive(Clone, Copy, Eq, Debug, PartialEq)]
pub struct Rect {
    /// Minimum coordinate (inclusive)
    min_coord: Coord,

    /// Maximum coordinate (inclusive)
    max_coord: Coord
}

impl Rect {
    /// Calculate rectangle width
    pub fn width(&self) -> usize {
        return self.max_coord.x - self.min_coord.x + 1;
    }

    /// Calculate rectangle height
    pub fn height(&self) -> usize {
        return self.max_coord.y - self.min_coord.y + 1;
    }

    /// Calculate rectangle size
    pub fn size(&self) -> Size {
        Size::new(self.width(), self.height())
    }
}

pub struct Vec2D<T> {
    elems: Vec<T>,
    size: Size
}

impl<Elem: Copy> Vec2D<Elem> {
    pub fn from_example(size: Size, example: &Elem) -> Vec2D<Elem> {
        Vec2D {
            elems: vec![*example; size.area()],
            size: size
        }
    }

    pub fn from_vec(size: Size, src: Vec<Elem>) -> Option<Vec2D<Elem>> {
        if size.area() == src.len() {
            Some(Vec2D {
                elems: src,
                size: size
            })
        }
        else {
            None
        }
    }

    pub fn rect_iter_mut<'a>(&'a mut self, rect: Rect) -> Option<RectIterMut<'a, Elem>> {
        if self.size.contains_coord(rect.max_coord) {
            Some(RectIterMut {
                stride: (self.size.width - rect.width()) as isize,
                cur_elem: self.elems.as_mut_ptr(),
                grid: self,
                rect: rect,
                cur_coord: rect.min_coord
            })
        }
        else {
            None
        }
    }
}

impl<'a, Elem> Iterator for RectIterMut<'a, Elem> {
    type Item = (Coord, &'a mut Elem);

    fn next(&mut self) -> Option<Self::Item> {
        if self.cur_coord.y <= self.rect.max_coord.y {
            let result = (self.cur_coord, unsafe { &mut *self.cur_elem });

            self.cur_coord.x += 1;
            if self.cur_coord.x <= self.rect.max_coord.x {
                unsafe { self.cur_elem.offset(1); }
            }
            else {
                self.cur_coord.x = self.rect.min_coord.x;
                self.cur_coord.y += 1;
                unsafe { self.cur_elem.offset(self.stride); }
            }
            Some(result)
        }
        else {
            None
        }
    }
}

pub struct RectIterMut<'a, Elem: 'a> {
    grid: &'a mut Vec2D<Elem>,
    rect: Rect,
    cur_elem: *mut Elem,
    cur_coord: Coord,
    stride: isize
}

#[test]
fn test_rect_iter_mut() {
    let elems = vec![0, 1, 2, 3];
    let mut grid = Vec2D::from_vec(Size::new(2, 2), elems).unwrap();
    let rect = Rect::new(Coord::new(0, 0), Coord::new(1, 1)).unwrap();

    let mut actual_coords = Vec::new();
    for (coord, elem) in grid.rect_iter_mut(rect).unwrap() {
        *elem = -(*elem);
        actual_coords.push((coord.x, coord.y));
    }
    assert_eq!(actual_coords, [(0, 0), (1, 0), (0, 1), (1, 1)]);
}

impl Rect {
    /// Create a new Rect defined by inclusive minimum and maximum
    /// coordinates. If min_coord is greater than max_coord on either
    /// axis then None is returned.
    pub fn new(min_coord: Coord, max_coord: Coord) -> Option<Rect> {
        if min_coord.x <= max_coord.x && min_coord.y <= max_coord.y {
            Some(Rect {
                min_coord: min_coord,
                max_coord: max_coord
            })
        }
        else {
            None
        }
    }

}
<commit_msg>Update test<commit_after>/// 2D coordinate
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Coord {
    pub x: usize,
    pub y: usize
}

/// 2D dimensions
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Size {
    pub width: usize,
    pub height: usize
}

impl Coord {
    /// Create a coordinate at (x, y)
    pub fn new(x: usize, y: usize) -> Coord {
        Coord {
            x: x,
            y: y
        }
    }
}

impl Size {
    /// Create a 2D size of (width, height)
    pub fn new(width: usize, height: usize) -> Size {
        Size {
            width: width,
            height: height
        }
    }

    pub fn area(&self) -> usize {
        self.width * self.height
    }

    /// Return true if the coordinate fits within self's width and
    /// height, false otherwise.
    pub fn contains_coord(&self, coord: Coord) -> bool {
        coord.x < self.width && coord.y < self.height
    }
}

/// Rectangle defined by inclusive minimum and maximum coordinates
#[derive(Clone, Copy, Eq, Debug, PartialEq)]
pub struct Rect {
    /// Minimum coordinate (inclusive)
    min_coord: Coord,

    /// Maximum coordinate (inclusive)
    max_coord: Coord
}

impl Rect {
    /// Calculate rectangle width
    pub fn width(&self) -> usize {
        return self.max_coord.x - self.min_coord.x + 1;
    }

    /// Calculate rectangle height
    pub fn height(&self) -> usize {
        return self.max_coord.y - self.min_coord.y + 1;
    }

    /// Calculate rectangle size
    pub fn size(&self) -> Size {
        Size::new(self.width(), self.height())
    }
}

pub struct Vec2D<T> {
    elems: Vec<T>,
    size: Size
}

impl<Elem: Copy> Vec2D<Elem> {
    pub fn from_example(size: Size, example: &Elem) -> Vec2D<Elem> {
        Vec2D {
            elems: vec![*example; size.area()],
            size: size
        }
    }

    pub fn from_vec(size: Size, src: Vec<Elem>) -> Option<Vec2D<Elem>> {
        if size.area() == src.len() {
            Some(Vec2D {
                elems: src,
                size: size
            })
        }
        else {
            None
        }
    }

    pub fn rect_iter_mut<'a>(&'a mut self, rect: Rect) -> Option<RectIterMut<'a, Elem>> {
        if self.size.contains_coord(rect.max_coord) {
            Some(RectIterMut {
                stride: (self.size.width - rect.width()) as isize,
                cur_elem: self.elems.as_mut_ptr(),
                grid: self,
                rect: rect,
                cur_coord: rect.min_coord
            })
        }
        else {
            None
        }
    }
}

impl<'a, Elem> Iterator for RectIterMut<'a, Elem> {
    type Item = (Coord, &'a mut Elem);

    fn next(&mut self) -> Option<Self::Item> {
        if self.cur_coord.y <= self.rect.max_coord.y {
            let result = (self.cur_coord, unsafe { &mut *self.cur_elem });

            self.cur_coord.x += 1;
            if self.cur_coord.x <= self.rect.max_coord.x {
                unsafe { self.cur_elem.offset(1); }
            }
            else {
                self.cur_coord.x = self.rect.min_coord.x;
                self.cur_coord.y += 1;
                unsafe { self.cur_elem.offset(self.stride); }
            }
            Some(result)
        }
        else {
            None
        }
    }
}

pub struct RectIterMut<'a, Elem: 'a> {
    grid: &'a mut Vec2D<Elem>,
    rect: Rect,
    cur_elem: *mut Elem,
    cur_coord: Coord,
    stride: isize
}

#[test]
fn test_rect_iter_mut() {
    let elems = vec![1, 2, 3, 4];
    let mut grid = Vec2D::from_vec(Size::new(2, 2), elems).unwrap();
    let rect = Rect::new(Coord::new(0, 0), Coord::new(1, 1)).unwrap();

    let mut actual_coords = Vec::new();
    for (coord, elem) in grid.rect_iter_mut(rect).unwrap() {
        *elem = -(*elem);
        actual_coords.push((coord.x, coord.y));
    }
    assert_eq!(actual_coords, [(0, 0), (1, 0), (0, 1), (1, 1)]);
    assert_eq!(grid.elems, [-1, -2, -3, -4]);
}

impl Rect {
    /// Create a new Rect defined by inclusive minimum and maximum
    /// coordinates. If min_coord is greater than max_coord on either
    /// axis then None is returned.
    pub fn new(min_coord: Coord, max_coord: Coord) -> Option<Rect> {
        if min_coord.x <= max_coord.x && min_coord.y <= max_coord.y {
            Some(Rect {
                min_coord: min_coord,
                max_coord: max_coord
            })
        }
        else {
            None
        }
    }

}
<|endoftext|>


<commit_before>pub mod topic;

pub fn parse_input(s: &str) -> Result<(&str, u8), &str> {
    let mut iter = s.split(",");

    match (iter.next(), iter.next()) {
        (Some(topic), Some(n)) => {
            let num: u8 = match n.trim().parse() {
                Ok(m) => m,
                Err(_) => { return Err("Bad input"); }
            };
            Ok((topic, num))
        },
        _ => Err("Bad input")
    }
}

#[test]
fn should_parse_valid_input() {

    let (topic, num) = parse_input("Dance, 42").unwrap();

    assert_eq!(num, 42);
    assert_eq!(topic, "Dance");
}

#[test]
fn should_fail_to_parse_non_number(){

    let result = parse_input("Comom, Lomom");

    assert_eq!(result, Err("Bad input"));
}

#[test]
fn should_fail_to_parse_missing_comma(){

    let result = parse_input("Toldom Acjdul");

    assert_eq!(result, Err("Bad input"));
}
<commit_msg>EM: refactoring parsing code<commit_after>pub mod topic;

pub fn parse_input(s: &str) -> Result<(&str, u8), &str> {
    let mut iter = s.split(",");
    (match (iter.next(), iter.next()) {
        (Some(topic), Some(n)) => Ok((topic, n)),
        _ => Err("Bad input")
    }).and_then(|(topic, n)| {
        n.trim()
            .parse::<u8>()
            .map(|num| { (topic, num) })
            .or(Err("Bad input"))
    })
}

#[test]
fn should_parse_valid_input() {

    let (topic, num) = parse_input("Dance, 42").unwrap();

    assert_eq!(num, 42);
    assert_eq!(topic, "Dance");
}

#[test]
fn should_fail_to_parse_non_number(){

    let result = parse_input("Comom, Lomom");

    assert_eq!(result, Err("Bad input"));
}

#[test]
fn should_fail_to_parse_missing_comma(){

    let result = parse_input("Toldom Acjdul");

    assert_eq!(result, Err("Bad input"));
}
<|endoftext|>


<commit_before>// (c) 2015 Joost Yervante Damad <joost@damad.be>

// loosely based on https://github.com/cgaebel/sexp
// latest version can be found at https://github.com/andete/rust_sexp

use std::fmt;
use std::str::FromStr;
use std::f64;

use std::fs::File;
use std::io::prelude::*;

pub enum Atom {
  S(String),
  Q(String),
  I(i64),
  F(f64),
}

impl Atom {
    pub fn f(&self) -> Result<f64,String> {
        match *self {
            Atom::F(f) => Ok(f),
            _ => Err(String::from("not a float"))
        }
    }
    pub fn i(&self) -> Result<i64,String> {
        match *self {
            Atom::I(i) => Ok(i),
            _ => Err(String::from("not an int"))
        }
    }
    pub fn string(&self) -> Result<String,String> {
        match *self {
            Atom::S(ref s) => Ok(s.clone()),
            Atom::Q(ref s) => Ok(s.clone()),
            _ => Err(String::from("not a string"))
        }
    }

}

pub enum Sexp {
  Atom(Atom),
  Empty,
  List(Vec<Sexp>),
}

impl Sexp {
    pub fn atom(&self) -> Result<&Atom,String> {
        match *self {
            Sexp::Atom(ref f) => Ok(f),
            _ => Err(String::from("not an atom"))
        }
    }
    pub fn list(&self) -> Result<&Vec<Sexp>,String> {
        match *self {
            Sexp::List(ref v) => Ok(v),
            _ => Err(String::from("not a list"))
        }
    }
}

pub struct ParseError {
    msg: &'static str,
    line: usize,
    lpos: usize,
}

pub enum Error {
    ParseError(ParseError),
    IOError(std::io::Error),
}

pub type ERes<T> = Result<T, Error>;

fn err_parse<T>(msg: &'static str, state: &ParseState) -> ERes<T> {
    Err(Error::ParseError(ParseError { msg: msg, line: state.line, lpos: state.lpos}))
}

fn err_io<T>(err: std::io::Error) -> ERes<T> {
    Err(Error::IOError(err))
}

struct ParseState {
    pos: usize,
    line: usize,
    lpos: usize,
    vec: Vec<char>,
    len: usize,
}

impl ParseState {
    fn peek(&self) -> ERes<char> {
        if self.pos >= self.len {
            return err_parse("end of document reached", self)
        }
        Ok(self.vec[self.pos])
    }
    fn peek_option(&self) -> Option<char> {
        if self.pos >= self.len {
            return None
        }
        Some(self.vec[self.pos])
    }
    fn next(&mut self) -> ERes<()> {
        if self.pos >= self.len {
            return err_parse("end of document reached", self)
        }
        let c = self.vec[self.pos];
        self.pos += 1;
        match c {
            '\r' | '\n' => {
                self.lpos = 0;
                self.line += 1;
            }
            _ => {
                self.lpos += 1;
            }
        }
        Ok(())
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Error::ParseError(ref p) =>
                write!(f, "Parse Error {}:{}: {}", p.line, p.lpos, p.msg),
            Error::IOError(ref i) =>
                write!(f, "{}", i)
        }
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Error::ParseError(ref p) =>
                write!(f, "Parse Error {}:{}: {}", p.line, p.lpos, p.msg),
            Error::IOError(ref i) =>
                write!(f, "{}", i)
        }
    }
}

impl fmt::Display for Atom {
  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
    match *self {
        Atom::S(ref s) => write!(f, "{}", s),
        Atom::Q(ref s) => write!(f, "\"{}\"", s),
        Atom::I(i)     => write!(f, "{}", i),
        Atom::F(d)     => {
            let z = d.floor();
            if d - z < f64::EPSILON {
                write!(f, "{}.0", z)
            } else {
                write!(f, "{}", d)
            }
        }
    }
  }
}

impl fmt::Display for Sexp {
  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
    match *self {
      Sexp::Atom(ref a) => write!(f, "{}", a),
      Sexp::List(ref xs) => {
        try!(write!(f, "("));
        for (i, x) in xs.iter().enumerate() {
          let s = if i == 0 { "" } else { " " };
          try!(write!(f, "{}{}", s, x));
        }
        write!(f, ")")
      },
      Sexp::Empty => write!(f, ""),
    }
  }
}

fn parse_list(state: &mut ParseState) -> ERes<Sexp> {
    //println!("list");
    try!(state.next()); // skip (
    let mut l: Vec<Sexp> = Vec::new();
    loop {
        match try!(state.peek()) {
            ')' => {
                try!(state.next());
                break;
            }
            _ => {
                l.push(try!(parse_sexp(state)));
            }
        }
    }
    //println!("Found list");
    Ok(Sexp::List(l))
}

fn parse_quoted_string(state: &mut ParseState) -> ERes<Atom> {
    //println!("qstring");
    try!(state.next()); // skip "
    let mut s = String::new();
    loop {
        match try!(state.peek()) {
            '"' => {
                try!(state.next());
                break
            }
            x @ '\r' | x @ '\n' => {
                s.push(x);
                try!(state.next());
                }
            x => {
                s.push(x);
                try!(state.next());
            }
        }
    }
    //println!("Found quoted string {}", s);
    Ok(Atom::Q(s))
}

fn parse_string(state: &mut ParseState) -> ERes<Atom> {
    //println!("string");
    let mut s = String::new();
    loop {
        match state.peek_option() {
            Some(x) => {
                match x {
                    ' ' | '\t' | '\r' | '\n' | ')' => break,
                    '"' => return err_parse("unexpected \" in string", state),
                    x => s.push(x),
                }
            }
            None => {
                break;
            }
        }
        try!(state.next())
    }
    //println!("Found string {}", s);
    Ok(Atom::S(s))
}

fn parse_number(state: &mut ParseState) -> ERes<Atom> {
    //println!("number");
    let mut s = String::new();
    loop {
        match state.peek_option() {
            Some(x) => {
                match x {
                    ' ' | '\r' | '\n' | '\t' | ')' => {
                        break
                    },
                    '0' ... '9' | '.' | '-' => {
                        s.push(state.vec[state.pos])
                    },
                    _ => {
                        return err_parse("unexpected char in number", state)
                    },
                }
            }
            None => {
                break
            }
        }
        try!(state.next())
    }
    //println!("Found number {}", s);
    let s2: &str = &s[..];
    if s.contains('.') {
        Ok(Atom::F(f64::from_str(s2).unwrap()))
    } else {
        Ok(Atom::I(i64::from_str(s2).unwrap()))
    }
}

fn parse_atom(state: &mut ParseState) -> ERes<Sexp> {
    //println!("atom");
    let a = match try!(state.peek()) {
        '"' => {
            try!(parse_quoted_string(state))
        }
        '0' ... '9' | '.' | '-' => {
            try!(parse_number(state))
        }
        _ => {
            try!(parse_string(state))
        }
    };
    Ok(Sexp::Atom(a))
}

fn parse_sexp(state: &mut ParseState) -> ERes<Sexp> {
    loop {
        match try!(state.peek()) {
            '(' => {
                return parse_list(state)
            }
            ' ' | '\t' | '\r' | '\n' => {
                try!(state.next());
            }
            ')' => {
                return err_parse("unmatched )", state)
            }
            _ => {
                return parse_atom(state)
            }
        }
    }
}

fn parse(data: &str) -> ERes<Sexp> {
    if data.len() == 0 {
        Ok(Sexp::Empty)
    } else {
        let vec: Vec<char> = data.chars().collect();
        let len = vec.len();
        let state = &mut ParseState { pos: 0, line: 1, lpos: 0, vec: vec, len: len };
        parse_sexp(state)
    }
}

fn read_file(name: &str) -> Result<String, std::io::Error> {
    let mut f = try!(File::open(name));
    let mut s = String::new();
    try!(f.read_to_string(&mut s));
    Ok(s)
}

pub fn parse_str(s: &str) -> ERes<Sexp> {
    parse(s)
}

pub fn parse_file(name: &str) -> ERes<Sexp> {
    let s = try!(match read_file(name) {
        Ok(s) => Ok(s),
        Err(x) => err_io(x),
    });
    parse(&s[..])
}

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

    #[allow(dead_code)]
    fn check_parse(s: &str) {
        let e = parse_str(s).unwrap();
        let t = format!("{}", e);
        assert_eq!(s, t);
    }

    #[allow(dead_code)]
    fn parse_fail(s: &str) {
        parse_str(s).unwrap();
    }

    #[test]
    fn test_empty() { check_parse("") }

    #[test]
    fn test_minimal() { check_parse("()") }

    #[test]
    fn test_string() { check_parse("hello") }

    #[test]
    fn test_qstring() { check_parse("\"hello\"") }

    #[test]
    fn test_number() { check_parse("1.3") }

    #[test]
    fn test_float_vs_int() { check_parse("2.0") }

    #[test]
    fn test_double() { check_parse("(())") }

    #[test]
    fn test_br_string() { check_parse("(world)") }

    #[test]
    fn test_br_qstring() { check_parse("(\"world\")") }

    #[test]
    fn test_br_int() { check_parse("(42)") }

    #[test]
    fn test_br_float() { check_parse("(12.7)") }

    #[test]
    fn test_br_qbrstring() { check_parse("(\"(()\")") }

    #[test]
    #[should_panic(expected="Parse Error 1:1: end of document reached")]
    fn test_invalid1() { parse_fail("(") }

    #[test]
    #[should_panic(expected="Parse Error 1:0: unmatched )")]
    fn test_invalid2() { parse_fail(")") }

    #[test]
    #[should_panic(expected="Parse Error 1:6: end of document reached")]
    fn test_invalid3() { parse_fail("\"hello") }

    #[test]
    fn test_complex() { check_parse("(module SWITCH_3W_SIDE_MMP221-R (layer F.Cu) (descr \"\") (pad 1 thru_hole rect (size 1.2 1.2) (at -2.5 -1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (pad 2 thru_hole rect (size 1.2 1.2) (at 0.0 -1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (pad 3 thru_hole rect (size 1.2 1.2) (at 2.5 -1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (pad 5 thru_hole rect (size 1.2 1.2) (at 0.0 1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (pad 6 thru_hole rect (size 1.2 1.2) (at -2.5 1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (pad 4 thru_hole rect (size 1.2 1.2) (at 2.5 1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (fp_line (start -4.5 -1.75) (end 4.5 -1.75) (layer F.SilkS) (width 0.127)) (fp_line (start 4.5 -1.75) (end 4.5 1.75) (layer F.SilkS) (width 0.127)) (fp_line (start 4.5 1.75) (end -4.5 1.75) (layer F.SilkS) (width 0.127)) (fp_line (start -4.5 1.75) (end -4.5 -1.75) (layer F.SilkS) (width 0.127)))") }
}
<commit_msg>improve error handling<commit_after>// (c) 2015 Joost Yervante Damad <joost@damad.be>

// loosely based on https://github.com/cgaebel/sexp
// latest version can be found at https://github.com/andete/rust_sexp

use std::fmt;
use std::str::FromStr;
use std::f64;

use std::fs::File;
use std::io::prelude::*;

pub enum Atom {
  S(String),
  Q(String),
  I(i64),
  F(f64),
}

impl Atom {
    pub fn f(&self) -> Result<f64,String> {
        match *self {
            Atom::F(f) => Ok(f),
            ref x => Err(format!("not a float: {}", x))
        }
    }
    pub fn i(&self) -> Result<i64,String> {
        match *self {
            Atom::I(i) => Ok(i),
            ref x => Err(format!("not an int: {}", x))
        }
    }
    pub fn string(&self) -> Result<String,String> {
        match *self {
            Atom::S(ref s) => Ok(s.clone()),
            Atom::Q(ref s) => Ok(s.clone()),
            ref x => Err(format!("not a string: {}", x))
        }
    }

}

pub enum Sexp {
  Atom(Atom),
  Empty,
  List(Vec<Sexp>),
}

impl Sexp {
    pub fn atom(&self) -> Result<&Atom,String> {
        match *self {
            Sexp::Atom(ref f) => Ok(f),
            ref x => Err(format!("not an atom: {}", x))
        }
    }
    pub fn list(&self) -> Result<&Vec<Sexp>,String> {
        match *self {
            Sexp::List(ref v) => Ok(v),
            ref x => Err(format!("not a list: {}", x))
        }
    }
}

pub struct ParseError {
    msg: &'static str,
    line: usize,
    lpos: usize,
}

pub enum Error {
    ParseError(ParseError),
    IOError(std::io::Error),
}

pub type ERes<T> = Result<T, Error>;

fn err_parse<T>(msg: &'static str, state: &ParseState) -> ERes<T> {
    Err(Error::ParseError(ParseError { msg: msg, line: state.line, lpos: state.lpos}))
}

fn err_io<T>(err: std::io::Error) -> ERes<T> {
    Err(Error::IOError(err))
}

struct ParseState {
    pos: usize,
    line: usize,
    lpos: usize,
    vec: Vec<char>,
    len: usize,
}

impl ParseState {
    fn peek(&self) -> ERes<char> {
        if self.pos >= self.len {
            return err_parse("end of document reached", self)
        }
        Ok(self.vec[self.pos])
    }
    fn peek_option(&self) -> Option<char> {
        if self.pos >= self.len {
            return None
        }
        Some(self.vec[self.pos])
    }
    fn next(&mut self) -> ERes<()> {
        if self.pos >= self.len {
            return err_parse("end of document reached", self)
        }
        let c = self.vec[self.pos];
        self.pos += 1;
        match c {
            '\r' | '\n' => {
                self.lpos = 0;
                self.line += 1;
            }
            _ => {
                self.lpos += 1;
            }
        }
        Ok(())
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Error::ParseError(ref p) =>
                write!(f, "Parse Error {}:{}: {}", p.line, p.lpos, p.msg),
            Error::IOError(ref i) =>
                write!(f, "{}", i)
        }
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Error::ParseError(ref p) =>
                write!(f, "Parse Error {}:{}: {}", p.line, p.lpos, p.msg),
            Error::IOError(ref i) =>
                write!(f, "{}", i)
        }
    }
}

impl fmt::Display for Atom {
  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
    match *self {
        Atom::S(ref s) => write!(f, "{}", s),
        Atom::Q(ref s) => write!(f, "\"{}\"", s),
        Atom::I(i)     => write!(f, "{}", i),
        Atom::F(d)     => {
            let z = d.floor();
            if d - z < f64::EPSILON {
                write!(f, "{}.0", z)
            } else {
                write!(f, "{}", d)
            }
        }
    }
  }
}

impl fmt::Display for Sexp {
  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
    match *self {
      Sexp::Atom(ref a) => write!(f, "{}", a),
      Sexp::List(ref xs) => {
        try!(write!(f, "("));
        for (i, x) in xs.iter().enumerate() {
          let s = if i == 0 { "" } else { " " };
          try!(write!(f, "{}{}", s, x));
        }
        write!(f, ")")
      },
      Sexp::Empty => write!(f, ""),
    }
  }
}

fn parse_list(state: &mut ParseState) -> ERes<Sexp> {
    //println!("list");
    try!(state.next()); // skip (
    let mut l: Vec<Sexp> = Vec::new();
    loop {
        match try!(state.peek()) {
            ')' => {
                try!(state.next());
                break;
            }
            _ => {
                l.push(try!(parse_sexp(state)));
            }
        }
    }
    //println!("Found list");
    Ok(Sexp::List(l))
}

fn parse_quoted_string(state: &mut ParseState) -> ERes<Atom> {
    //println!("qstring");
    try!(state.next()); // skip "
    let mut s = String::new();
    loop {
        match try!(state.peek()) {
            '"' => {
                try!(state.next());
                break
            }
            x @ '\r' | x @ '\n' => {
                s.push(x);
                try!(state.next());
                }
            x => {
                s.push(x);
                try!(state.next());
            }
        }
    }
    //println!("Found quoted string {}", s);
    Ok(Atom::Q(s))
}

fn parse_string(state: &mut ParseState) -> ERes<Atom> {
    //println!("string");
    let mut s = String::new();
    loop {
        match state.peek_option() {
            Some(x) => {
                match x {
                    ' ' | '\t' | '\r' | '\n' | ')' => break,
                    '"' => return err_parse("unexpected \" in string", state),
                    x => s.push(x),
                }
            }
            None => {
                break;
            }
        }
        try!(state.next())
    }
    //println!("Found string {}", s);
    Ok(Atom::S(s))
}

fn parse_number(state: &mut ParseState) -> ERes<Atom> {
    //println!("number");
    let mut s = String::new();
    loop {
        match state.peek_option() {
            Some(x) => {
                match x {
                    ' ' | '\r' | '\n' | '\t' | ')' => {
                        break
                    },
                    '0' ... '9' | '.' | '-' => {
                        s.push(state.vec[state.pos])
                    },
                    _ => {
                        return err_parse("unexpected char in number", state)
                    },
                }
            }
            None => {
                break
            }
        }
        try!(state.next())
    }
    //println!("Found number {}", s);
    let s2: &str = &s[..];
    if s.contains('.') {
        Ok(Atom::F(f64::from_str(s2).unwrap()))
    } else {
        Ok(Atom::I(i64::from_str(s2).unwrap()))
    }
}

fn parse_atom(state: &mut ParseState) -> ERes<Sexp> {
    //println!("atom");
    let a = match try!(state.peek()) {
        '"' => {
            try!(parse_quoted_string(state))
        }
        '0' ... '9' | '.' | '-' => {
            try!(parse_number(state))
        }
        _ => {
            try!(parse_string(state))
        }
    };
    Ok(Sexp::Atom(a))
}

fn parse_sexp(state: &mut ParseState) -> ERes<Sexp> {
    loop {
        match try!(state.peek()) {
            '(' => {
                return parse_list(state)
            }
            ' ' | '\t' | '\r' | '\n' => {
                try!(state.next());
            }
            ')' => {
                return err_parse("unmatched )", state)
            }
            _ => {
                return parse_atom(state)
            }
        }
    }
}

fn parse(data: &str) -> ERes<Sexp> {
    if data.len() == 0 {
        Ok(Sexp::Empty)
    } else {
        let vec: Vec<char> = data.chars().collect();
        let len = vec.len();
        let state = &mut ParseState { pos: 0, line: 1, lpos: 0, vec: vec, len: len };
        parse_sexp(state)
    }
}

fn read_file(name: &str) -> Result<String, std::io::Error> {
    let mut f = try!(File::open(name));
    let mut s = String::new();
    try!(f.read_to_string(&mut s));
    Ok(s)
}

pub fn parse_str(s: &str) -> ERes<Sexp> {
    parse(s)
}

pub fn parse_file(name: &str) -> ERes<Sexp> {
    let s = try!(match read_file(name) {
        Ok(s) => Ok(s),
        Err(x) => err_io(x),
    });
    parse(&s[..])
}

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

    #[allow(dead_code)]
    fn check_parse(s: &str) {
        let e = parse_str(s).unwrap();
        let t = format!("{}", e);
        assert_eq!(s, t);
    }

    #[allow(dead_code)]
    fn parse_fail(s: &str) {
        parse_str(s).unwrap();
    }

    #[test]
    fn test_empty() { check_parse("") }

    #[test]
    fn test_minimal() { check_parse("()") }

    #[test]
    fn test_string() { check_parse("hello") }

    #[test]
    fn test_qstring() { check_parse("\"hello\"") }

    #[test]
    fn test_number() { check_parse("1.3") }

    #[test]
    fn test_float_vs_int() { check_parse("2.0") }

    #[test]
    fn test_double() { check_parse("(())") }

    #[test]
    fn test_br_string() { check_parse("(world)") }

    #[test]
    fn test_br_qstring() { check_parse("(\"world\")") }

    #[test]
    fn test_br_int() { check_parse("(42)") }

    #[test]
    fn test_br_float() { check_parse("(12.7)") }

    #[test]
    fn test_br_qbrstring() { check_parse("(\"(()\")") }

    #[test]
    #[should_panic(expected="Parse Error 1:1: end of document reached")]
    fn test_invalid1() { parse_fail("(") }

    #[test]
    #[should_panic(expected="Parse Error 1:0: unmatched )")]
    fn test_invalid2() { parse_fail(")") }

    #[test]
    #[should_panic(expected="Parse Error 1:6: end of document reached")]
    fn test_invalid3() { parse_fail("\"hello") }

    #[test]
    fn test_complex() { check_parse("(module SWITCH_3W_SIDE_MMP221-R (layer F.Cu) (descr \"\") (pad 1 thru_hole rect (size 1.2 1.2) (at -2.5 -1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (pad 2 thru_hole rect (size 1.2 1.2) (at 0.0 -1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (pad 3 thru_hole rect (size 1.2 1.2) (at 2.5 -1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (pad 5 thru_hole rect (size 1.2 1.2) (at 0.0 1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (pad 6 thru_hole rect (size 1.2 1.2) (at -2.5 1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (pad 4 thru_hole rect (size 1.2 1.2) (at 2.5 1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (fp_line (start -4.5 -1.75) (end 4.5 -1.75) (layer F.SilkS) (width 0.127)) (fp_line (start 4.5 -1.75) (end 4.5 1.75) (layer F.SilkS) (width 0.127)) (fp_line (start 4.5 1.75) (end -4.5 1.75) (layer F.SilkS) (width 0.127)) (fp_line (start -4.5 1.75) (end -4.5 -1.75) (layer F.SilkS) (width 0.127)))") }
}
<|endoftext|>


<commit_before>//! ### Transport agnostic jsonrpc library.
//!
//! Right now it supports only server side handling requests.
//!
//! ```rust
//! extern crate jsonrpc_core;
//!
//! use jsonrpc_core::*;
//!
//! struct SayHello;
//! impl SyncMethodCommand for SayHello {
//!     fn execute(&self, _params: Params) -> Result<Value, Error> {
//!         Ok(Value::String("hello".to_string()))
//!     }
//! }
//!
//! struct SayHelloAsync;
//! impl MethodCommand for SayHelloAsync {
//!		fn execute(&self, _params: Params, ready: Ready) {
//!			ready.ready(Ok(Value::String("hello".to_string())))
//!		}
//! }
//!
//! fn main() {
//! 	let io = IoHandler::new();
//! 	io.add_method("say_hello", SayHello);
//! 	io.add_async_method("say_hello_async", SayHelloAsync);
//!
//! 	let request = r#"{"jsonrpc": "2.0", "method": "say_hello", "params": [42, 23], "id": 1}"#;
//! 	let request2 = r#"{"jsonrpc": "2.0", "method": "say_hello_async", "params": [42, 23], "id": 1}"#;
//! 	let response = r#"{"jsonrpc":"2.0","result":"hello","id":1}"#;
//!
//! 	assert_eq!(io.handle_request_sync(request), Some(response.to_string()));
//! 	assert_eq!(io.handle_request_sync(request2), Some(response.to_string()));
//! }
//! ```

#![warn(missing_docs)]
#![cfg_attr(feature="nightly", feature(custom_derive, plugin))]
#![cfg_attr(feature="nightly", plugin(serde_macros))]

extern crate serde;
extern crate serde_json;
extern crate parking_lot;
#[macro_use] extern crate log;

// pub mod async;
pub mod control;
pub mod commander;
pub mod request_handler;
pub mod io;

pub use self::control::*;
pub use self::commander::{Commander, MethodCommand, SyncMethodCommand, NotificationCommand, SubscriptionCommand};
pub use self::request_handler::RequestHandler;
pub use self::io::{IoHandler, IoDelegate};

#[cfg(feature = "serde_macros")]
include!("lib.rs.in");

#[cfg(not(feature = "serde_macros"))]
include!(concat!(env!("OUT_DIR"), "/lib.rs"));
<commit_msg>Exposing IoSession<commit_after>//! ### Transport agnostic jsonrpc library.
//!
//! Right now it supports only server side handling requests.
//!
//! ```rust
//! extern crate jsonrpc_core;
//!
//! use jsonrpc_core::*;
//!
//! struct SayHello;
//! impl SyncMethodCommand for SayHello {
//!     fn execute(&self, _params: Params) -> Result<Value, Error> {
//!         Ok(Value::String("hello".to_string()))
//!     }
//! }
//!
//! struct SayHelloAsync;
//! impl MethodCommand for SayHelloAsync {
//!		fn execute(&self, _params: Params, ready: Ready) {
//!			ready.ready(Ok(Value::String("hello".to_string())))
//!		}
//! }
//!
//! fn main() {
//! 	let io = IoHandler::new();
//! 	io.add_method("say_hello", SayHello);
//! 	io.add_async_method("say_hello_async", SayHelloAsync);
//!
//! 	let request = r#"{"jsonrpc": "2.0", "method": "say_hello", "params": [42, 23], "id": 1}"#;
//! 	let request2 = r#"{"jsonrpc": "2.0", "method": "say_hello_async", "params": [42, 23], "id": 1}"#;
//! 	let response = r#"{"jsonrpc":"2.0","result":"hello","id":1}"#;
//!
//! 	assert_eq!(io.handle_request_sync(request), Some(response.to_string()));
//! 	assert_eq!(io.handle_request_sync(request2), Some(response.to_string()));
//! }
//! ```

#![warn(missing_docs)]
#![cfg_attr(feature="nightly", feature(custom_derive, plugin))]
#![cfg_attr(feature="nightly", plugin(serde_macros))]

extern crate serde;
extern crate serde_json;
extern crate parking_lot;
#[macro_use] extern crate log;

// pub mod async;
pub mod control;
pub mod commander;
pub mod request_handler;
pub mod io;

pub use self::control::*;
pub use self::commander::{Commander, MethodCommand, SyncMethodCommand, NotificationCommand, SubscriptionCommand};
pub use self::request_handler::RequestHandler;
pub use self::io::{IoHandler, IoDelegate, IoSession};

#[cfg(feature = "serde_macros")]
include!("lib.rs.in");

#[cfg(not(feature = "serde_macros"))]
include!(concat!(env!("OUT_DIR"), "/lib.rs"));
<|endoftext|>


<commit_before>#![feature(collections,vec_push_all)]

extern crate unicode_segmentation;
use unicode_segmentation::UnicodeSegmentation;

use std::rc::Rc;

const SPLIT_LEN: usize = 10;
const JOIN_LEN: usize = 5;
const REBALANCE_RATIO: f32 = 1.2;

struct Leaf {
    base: Rc<String>,
    start: usize,
    end: usize,
    graphemes: usize,
}
impl Leaf {
    /// Create a new Leaf from a String
    fn from_string(base: &str) -> Leaf {
        let base = String::from_str(base);
        let (start, end) = (0, base.len());
        Leaf::new(Rc::new(base), start, end)
    }
    /// Create a new Leaf
    /// This works like a Slice of the base String; base[start..end]
    fn new(base: Rc<String>, start: usize, end: usize) -> Leaf {
        let graphemes = UnicodeSegmentation::graphemes(&base[start..end], true).collect::<Vec<&str>>().len();
        Leaf { base: base, start: start, end: end, graphemes: graphemes }
    }
    /// Split a Leaf after the nth grapheme
    /// Panics if the grapheme index is out of range
    fn split(&self, grapheme_index: usize) -> (Rope, Rope) {
        let byte_index = UnicodeSegmentation::grapheme_indices(&self.base[self.start..self.end], true)
            .nth(grapheme_index).unwrap().0;
        let left = Leaf::new(self.base.clone(), self.start, self.start + byte_index);
        let right = Leaf::new(self.base.clone(), self.start + byte_index, self.end);
        (Rope::Leaf(left), Rope::Leaf(right))
    }
    /// Gets the number of Unicode grapheme clusters in this leaf
    fn num_graphemes(&self) -> usize {
        self.graphemes
    }
    /// Returns a &str of this Leafs contents
    fn to_str(&self) -> &str {
        &self.base[self.start..self.end]
    }
}
impl Clone for Leaf {
    fn clone(&self) -> Leaf {
        Leaf { base: self.base.clone(),
               start: self.start,
               end: self.end,
               graphemes: self.graphemes }
    }
}

struct Concat {
    left: Rope,
    right: Rope,
    graphemes: usize,
}
impl Concat {
    /// Join two Ropes
    fn new(left: &Rope, right: &Rope) -> Concat {
        let graphemes = left.num_graphemes() + right.num_graphemes();
        Concat { left: left.clone(), right: right.clone(), graphemes: graphemes }
    }

    /// Split a Rope after the nth grapheme
    fn split(&self, grapheme_index: usize) -> (Rope, Rope) {
        // if self is (a, b)
        // find out if the index is in the left or right child
        if self.left.num_graphemes() >= grapheme_index {
            // split a into (a1, a2), return ( a1, concat(a2, b) )
            let (a1, a2) = self.left.split(grapheme_index);
            return (a1, Rope::Concat(Rc::new(Concat::new(&a2, &self.right))));
        } else {
            // split b into (b1, b2), return ( concat(a, b1), b2 )
            let (b1, b2) = self.right.split(grapheme_index - self.left.num_graphemes());
            return (Rope::Concat(Rc::new(Concat::new(&self.left, &b1))), b2);
        }
    }

    /// Gets the number of Unicode grapheme clusters in the children of this node
    fn num_graphemes(&self) -> usize {
        self.graphemes
    }
}
impl Clone for Concat {
    fn clone(&self) -> Concat {
        Concat { left: self.left.clone(),
                 right: self.right.clone(),
                 graphemes: self.graphemes }
    }
}

enum Rope {
    Leaf(Leaf),
    Concat(Rc<Concat>),
}
impl Rope {
    /// Create a new Rope
    fn from_string(base: &str) -> Rope {
        Rope::Leaf(Leaf::from_string(base))
    }
    /// Gets the number of Unicode grapheme clusters in the children of this node
    fn num_graphemes(&self) -> usize {
        match *self {
            Rope::Leaf(ref leaf) => leaf.num_graphemes(),
            Rope::Concat(ref concat) => concat.num_graphemes(),
        }
    }
    /// Split a Rope after the nth grapheme
    fn split(&self, grapheme_index: usize) -> (Rope, Rope) {
        match *self {
            Rope::Leaf(ref leaf) => leaf.split(grapheme_index),
            Rope::Concat(ref concat) => concat.split(grapheme_index),
        }
    }
    /// Collect the pieces of this Rope into a continuous String
    fn to_string(&self) -> String {
        let mut buf = String::with_capacity(self.num_graphemes());

        fn str_parts<'a>(root: &'a Rope) -> Vec<&'a str> {
            let mut v = vec![];
            match *root {
                Rope::Leaf(ref leaf) => {
                    v.push(leaf.to_str());
                },
                Rope::Concat(ref concat) => {
                    v.push_all(&str_parts(&concat.left));
                    v.push_all(&str_parts(&concat.right));
                },
            }
            v
        }
        for part in str_parts(self).iter() {
            buf.push_str(part);
        }

        buf
    }
    /// Join two pieces into a Rope
    fn join(left: &Rope, right: &Rope) -> Rope {
        Rope::Concat(Rc::new(Concat::new(left, right)))
    }
    /// Insert a string into a Rope by splitting and joining nodes
    /// Returns a new Rope, leaving the original unchanged
    fn insert(&self, grapheme_index: usize, value: &str) -> Rope {
        let (left, right) = self.split(grapheme_index);
        let left = Rope::join(&left, &Rope::from_string(value));
        Rope::join(&left, &right)
    }

}
impl Clone for Rope {
    fn clone(&self) -> Rope {
        match *self {
            Rope::Leaf(ref leaf) => Rope::Leaf(leaf.clone()),
            Rope::Concat(ref concat) => Rope::Concat(concat.clone()),
        }
    }
}

/// Count the number of unicode extended grapheme clusters in a string
/// This is O(n)
fn count_clusters(s: &str) -> usize {
    UnicodeSegmentation::graphemes(s, true).collect::<Vec<&str>>().len()
}

#[test]
fn test_count_clusters() {
    // 11 bytes, 3 grapheme clusters
    let s = "a̐éö̲";
    assert_eq!(s.len(), 11);
    assert_eq!(count_clusters(s), 3);
}

#[test]
fn test_create_leaf() {
    let base = "a̐éö̲";
    let leaf = Leaf::from_string(base);
    assert_eq!(leaf.num_graphemes(), 3);
}

#[test]
fn test_split_leaf() {
    let base = "a̐éö̲a̐éö̲";
    let leaf = Leaf::from_string(base);
    let (left, right) = leaf.split(3);
    assert_eq!(left.num_graphemes(), right.num_graphemes());
    assert_eq!(left.to_string(), "a̐éö̲");
}

#[test]
fn test_create_rope() {
    let rope = Rope::from_string("The quick brown fox jumps over the lazy dog.");

    assert_eq!(rope.num_graphemes(), 44);
    assert_eq!(rope.to_string(), "The quick brown fox jumps over the lazy dog.");
}

#[test]
fn test_rope_operations() {
    let rope = Rope::from_string("The quick brown fox jumps over the lazy dog.");

    let (left, right) = rope.split(22);
    assert_eq!(left.to_string(), "The quick brown fox ju");
    assert_eq!(right.to_string(), "mps over the lazy dog.");

    let rope = Rope::join(&left, &Rope::from_string("mps over the tiny wooden fence!"));
    assert_eq!(rope.to_string(), "The quick brown fox jumps over the tiny wooden fence!");

    let rope2 = rope.insert(10, "(and really very clever) ");
    assert_eq!(rope2.to_string(), "The quick (and really very clever) brown fox jumps over the tiny wooden fence!");
}
<commit_msg>Refactor<commit_after>#![feature(vec_push_all)]

extern crate unicode_segmentation;
use unicode_segmentation::UnicodeSegmentation;

use std::rc::Rc;

// const SPLIT_LEN: usize = 10;
// const JOIN_LEN: usize = 5;
// const REBALANCE_RATIO: f32 = 1.2;

pub enum Rope {
    Leaf { base: Rc<String>,
           start: usize,
           end: usize,
           graphemes: usize },
    Concat { left: Rc<Rope>,
             right: Rc<Rope>,
             graphemes: usize },
}
impl Rope {
    /// Create a new rope leaf
    pub fn from_str(base: &str) -> Rope {
        let num_graphemes = count_grapheme_clusters(base);
        Rope::Leaf { base: Rc::new(String::from(base)),
                     start: 0,
                     end: base.len(),
                     graphemes: num_graphemes }
    }
    /// Gets the number of Unicode grapheme clusters in the children of this node
    pub fn num_graphemes(&self) -> usize {
        match *self {
            Rope::Leaf { graphemes, .. } => graphemes,
            Rope::Concat { graphemes, .. } => graphemes,
        }
    }
    /// Split a Rope after the nth grapheme
    pub fn split(&self, grapheme_index: usize) -> Option<(Rope, Rope)> {
        match *self {
            Rope::Leaf { ref base, start, end, .. } => {
                grapheme_byte_index(&base[start..end], grapheme_index)
                    .map(|byte_index| {
                        let left = Rope::Leaf { base: base.clone(),
                                                start: start,
                                                end: start+byte_index,
                                                graphemes: count_grapheme_clusters(&base[start..start+byte_index]) };
                        let right = Rope::Leaf { base: base.clone(),
                                                 start: start+byte_index,
                                                 end: end,
                                                 graphemes: count_grapheme_clusters(&base[start+byte_index..end]) };
                        (left, right)
                    })
            },
            Rope::Concat{ ref left, ref right, .. } => {
                // self is (left, right)
                if left.num_graphemes() >= grapheme_index {
                    // split left into (l1, l2), return (l1, concat(l2, right))
                    left.split(grapheme_index).map(|(l1, l2)| {
                        (l1, Rope::Concat { left: Rc::new(l2.clone()),
                                            right: right.clone(),
                                            graphemes: l2.num_graphemes() + right.num_graphemes() })
                    })
                } else {
                    // split right into (r1, r2), return (concat(left, r1), r2)
                    right.split(grapheme_index - left.num_graphemes()).map(|(r1, r2)| {
                        (Rope::Concat { left: left.clone(),
                                        right: Rc::new(r1.clone()),
                                        graphemes: left.num_graphemes() + r1.num_graphemes() },
                         r2)
                    })
                }
            }
        }
    }
    /// Collect the pieces of this Rope into a continuous String
    pub fn to_string(&self) -> String {
        let mut buf = String::with_capacity(self.num_graphemes());

        fn str_parts<'a>(root: &'a Rope) -> Vec<&'a str> {
            let mut v = vec![];
            match *root {
                Rope::Leaf { ref base, start, end, .. } => {
                    v.push( &base[start..end] );
                },
                Rope::Concat { ref left, ref right, .. } => {
                    v.push_all(&str_parts(&left));
                    v.push_all(&str_parts(&right));
                },
            }
            v
        }
        for part in str_parts(self).iter() {
            buf.push_str(part);
        }

        buf
    }
    /// Join two pieces into a Rope
    pub fn join(left: Rope, right: Rope) -> Rope {
        let graphemes = left.num_graphemes() + right.num_graphemes();
        Rope::Concat { left: Rc::new(left),
                       right: Rc::new(right),
                       graphemes: graphemes }
    }
    /// Insert a string into a Rope by splitting and joining nodes
    /// Returns a new Rope, leaving the original unchanged
    pub fn insert(&self, grapheme_index: usize, value: &str) -> Option<Rope> {
        self.split(grapheme_index).map(|(left, right)| {
            let left = Rope::join(left, Rope::from_str(value));
            Rope::join(left, right)
        })
    }
}
impl Clone for Rope {
    fn clone(&self) -> Rope {
        match *self {
            Rope::Leaf { ref base, start, end, graphemes } => Rope::Leaf { base: base.clone(),
                                                                           start: start,
                                                                           end: end,
                                                                           graphemes: graphemes },
            Rope::Concat { ref left, ref right, graphemes } => Rope::Concat { left: left.clone(),
                                                                              right: right.clone(),
                                                                              graphemes: graphemes },
        }
    }
}
/// Count the number of unicode extended grapheme clusters in a string
/// This is O(n)
fn count_grapheme_clusters(s: &str) -> usize {
    UnicodeSegmentation::graphemes(s, true).collect::<Vec<&str>>().len()
}

/// Find the byte index of the nth grapheme cluster in a string
/// Returns None if the grapheme index is out of bounds
fn grapheme_byte_index(base: &str, nth_grapheme: usize) -> Option<usize> {
    UnicodeSegmentation::grapheme_indices(base, true)
        .nth(nth_grapheme).map(|(i, _)| i)
}

#[test]
fn test_count_grapheme_clusters() {
    // 11 bytes, 3 grapheme clusters
    let s = "a̐éö̲";
    assert_eq!(s.len(), 11);
    assert_eq!(count_grapheme_clusters(s), 3);
}

#[test]
fn test_create_leaf() {
    let leaf = Rope::from_str("a̐éö̲");
    assert_eq!(leaf.num_graphemes(), 3);
}

#[test]
fn test_split_leaf() {
    let leaf = Rope::from_str("a̐éö̲a̐éö̲");
    let (left, right) = leaf.split(3).unwrap();
    assert_eq!(left.num_graphemes(), right.num_graphemes());
    assert_eq!(left.to_string(), "a̐éö̲");
}

#[test]
fn test_create_rope() {
    let rope = Rope::from_str("The quick brown fox jumps over the lazy dog.");
    assert_eq!(rope.num_graphemes(), 44);
    assert_eq!(rope.to_string(), "The quick brown fox jumps over the lazy dog.");
}

#[test]
fn test_rope_operations() {
    let rope = Rope::from_str("The quick brown fox jumps over the lazy dog.");

    let (left, right) = rope.split(22).unwrap();
    assert_eq!(left.to_string(), "The quick brown fox ju");
    assert_eq!(right.to_string(), "mps over the lazy dog.");

    let rope = Rope::join(left, Rope::from_str("mps over the tiny wooden fence!"));
    assert_eq!(rope.to_string(), "The quick brown fox jumps over the tiny wooden fence!");

    let rope2 = rope.insert(10, "(and really very clever) ").unwrap();
    assert_eq!(rope2.to_string(), "The quick (and really very clever) brown fox jumps over the tiny wooden fence!");
}
<|endoftext|>