<commit_before>//!Server configuration and instance.

#![stable]

use std;
use std::collections::HashMap;
use std::sync::RwLock;
use std::old_io::net::ip::{IpAddr, Ipv4Addr, Port};
use std::borrow::ToOwned;

use time::{self, Timespec};

use url::percent_encoding::lossy_utf8_percent_decode;

use hyper;
use hyper::server::Handler as HyperHandler;
use hyper::header::{Headers, Date, ContentType, ContentLength};
use hyper::mime::Mime;
use hyper::uri::RequestUri;

pub use hyper::server::Listening;

use StatusCode;

use context::{self, Context};
use plugin::{ContextPlugin, ContextAction, ResponsePlugin};
use router::Router;
use cache::Cache;
use handler::Handler;
use response::Response;
use log::{Log, StdOut};
use Protocol;

use utils;

///Used to build and run a server.
///
///Each field has a corresponding modifier method and
///calls to these methods can be chained for quick setup.
///
///```no_run
///# use std::error::Error;
///# use rustful::{Server, Handler, Context, Response};
///# struct R;
///# impl Handler for R {
///#     type Cache = ();
///#     fn handle_request(&self, _context: Context, _response: Response) {}
///# }
///# let router = R;
///let server_result = Server::new().port(8080).handlers(router).run();
///
///match server_result {
///    Ok(_server) => {},
///    Err(e) => println!("could not start server: {}", e.description())
///}
///```
pub struct Server<R, C> {
    ///One or several response handlers.
    pub handlers: R,

    ///The port where the server will listen for requests.
    pub port: Port,

    ///The host address where the server will listen for requests.
    pub host: IpAddr,

    ///The type of HTTP protocol.
    pub protocol: Protocol,

    ///The number of threads to be used in the server task pool.
    ///The default (`None`) is based on recommendations from the system.
    pub threads: Option<usize>,

    ///The content of the server header.
    pub server: String,

    ///The default media type.
    pub content_type: Mime,

    ///A structure where resources are cached.
    pub cache: C,

    ///How often the cache should be cleaned. Measured in seconds.
    pub cache_clean_interval: Option<i64>,

    ///Tool for printing to a log.
    pub log: Box<Log + Send + Sync>,

    ///The context plugin stack.
    #[unstable]
    pub context_plugins: Vec<Box<ContextPlugin<Cache=C> + Send + Sync>>,

    ///The response plugin stack.
    #[unstable]
    pub response_plugins: Vec<Box<ResponsePlugin + Send + Sync>>
}

impl Server<(), ()> {
    ///Create a new empty server which will listen on host address `0.0.0.0` and port `80`.
    pub fn new() -> Server<(), ()> {
        Server::with_cache(())
    }
}

impl<C: Cache> Server<(), C> {
    ///Create a new empty server with a cache.
    pub fn with_cache(cache: C) -> Server<(), C> {
        Server {
            handlers: (),
            port: 80,
            host: Ipv4Addr(0, 0, 0, 0),
            protocol: Protocol::Http,
            threads: None,
            server: "rustful".to_owned(),
            content_type: Mime(
                hyper::mime::TopLevel::Text,
                hyper::mime::SubLevel::Plain,
                vec![(hyper::mime::Attr::Charset, hyper::mime::Value::Utf8)]
            ),
            cache: cache,
            cache_clean_interval: None,
            log: Box::new(StdOut) as Box<Log + Send + Sync>,
            context_plugins: Vec::new(),
            response_plugins: Vec::new()
        }
    }
}

impl<R, C> Server<R, C> {
    ///Set request handlers.
    pub fn handlers<NewRouter: Router<Handler=H>, H: Handler<Cache=C>>(self, handlers: NewRouter) -> Server<NewRouter, C> {
        Server {
            handlers: handlers,
            port: self.port,
            host: self.host,
            protocol: self.protocol,
            threads: self.threads,
            server: self.server,
            content_type: self.content_type,
            cache: self.cache,
            cache_clean_interval: self.cache_clean_interval,
            log: self.log,
            context_plugins: self.context_plugins,
            response_plugins: self.response_plugins,
        }
    }

    ///Change the port. Default is `80`.
    pub fn port(mut self, port: Port) -> Server<R, C> {
        self.port = port;
        self
    }

    ///Change the host address. Default is `0.0.0.0`.
    pub fn host(mut self, host: IpAddr) -> Server<R, C> {
        self.host = host;
        self
    }

    ///Change the protocol to HTTPS.
    pub fn https(mut self, cert: Path, key: Path) -> Server<R, C> {
        self.protocol = Protocol::Https {
            cert: cert,
            key: key
        };
        self
    }

    ///Set the number of threads to be used in the server task pool.
    ///
    ///Passing `None` will set it to the default number of threads,
    ///based on recommendations from the system.
    pub fn threads(mut self, threads: Option<usize>) -> Server<R, C> {
        self.threads = threads;
        self
    }

    ///Set the minimal number of seconds between each cache clean.
    ///
    ///Passing `None` disables cache cleaning.
    pub fn cache_clean_interval(mut self, interval: Option<u32>) -> Server<R, C> {
        self.cache_clean_interval = interval.map(|i| i as i64);
        self
    }

    ///Change the server response header. Default is `rustful`.
    pub fn server_name(mut self, name: String) -> Server<R, C> {
        self.server = name;
        self
    }

    ///Change the default content type. Default is `text/plain`.
    pub fn content_type(mut self, content_type: Mime) -> Server<R, C> {
        self.content_type = content_type;
        self
    }

    ///Change log tool. Default is to print to standard output.
    pub fn log<L: Log + Send + Sync>(mut self, log: L) -> Server<R, C> {
        self.log = Box::new(log) as Box<Log + Send + Sync>;
        self
    }

    ///Add a context plugin to the plugin stack.
    #[unstable]
    pub fn with_context_plugin<P: ContextPlugin<Cache=C> + Send + Sync>(mut self, plugin: P) ->  Server<R, C> {
        self.context_plugins.push(Box::new(plugin) as Box<ContextPlugin<Cache=C> + Send + Sync>);
        self
    }

    ///Add a response plugin to the plugin stack.
    #[unstable]
    pub fn with_response_plugin<P: ResponsePlugin + Send + Sync>(mut self, plugin: P) ->  Server<R, C> {
        self.response_plugins.push(Box::new(plugin) as Box<ResponsePlugin + Send + Sync>);
        self
    }
}

impl<R, H, C> Server<R, C>
    where
    R: Router<Handler=H> + Send + Sync,
    H: Handler<Cache=C> + Send + Sync,
    C: Cache + Send + Sync
{
    ///Start the server.
    pub fn run(self) -> hyper::HttpResult<Listening> {
        let threads = self.threads;
        let (server, protocol) = self.build();
        let http = match protocol {
            Protocol::Http => hyper::server::Server::http(server.host, server.port),
            Protocol::Https {cert, key} => hyper::server::Server::https(server.host, server.port, cert, key)
        };

        match threads {
            Some(threads) => http.listen_threads(server, threads),
            None => http.listen(server)
        }
    }

    ///Build a runnable instance of the server.
    pub fn build(self) -> (ServerInstance<R, C>, Protocol) {
        (ServerInstance {
            handlers: self.handlers,
            port: self.port,
            host: self.host,
            server: self.server,
            content_type: self.content_type,
            cache: self.cache,
            cache_clean_interval: self.cache_clean_interval,
            last_cache_clean: RwLock::new(Timespec::new(0, 0)),
            log: self.log,
            context_plugins: self.context_plugins,
            response_plugins: self.response_plugins,
        },
        self.protocol)
    }
}

///A runnable instance of a server.
///
///It's not meant to be used directly,
///unless additional control is required.
///
///```no_run
///# use rustful::{Server, Handler, Context, Response};
///# struct R;
///# impl Handler for R {
///#     type Cache = ();
///#     fn handle_request(&self, _context: Context, _response: Response) {}
///# }
///# let router = R;
///let (server_instance, protocol) = Server::new().port(8080).handlers(router).build();
///```
pub struct ServerInstance<R, C> {
    handlers: R,

    port: Port,
    host: IpAddr,

    server: String,
    content_type: Mime,

    cache: C,
    cache_clean_interval: Option<i64>,
    last_cache_clean: RwLock<Timespec>,

    log: Box<Log + Send + Sync>,

    context_plugins: Vec<Box<ContextPlugin<Cache=C> + Send + Sync>>,
    response_plugins: Vec<Box<ResponsePlugin + Send + Sync>>
}

impl<R, C: Cache> ServerInstance<R, C> {

    fn modify_context(&self, context: &mut Context<C>) -> ContextAction {
        let mut result = ContextAction::Continue;

        for plugin in &self.context_plugins {
            result = match result {
                ContextAction::Continue => plugin.modify(&*self.log, context),
                _ => return result
            };
        }

        result
    }

}

impl<R, H, C> HyperHandler for ServerInstance<R, C>
    where
    R: Router<Handler=H> + Send + Sync,
    H: Handler<Cache=C> + Send + Sync,
    C: Cache + Send + Sync,
{
    fn handle(&self, mut request: hyper::server::request::Request, writer: hyper::server::response::Response) {
        let request_uri = request.uri.clone();
        let request_method = request.method.clone();
        let mut request_headers = Headers::new();
        std::mem::swap(&mut request_headers, &mut request.headers);

        let mut response = Response::new(writer, &self.response_plugins, &*self.log);
        response.set_header(Date(time::now_utc()));
        response.set_header(ContentType(self.content_type.clone()));
        response.set_header(hyper::header::Server(self.server.clone()));

        let path_components = match request_uri {
            RequestUri::AbsoluteUri(url) => {
                Some((
                    url.serialize_path().map(|p| p.into_bytes()).unwrap_or_else(|| vec!['/' as u8]),
                    url.query_pairs().unwrap_or_else(|| Vec::new()).into_iter().collect(),
                    url.fragment
                ))
            },
            RequestUri::AbsolutePath(path) => {
                let (path, query, fragment) = parse_path(path);
                Some((path.into_bytes(), query, fragment))
            },
            _ => None //TODO: Handle *
        };

        match path_components {
            Some((path, query, fragment)) => {

                let mut context = Context {
                    headers: request_headers,
                    method: request_method,
                    path: lossy_utf8_percent_decode(&path),
                    variables: HashMap::new(),
                    query: query,
                    fragment: fragment,
                    cache: &self.cache,
                    log: &*self.log,
                    body_reader: context::BodyReader::from_request(request)
                };

                match self.modify_context(&mut context) {
                    ContextAction::Continue => {
                        match self.handlers.find(&context.method, &context.path) {
                            Some((handler, variables)) => {
                                context.variables = variables;
                                handler.handle_request(context, response);
                            },
                            None => {
                                response.set_header(ContentLength(0));
                                response.set_status(StatusCode::NotFound);
                            }
                        }
                    },
                    ContextAction::Abort(status) => {
                        response.set_header(ContentLength(0));
                        response.set_status(status);
                    }
                }
            },
            None => {
                response.set_header(ContentLength(0));
                response.set_status(StatusCode::BadRequest);
            }
        }

        self.cache_clean_interval.map(|t| {
            let clean_time = {
                let last_cache_clean = self.last_cache_clean.read().unwrap();
                Timespec::new(last_cache_clean.sec + t, last_cache_clean.nsec)
            };

            if time::get_time() > clean_time {
                *self.last_cache_clean.write().unwrap() = time::get_time();
                self.cache.free_unused(&*self.log);
            }
        });
    }
}

fn parse_path(path: String) -> (String, HashMap<String, String>, Option<String>) {
    match path.find('?') {
        Some(index) => {
            let (query, fragment) = parse_fragment(&path[index+1..]);
            (path[..index].to_owned(), utils::parse_parameters(query.as_bytes()), fragment.map(|f| f.to_owned()))
        },
        None => {
            let (path, fragment) = parse_fragment(&path);
            (path.to_owned(), HashMap::new(), fragment.map(|f| f.to_owned()))
        }
    }
}

fn parse_fragment<'a>(path: &'a str) -> (&'a str, Option<&'a str>) {
    match path.find('#') {
        Some(index) => (&path[..index], Some(&path[index+1..])),
        None => (path, None)
    }
}

#[test]
fn parse_path_parts() {
    let with = "this".to_owned();
    let and = "that".to_owned();
    let (path, query, fragment) = parse_path(String::from_str("/path/to/something?with=this&and=that#lol"));
    assert_eq!(path, String::from_str("/path/to/something"));
    assert_eq!(query.get("with"), Some(&with));
    assert_eq!(query.get("and"), Some(&and));
    assert_eq!(fragment, Some(String::from_str("lol")));
}

#[test]
fn parse_strange_path() {
    let with = "this".to_owned();
    let and = "what?".to_owned();
    let (path, query, fragment) = parse_path(String::from_str("/path/to/something?with=this&and=what?#"));
    assert_eq!(path, String::from_str("/path/to/something"));
    assert_eq!(query.get("with"), Some(&with));
    assert_eq!(query.get("and"), Some(&and));
    assert_eq!(fragment, Some(String::from_str("")));
}

#[test]
fn parse_missing_path_parts() {
    let with = "this".to_owned();
    let and = "that".to_owned();
    let (path, query, fragment) = parse_path(String::from_str("/path/to/something?with=this&and=that"));
    assert_eq!(path, String::from_str("/path/to/something"));
    assert_eq!(query.get("with"), Some(&with));
    assert_eq!(query.get("and"), Some(&and));
    assert_eq!(fragment, None);

    let (path, query, fragment) = parse_path(String::from_str("/path/to/something#lol"));
    assert_eq!(path, String::from_str("/path/to/something"));
    assert_eq!(query.len(), 0);
    assert_eq!(fragment, Some(String::from_str("lol")));

    let (path, query, fragment) = parse_path(String::from_str("?with=this&and=that#lol"));
    assert_eq!(path, String::from_str(""));
    assert_eq!(query.get("with"), Some(&with));
    assert_eq!(query.get("and"), Some(&and));
    assert_eq!(fragment, Some(String::from_str("lol")));
}<commit_msg>Update lifetimes for Send changes<commit_after>//!Server configuration and instance.

#![stable]

use std;
use std::collections::HashMap;
use std::sync::RwLock;
use std::old_io::net::ip::{IpAddr, Ipv4Addr, Port};
use std::borrow::ToOwned;

use time::{self, Timespec};

use url::percent_encoding::lossy_utf8_percent_decode;

use hyper;
use hyper::server::Handler as HyperHandler;
use hyper::header::{Headers, Date, ContentType, ContentLength};
use hyper::mime::Mime;
use hyper::uri::RequestUri;

pub use hyper::server::Listening;

use StatusCode;

use context::{self, Context};
use plugin::{ContextPlugin, ContextAction, ResponsePlugin};
use router::Router;
use cache::Cache;
use handler::Handler;
use response::Response;
use log::{Log, StdOut};
use Protocol;

use utils;

///Used to build and run a server.
///
///Each field has a corresponding modifier method and
///calls to these methods can be chained for quick setup.
///
///```no_run
///# use std::error::Error;
///# use rustful::{Server, Handler, Context, Response};
///# struct R;
///# impl Handler for R {
///#     type Cache = ();
///#     fn handle_request(&self, _context: Context, _response: Response) {}
///# }
///# let router = R;
///let server_result = Server::new().port(8080).handlers(router).run();
///
///match server_result {
///    Ok(_server) => {},
///    Err(e) => println!("could not start server: {}", e.description())
///}
///```
pub struct Server<R, C> {
    ///One or several response handlers.
    pub handlers: R,

    ///The port where the server will listen for requests.
    pub port: Port,

    ///The host address where the server will listen for requests.
    pub host: IpAddr,

    ///The type of HTTP protocol.
    pub protocol: Protocol,

    ///The number of threads to be used in the server task pool.
    ///The default (`None`) is based on recommendations from the system.
    pub threads: Option<usize>,

    ///The content of the server header.
    pub server: String,

    ///The default media type.
    pub content_type: Mime,

    ///A structure where resources are cached.
    pub cache: C,

    ///How often the cache should be cleaned. Measured in seconds.
    pub cache_clean_interval: Option<i64>,

    ///Tool for printing to a log.
    pub log: Box<Log + Send + Sync>,

    ///The context plugin stack.
    #[unstable]
    pub context_plugins: Vec<Box<ContextPlugin<Cache=C> + Send + Sync>>,

    ///The response plugin stack.
    #[unstable]
    pub response_plugins: Vec<Box<ResponsePlugin + Send + Sync>>
}

impl Server<(), ()> {
    ///Create a new empty server which will listen on host address `0.0.0.0` and port `80`.
    pub fn new() -> Server<(), ()> {
        Server::with_cache(())
    }
}

impl<C: Cache> Server<(), C> {
    ///Create a new empty server with a cache.
    pub fn with_cache(cache: C) -> Server<(), C> {
        Server {
            handlers: (),
            port: 80,
            host: Ipv4Addr(0, 0, 0, 0),
            protocol: Protocol::Http,
            threads: None,
            server: "rustful".to_owned(),
            content_type: Mime(
                hyper::mime::TopLevel::Text,
                hyper::mime::SubLevel::Plain,
                vec![(hyper::mime::Attr::Charset, hyper::mime::Value::Utf8)]
            ),
            cache: cache,
            cache_clean_interval: None,
            log: Box::new(StdOut) as Box<Log + Send + Sync>,
            context_plugins: Vec::new(),
            response_plugins: Vec::new()
        }
    }
}

impl<R, C> Server<R, C> {
    ///Set request handlers.
    pub fn handlers<NewRouter: Router<Handler=H>, H: Handler<Cache=C>>(self, handlers: NewRouter) -> Server<NewRouter, C> {
        Server {
            handlers: handlers,
            port: self.port,
            host: self.host,
            protocol: self.protocol,
            threads: self.threads,
            server: self.server,
            content_type: self.content_type,
            cache: self.cache,
            cache_clean_interval: self.cache_clean_interval,
            log: self.log,
            context_plugins: self.context_plugins,
            response_plugins: self.response_plugins,
        }
    }

    ///Change the port. Default is `80`.
    pub fn port(mut self, port: Port) -> Server<R, C> {
        self.port = port;
        self
    }

    ///Change the host address. Default is `0.0.0.0`.
    pub fn host(mut self, host: IpAddr) -> Server<R, C> {
        self.host = host;
        self
    }

    ///Change the protocol to HTTPS.
    pub fn https(mut self, cert: Path, key: Path) -> Server<R, C> {
        self.protocol = Protocol::Https {
            cert: cert,
            key: key
        };
        self
    }

    ///Set the number of threads to be used in the server task pool.
    ///
    ///Passing `None` will set it to the default number of threads,
    ///based on recommendations from the system.
    pub fn threads(mut self, threads: Option<usize>) -> Server<R, C> {
        self.threads = threads;
        self
    }

    ///Set the minimal number of seconds between each cache clean.
    ///
    ///Passing `None` disables cache cleaning.
    pub fn cache_clean_interval(mut self, interval: Option<u32>) -> Server<R, C> {
        self.cache_clean_interval = interval.map(|i| i as i64);
        self
    }

    ///Change the server response header. Default is `rustful`.
    pub fn server_name(mut self, name: String) -> Server<R, C> {
        self.server = name;
        self
    }

    ///Change the default content type. Default is `text/plain`.
    pub fn content_type(mut self, content_type: Mime) -> Server<R, C> {
        self.content_type = content_type;
        self
    }

    ///Change log tool. Default is to print to standard output.
    pub fn log<L: Log + Send + Sync + 'static>(mut self, log: L) -> Server<R, C> {
        self.log = Box::new(log) as Box<Log + Send + Sync>;
        self
    }

    ///Add a context plugin to the plugin stack.
    #[unstable]
    pub fn with_context_plugin<P: ContextPlugin<Cache=C> + Send + Sync + 'static>(mut self, plugin: P) ->  Server<R, C> {
        self.context_plugins.push(Box::new(plugin) as Box<ContextPlugin<Cache=C> + Send + Sync>);
        self
    }

    ///Add a response plugin to the plugin stack.
    #[unstable]
    pub fn with_response_plugin<P: ResponsePlugin + Send + Sync + 'static>(mut self, plugin: P) ->  Server<R, C> {
        self.response_plugins.push(Box::new(plugin) as Box<ResponsePlugin + Send + Sync>);
        self
    }
}

impl<R, H, C> Server<R, C>
    where
    R: Router<Handler=H> + Send + Sync + 'static,
    H: Handler<Cache=C> + Send + Sync + 'static,
    C: Cache + Send + Sync + 'static
{
    ///Start the server.
    pub fn run(self) -> hyper::HttpResult<Listening> {
        let threads = self.threads;
        let (server, protocol) = self.build();
        let http = match protocol {
            Protocol::Http => hyper::server::Server::http(server.host, server.port),
            Protocol::Https {cert, key} => hyper::server::Server::https(server.host, server.port, cert, key)
        };

        match threads {
            Some(threads) => http.listen_threads(server, threads),
            None => http.listen(server)
        }
    }

    ///Build a runnable instance of the server.
    pub fn build(self) -> (ServerInstance<R, C>, Protocol) {
        (ServerInstance {
            handlers: self.handlers,
            port: self.port,
            host: self.host,
            server: self.server,
            content_type: self.content_type,
            cache: self.cache,
            cache_clean_interval: self.cache_clean_interval,
            last_cache_clean: RwLock::new(Timespec::new(0, 0)),
            log: self.log,
            context_plugins: self.context_plugins,
            response_plugins: self.response_plugins,
        },
        self.protocol)
    }
}

///A runnable instance of a server.
///
///It's not meant to be used directly,
///unless additional control is required.
///
///```no_run
///# use rustful::{Server, Handler, Context, Response};
///# struct R;
///# impl Handler for R {
///#     type Cache = ();
///#     fn handle_request(&self, _context: Context, _response: Response) {}
///# }
///# let router = R;
///let (server_instance, protocol) = Server::new().port(8080).handlers(router).build();
///```
pub struct ServerInstance<R, C> {
    handlers: R,

    port: Port,
    host: IpAddr,

    server: String,
    content_type: Mime,

    cache: C,
    cache_clean_interval: Option<i64>,
    last_cache_clean: RwLock<Timespec>,

    log: Box<Log + Send + Sync>,

    context_plugins: Vec<Box<ContextPlugin<Cache=C> + Send + Sync>>,
    response_plugins: Vec<Box<ResponsePlugin + Send + Sync>>
}

impl<R, C: Cache> ServerInstance<R, C> {

    fn modify_context(&self, context: &mut Context<C>) -> ContextAction {
        let mut result = ContextAction::Continue;

        for plugin in &self.context_plugins {
            result = match result {
                ContextAction::Continue => plugin.modify(&*self.log, context),
                _ => return result
            };
        }

        result
    }

}

impl<R, H, C> HyperHandler for ServerInstance<R, C>
    where
    R: Router<Handler=H> + Send + Sync,
    H: Handler<Cache=C> + Send + Sync,
    C: Cache + Send + Sync,
{
    fn handle(&self, mut request: hyper::server::request::Request, writer: hyper::server::response::Response) {
        let request_uri = request.uri.clone();
        let request_method = request.method.clone();
        let mut request_headers = Headers::new();
        std::mem::swap(&mut request_headers, &mut request.headers);

        let mut response = Response::new(writer, &self.response_plugins, &*self.log);
        response.set_header(Date(time::now_utc()));
        response.set_header(ContentType(self.content_type.clone()));
        response.set_header(hyper::header::Server(self.server.clone()));

        let path_components = match request_uri {
            RequestUri::AbsoluteUri(url) => {
                Some((
                    url.serialize_path().map(|p| p.into_bytes()).unwrap_or_else(|| vec!['/' as u8]),
                    url.query_pairs().unwrap_or_else(|| Vec::new()).into_iter().collect(),
                    url.fragment
                ))
            },
            RequestUri::AbsolutePath(path) => {
                let (path, query, fragment) = parse_path(path);
                Some((path.into_bytes(), query, fragment))
            },
            _ => None //TODO: Handle *
        };

        match path_components {
            Some((path, query, fragment)) => {

                let mut context = Context {
                    headers: request_headers,
                    method: request_method,
                    path: lossy_utf8_percent_decode(&path),
                    variables: HashMap::new(),
                    query: query,
                    fragment: fragment,
                    cache: &self.cache,
                    log: &*self.log,
                    body_reader: context::BodyReader::from_request(request)
                };

                match self.modify_context(&mut context) {
                    ContextAction::Continue => {
                        match self.handlers.find(&context.method, &context.path) {
                            Some((handler, variables)) => {
                                context.variables = variables;
                                handler.handle_request(context, response);
                            },
                            None => {
                                response.set_header(ContentLength(0));
                                response.set_status(StatusCode::NotFound);
                            }
                        }
                    },
                    ContextAction::Abort(status) => {
                        response.set_header(ContentLength(0));
                        response.set_status(status);
                    }
                }
            },
            None => {
                response.set_header(ContentLength(0));
                response.set_status(StatusCode::BadRequest);
            }
        }

        self.cache_clean_interval.map(|t| {
            let clean_time = {
                let last_cache_clean = self.last_cache_clean.read().unwrap();
                Timespec::new(last_cache_clean.sec + t, last_cache_clean.nsec)
            };

            if time::get_time() > clean_time {
                *self.last_cache_clean.write().unwrap() = time::get_time();
                self.cache.free_unused(&*self.log);
            }
        });
    }
}

fn parse_path(path: String) -> (String, HashMap<String, String>, Option<String>) {
    match path.find('?') {
        Some(index) => {
            let (query, fragment) = parse_fragment(&path[index+1..]);
            (path[..index].to_owned(), utils::parse_parameters(query.as_bytes()), fragment.map(|f| f.to_owned()))
        },
        None => {
            let (path, fragment) = parse_fragment(&path);
            (path.to_owned(), HashMap::new(), fragment.map(|f| f.to_owned()))
        }
    }
}

fn parse_fragment<'a>(path: &'a str) -> (&'a str, Option<&'a str>) {
    match path.find('#') {
        Some(index) => (&path[..index], Some(&path[index+1..])),
        None => (path, None)
    }
}

#[test]
fn parse_path_parts() {
    let with = "this".to_owned();
    let and = "that".to_owned();
    let (path, query, fragment) = parse_path(String::from_str("/path/to/something?with=this&and=that#lol"));
    assert_eq!(path, String::from_str("/path/to/something"));
    assert_eq!(query.get("with"), Some(&with));
    assert_eq!(query.get("and"), Some(&and));
    assert_eq!(fragment, Some(String::from_str("lol")));
}

#[test]
fn parse_strange_path() {
    let with = "this".to_owned();
    let and = "what?".to_owned();
    let (path, query, fragment) = parse_path(String::from_str("/path/to/something?with=this&and=what?#"));
    assert_eq!(path, String::from_str("/path/to/something"));
    assert_eq!(query.get("with"), Some(&with));
    assert_eq!(query.get("and"), Some(&and));
    assert_eq!(fragment, Some(String::from_str("")));
}

#[test]
fn parse_missing_path_parts() {
    let with = "this".to_owned();
    let and = "that".to_owned();
    let (path, query, fragment) = parse_path(String::from_str("/path/to/something?with=this&and=that"));
    assert_eq!(path, String::from_str("/path/to/something"));
    assert_eq!(query.get("with"), Some(&with));
    assert_eq!(query.get("and"), Some(&and));
    assert_eq!(fragment, None);

    let (path, query, fragment) = parse_path(String::from_str("/path/to/something#lol"));
    assert_eq!(path, String::from_str("/path/to/something"));
    assert_eq!(query.len(), 0);
    assert_eq!(fragment, Some(String::from_str("lol")));

    let (path, query, fragment) = parse_path(String::from_str("?with=this&and=that#lol"));
    assert_eq!(path, String::from_str(""));
    assert_eq!(query.get("with"), Some(&with));
    assert_eq!(query.get("and"), Some(&and));
    assert_eq!(fragment, Some(String::from_str("lol")));
}<|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers.
// Copyright 2015 Guillaume Gomez
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Library to interface with chunks of memory allocated in C.
//!
//! It is often desirable to safely interface with memory allocated from C,
//! encapsulating the unsafety into allocation and destruction time.  Indeed,
//! allocating memory externally is currently the only way to give Rust shared
//! mut state with C programs that keep their own references; vectors are
//! unsuitable because they could be reallocated or moved at any time, and
//! importing C memory into a vector takes a one-time snapshot of the memory.
//!
//! This module simplifies the usage of such external blocks of memory.  Memory
//! is encapsulated into an opaque object after creation; the lifecycle of the
//! memory can be optionally managed by Rust, if an appropriate destructor
//! closure is provided.  Safety is ensured by bounds-checking accesses, which
//! are marshalled through get and set functions.
//!
//! There are three unsafe functions: the two constructors, and the
//! unwrapping method. The constructors are unsafe for the
//! obvious reason (they act on a pointer that cannot be checked inside the
//! method), but `into_inner()` is somewhat more subtle in its unsafety.
//! It returns the contained pointer, but at the same time destroys the CVec
//! without running its destructor. This can be used to pass memory back to
//! C, but care must be taken that the ownership of underlying resources are
//! handled correctly, i.e. that allocated memory is eventually freed
//! if necessary.

#![feature(unsafe_destructor, core, std_misc, unique)]

use std::mem;
use std::ptr;
use std::raw;
use std::ptr::Unique;
use std::thunk::Invoke;
use std::ops::{Index, IndexMut};

/// The type representing a foreign chunk of memory
pub struct CVec<T> {
    base: Unique<T>,
    len: usize,
    dtor: Option<Box<Invoke<*mut T> + 'static>>
}

#[unsafe_destructor]
impl<T> Drop for CVec<T> {
    fn drop(&mut self) {
        match self.dtor.take() {
            None => (),
            Some(f) => f.invoke(*self.base),
        }
    }
}

impl<T> CVec<T> {
    /// Create a `CVec` from a raw pointer to a buffer with a given length.
    ///
    /// Panics if the given pointer is null. The returned vector will not attempt
    /// to deallocate the vector when dropped.
    ///
    /// # Arguments
    ///
    /// * base - A unique pointer to a buffer
    /// * len - The number of elements in the buffer
    pub unsafe fn new(base: Unique<T>, len: usize) -> CVec<T> {
        assert!(*base != ptr::null_mut());
        CVec {
            base: base,
            len: len,
            dtor: None,
        }
    }

    /// Create a `CVec` from a foreign buffer, with a given length,
    /// and a function to run upon destruction.
    ///
    /// Panics if the given pointer is null.
    ///
    /// # Arguments
    ///
    /// * base - A unique pointer to a buffer
    /// * len - The number of elements in the buffer
    /// * dtor - A fn to run when the value is destructed, useful
    ///          for freeing the buffer, etc. `base` will be passed
    ///          to it as an argument.
    pub unsafe fn new_with_dtor<F>(base: Unique<T>,
                                   len: usize,
                                   dtor: F)
                                   -> CVec<T>
        where F : FnOnce(*mut T) + 'static
    {
        assert!(*base != ptr::null_mut());
        let dtor = Box::new(dtor);
        CVec {
            base: base,
            len: len,
            dtor: Some(dtor)
        }
    }

    /// View the stored data as a mutable slice.
    pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
        unsafe {
            mem::transmute(raw::Slice { data: *self.base as *const T, len: self.len })
        }
    }

    /// Retrieves an element at a given index, returning `None` if the requested
    /// index is greater than the length of the vector.
    pub fn get<'a>(&'a self, ofs: usize) -> Option<&'a T> {
        if ofs < self.len {
            Some(unsafe { &*self.base.offset(ofs as isize) })
        } else {
            None
        }
    }

    /// Retrieves a mutable element at a given index, returning `None` if the
    /// requested index is greater than the length of the vector.
    pub fn get_mut<'a>(&'a mut self, ofs: usize) -> Option<&'a mut T> {
        if ofs < self.len {
            Some(unsafe { &mut *self.base.offset(ofs as isize) })
        } else {
            None
        }
    }

    /// Unwrap the pointer without running the destructor
    ///
    /// This method retrieves the underlying pointer, and in the process
    /// destroys the CVec but without running the destructor. A use case
    /// would be transferring ownership of the buffer to a C function, as
    /// in this case you would not want to run the destructor.
    ///
    /// Note that if you want to access the underlying pointer without
    /// cancelling the destructor, you can simply call `transmute` on the return
    /// value of `get(0)`.
    pub unsafe fn into_inner(mut self) -> *mut T {
        self.dtor = None;
        *self.base
    }

    /// Returns the number of items in this vector.
    pub fn len(&self) -> usize { self.len }

    /// Returns whether this vector is empty.
    pub fn is_empty(&self) -> bool { self.len() == 0 }

    /// Convert to CSlice
    pub fn as_cslice(&self) -> CSlice<T> {
        CSlice {
            base: *self.base,
            len: self.len
        }
    }
}

impl<T> AsSlice<T> for CVec<T> {
    /// View the stored data as a slice.
    fn as_slice<'a>(&'a self) -> &'a [T] {
        unsafe {
            mem::transmute(raw::Slice { data: *self.base as *const T, len: self.len })
        }
    }
}

/// The type representing an 'unsafe' foreign chunk of memory
pub struct CSlice<T> {
    base: *mut T,
    len: usize
}

impl<T> CSlice<T> {
    /// Create a `CSlice` from a raw pointer to a buffer with a given length.
    ///
    /// Panics if the given pointer is null. The returned vector will not attempt
    /// to deallocate the vector when dropped.
    ///
    /// # Arguments
    ///
    /// * base - A raw pointer to a buffer
    /// * len - The number of elements in the buffer
    pub unsafe fn new(base: *mut T, len: usize) -> CSlice<T> {
        assert!(base != ptr::null_mut());
        CSlice {
            base: base,
            len: len
        }
    }

    /// View the stored data as a mutable slice.
    pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
        unsafe {
            mem::transmute(raw::Slice { data: self.base as *const T, len: self.len })
        }
    }

    /// Retrieves an element at a given index, returning `None` if the requested
    /// index is greater than the length of the vector.
    pub fn get<'a>(&'a self, ofs: usize) -> Option<&'a T> {
        if ofs < self.len {
            Some(unsafe { &*self.base.offset(ofs as isize) })
        } else {
            None
        }
    }

    /// Retrieves a mutable element at a given index, returning `None` if the
    /// requested index is greater than the length of the vector.
    pub fn get_mut<'a>(&'a mut self, ofs: usize) -> Option<&'a mut T> {
        if ofs < self.len {
            Some(unsafe { &mut *self.base.offset(ofs as isize) })
        } else {
            None
        }
    }

    /// Returns the number of items in this vector.
    pub fn len(&self) -> usize { self.len }

    /// Returns whether this vector is empty.
    pub fn is_empty(&self) -> bool { self.len() == 0 }
}

impl<T> AsSlice<T> for CSlice<T> {
    /// View the stored data as a slice.
    fn as_slice<'a>(&'a self) -> &'a [T] {
        unsafe {
            mem::transmute(raw::Slice { data: self.base as *const T, len: self.len })
        }
    }
}

impl<T> Index<usize> for CSlice<T> {
    type Output = T;

    fn index<'a>(&'a self, _index: &usize) -> &'a T {
        assert!(*_index < self.len);
        unsafe { &*self.base.offset(*_index as isize) }
    }
}

impl<T> IndexMut<usize> for CSlice<T> {
    fn index_mut<'a>(&'a mut self, _index: &usize) -> &'a mut T {
        assert!(*_index < self.len);
        unsafe { &mut *self.base.offset(*_index as isize) }
    }
}

#[cfg(test)]
mod tests {
    extern crate alloc;
    extern crate libc;

    use super::{CVec, CSlice};
    use std::ptr::{self, Unique};

    // allocation of CVec
    fn v_malloc(n: usize) -> CVec<u8> {
        unsafe {
            let mem: Unique<u8> = Unique::new(
                libc::malloc(n as libc::size_t) as *mut _);
            if (*mem).is_null() { alloc::oom() }

            CVec::new_with_dtor(mem, n,
                                |mem| { libc::free((mem) as *mut _); })
        }
    }

    // allocation of CSlice
    fn s_malloc(n: usize) -> CSlice<u8> {
        unsafe {
            let mem: *mut u8 = libc::malloc(n as libc::size_t) as *mut _;
            if mem.is_null() { alloc::oom() }

            CSlice::new(mem, n)
        }
    }

    #[test]
    fn vec_test_basic() {
        let mut cv = v_malloc(16);

        *cv.get_mut(3).unwrap() = 8;
        *cv.get_mut(4).unwrap() = 9;
        assert_eq!(*cv.get(3).unwrap(), 8);
        assert_eq!(*cv.get(4).unwrap(), 9);
        assert_eq!(cv.len(), 16);
    }

    #[test]
    fn slice_test_basic() {
        let mut cs = s_malloc(16);

        cs[3] = 8;
        cs[4] = 9;
        assert_eq!(cs[3], 8);
        assert_eq!(cs[4], 9);
        assert_eq!(cs.len(), 16);
    }

    #[test]
    #[should_fail]
    fn vec_test_panic_at_null() {
        unsafe {
            CVec::new(Unique::new(ptr::null_mut::<u8>()), 9);
        }
    }

    #[test]
    #[should_fail]
    fn slice_test_panic_at_null() {
        unsafe {
            CSlice::new(ptr::null_mut::<u8>(), 9);
        }
    }

    #[test]
    fn vec_test_overrun_get() {
        let cv = v_malloc(16);

        assert!(cv.get(17).is_none());
    }

    #[test]
    #[should_fail]
    fn slice_test_overrun_get() {
        let cs = s_malloc(16);

        assert!(cs[17] == 18);
    }

    #[test]
    fn vec_test_overrun_set() {
        let mut cv = v_malloc(16);

        assert!(cv.get_mut(17).is_none());
    }

    #[test]
    fn vec_test_unwrap() {
        unsafe {
            let cv = CVec::new_with_dtor(Unique::new(1 as *mut isize),
                                         0,
                                         |_| panic!("Don't run this destructor!"));
            let p = cv.into_inner();
            assert_eq!(p, 1 as *mut isize);
        }
    }

    #[test]
    fn vec_to_slice_test() {
        unsafe {
            let mut cv = v_malloc(2);

            *cv.get_mut(0).unwrap() = 10;
            *cv.get_mut(1).unwrap() = 12;
            let cs = cv.as_cslice();

            assert_eq!(cs[0], 10);
            assert_eq!(cs[1], 12);
        }
    }

    #[test]
    fn slice_to_vec_test() {
        let cv = v_malloc(2);
        let mut cs = cv.as_cslice();

        cs[0] = 13;
        cs[1] = 26;
        assert_eq!(*cv.get(0).unwrap(), 13);
        assert_eq!(*cv.get(1).unwrap(), 26);
    }
}
<commit_msg>Fix the build<commit_after>// Copyright 2012 The Rust Project Developers.
// Copyright 2015 Guillaume Gomez
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Library to interface with chunks of memory allocated in C.
//!
//! It is often desirable to safely interface with memory allocated from C,
//! encapsulating the unsafety into allocation and destruction time.  Indeed,
//! allocating memory externally is currently the only way to give Rust shared
//! mut state with C programs that keep their own references; vectors are
//! unsuitable because they could be reallocated or moved at any time, and
//! importing C memory into a vector takes a one-time snapshot of the memory.
//!
//! This module simplifies the usage of such external blocks of memory.  Memory
//! is encapsulated into an opaque object after creation; the lifecycle of the
//! memory can be optionally managed by Rust, if an appropriate destructor
//! closure is provided.  Safety is ensured by bounds-checking accesses, which
//! are marshalled through get and set functions.
//!
//! There are three unsafe functions: the two constructors, and the
//! unwrapping method. The constructors are unsafe for the
//! obvious reason (they act on a pointer that cannot be checked inside the
//! method), but `into_inner()` is somewhat more subtle in its unsafety.
//! It returns the contained pointer, but at the same time destroys the CVec
//! without running its destructor. This can be used to pass memory back to
//! C, but care must be taken that the ownership of underlying resources are
//! handled correctly, i.e. that allocated memory is eventually freed
//! if necessary.

#![feature(unsafe_destructor, core, std_misc, unique)]

use std::mem;
use std::ptr;
use std::raw;
use std::ptr::Unique;
use std::thunk::Invoke;
use std::ops::{Index, IndexMut};

/// The type representing a foreign chunk of memory
pub struct CVec<T> {
    base: Unique<T>,
    len: usize,
    dtor: Option<Box<Invoke<*mut T> + 'static>>
}

#[unsafe_destructor]
impl<T> Drop for CVec<T> {
    fn drop(&mut self) {
        match self.dtor.take() {
            None => (),
            Some(f) => f.invoke(*self.base),
        }
    }
}

impl<T> CVec<T> {
    /// Create a `CVec` from a raw pointer to a buffer with a given length.
    ///
    /// Panics if the given pointer is null. The returned vector will not attempt
    /// to deallocate the vector when dropped.
    ///
    /// # Arguments
    ///
    /// * base - A unique pointer to a buffer
    /// * len - The number of elements in the buffer
    pub unsafe fn new(base: Unique<T>, len: usize) -> CVec<T> {
        assert!(*base != ptr::null_mut());
        CVec {
            base: base,
            len: len,
            dtor: None,
        }
    }

    /// Create a `CVec` from a foreign buffer, with a given length,
    /// and a function to run upon destruction.
    ///
    /// Panics if the given pointer is null.
    ///
    /// # Arguments
    ///
    /// * base - A unique pointer to a buffer
    /// * len - The number of elements in the buffer
    /// * dtor - A fn to run when the value is destructed, useful
    ///          for freeing the buffer, etc. `base` will be passed
    ///          to it as an argument.
    pub unsafe fn new_with_dtor<F>(base: Unique<T>,
                                   len: usize,
                                   dtor: F)
                                   -> CVec<T>
        where F : FnOnce(*mut T) + 'static
    {
        assert!(*base != ptr::null_mut());
        let dtor = Box::new(dtor);
        CVec {
            base: base,
            len: len,
            dtor: Some(dtor)
        }
    }

    /// View the stored data as a mutable slice.
    pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
        unsafe {
            mem::transmute(raw::Slice { data: *self.base as *const T, len: self.len })
        }
    }

    /// Retrieves an element at a given index, returning `None` if the requested
    /// index is greater than the length of the vector.
    pub fn get<'a>(&'a self, ofs: usize) -> Option<&'a T> {
        if ofs < self.len {
            Some(unsafe { &*self.base.offset(ofs as isize) })
        } else {
            None
        }
    }

    /// Retrieves a mutable element at a given index, returning `None` if the
    /// requested index is greater than the length of the vector.
    pub fn get_mut<'a>(&'a mut self, ofs: usize) -> Option<&'a mut T> {
        if ofs < self.len {
            Some(unsafe { &mut *self.base.offset(ofs as isize) })
        } else {
            None
        }
    }

    /// Unwrap the pointer without running the destructor
    ///
    /// This method retrieves the underlying pointer, and in the process
    /// destroys the CVec but without running the destructor. A use case
    /// would be transferring ownership of the buffer to a C function, as
    /// in this case you would not want to run the destructor.
    ///
    /// Note that if you want to access the underlying pointer without
    /// cancelling the destructor, you can simply call `transmute` on the return
    /// value of `get(0)`.
    pub unsafe fn into_inner(mut self) -> *mut T {
        self.dtor = None;
        *self.base
    }

    /// Returns the number of items in this vector.
    pub fn len(&self) -> usize { self.len }

    /// Returns whether this vector is empty.
    pub fn is_empty(&self) -> bool { self.len() == 0 }

    /// Convert to CSlice
    pub fn as_cslice(&self) -> CSlice<T> {
        CSlice {
            base: *self.base,
            len: self.len
        }
    }
}

impl<T> AsSlice<T> for CVec<T> {
    /// View the stored data as a slice.
    fn as_slice<'a>(&'a self) -> &'a [T] {
        unsafe {
            mem::transmute(raw::Slice { data: *self.base as *const T, len: self.len })
        }
    }
}

/// The type representing an 'unsafe' foreign chunk of memory
pub struct CSlice<T> {
    base: *mut T,
    len: usize
}

impl<T> CSlice<T> {
    /// Create a `CSlice` from a raw pointer to a buffer with a given length.
    ///
    /// Panics if the given pointer is null. The returned vector will not attempt
    /// to deallocate the vector when dropped.
    ///
    /// # Arguments
    ///
    /// * base - A raw pointer to a buffer
    /// * len - The number of elements in the buffer
    pub unsafe fn new(base: *mut T, len: usize) -> CSlice<T> {
        assert!(base != ptr::null_mut());
        CSlice {
            base: base,
            len: len
        }
    }

    /// View the stored data as a mutable slice.
    pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
        unsafe {
            mem::transmute(raw::Slice { data: self.base as *const T, len: self.len })
        }
    }

    /// Retrieves an element at a given index, returning `None` if the requested
    /// index is greater than the length of the vector.
    pub fn get<'a>(&'a self, ofs: usize) -> Option<&'a T> {
        if ofs < self.len {
            Some(unsafe { &*self.base.offset(ofs as isize) })
        } else {
            None
        }
    }

    /// Retrieves a mutable element at a given index, returning `None` if the
    /// requested index is greater than the length of the vector.
    pub fn get_mut<'a>(&'a mut self, ofs: usize) -> Option<&'a mut T> {
        if ofs < self.len {
            Some(unsafe { &mut *self.base.offset(ofs as isize) })
        } else {
            None
        }
    }

    /// Returns the number of items in this vector.
    pub fn len(&self) -> usize { self.len }

    /// Returns whether this vector is empty.
    pub fn is_empty(&self) -> bool { self.len() == 0 }
}

impl<T> AsSlice<T> for CSlice<T> {
    /// View the stored data as a slice.
    fn as_slice<'a>(&'a self) -> &'a [T] {
        unsafe {
            mem::transmute(raw::Slice { data: self.base as *const T, len: self.len })
        }
    }
}

impl<T> Index<usize> for CSlice<T> {
    type Output = T;

    fn index<'a>(&'a self, _index: usize) -> &'a T {
        assert!(_index < self.len);
        unsafe { &*self.base.offset(_index as isize) }
    }
}

impl<T> IndexMut<usize> for CSlice<T> {
    fn index_mut<'a>(&'a mut self, _index: usize) -> &'a mut T {
        assert!(_index < self.len);
        unsafe { &mut *self.base.offset(_index as isize) }
    }
}

#[cfg(test)]
mod tests {
    extern crate alloc;
    extern crate libc;

    use super::{CVec, CSlice};
    use std::ptr::{self, Unique};

    // allocation of CVec
    fn v_malloc(n: usize) -> CVec<u8> {
        unsafe {
            let mem: Unique<u8> = Unique::new(
                libc::malloc(n as libc::size_t) as *mut _);
            if (*mem).is_null() { alloc::oom() }

            CVec::new_with_dtor(mem, n,
                                |mem| { libc::free((mem) as *mut _); })
        }
    }

    // allocation of CSlice
    fn s_malloc(n: usize) -> CSlice<u8> {
        unsafe {
            let mem: *mut u8 = libc::malloc(n as libc::size_t) as *mut _;
            if mem.is_null() { alloc::oom() }

            CSlice::new(mem, n)
        }
    }

    #[test]
    fn vec_test_basic() {
        let mut cv = v_malloc(16);

        *cv.get_mut(3).unwrap() = 8;
        *cv.get_mut(4).unwrap() = 9;
        assert_eq!(*cv.get(3).unwrap(), 8);
        assert_eq!(*cv.get(4).unwrap(), 9);
        assert_eq!(cv.len(), 16);
    }

    #[test]
    fn slice_test_basic() {
        let mut cs = s_malloc(16);

        cs[3] = 8;
        cs[4] = 9;
        assert_eq!(cs[3], 8);
        assert_eq!(cs[4], 9);
        assert_eq!(cs.len(), 16);
    }

    #[test]
    #[should_fail]
    fn vec_test_panic_at_null() {
        unsafe {
            CVec::new(Unique::new(ptr::null_mut::<u8>()), 9);
        }
    }

    #[test]
    #[should_fail]
    fn slice_test_panic_at_null() {
        unsafe {
            CSlice::new(ptr::null_mut::<u8>(), 9);
        }
    }

    #[test]
    fn vec_test_overrun_get() {
        let cv = v_malloc(16);

        assert!(cv.get(17).is_none());
    }

    #[test]
    #[should_fail]
    fn slice_test_overrun_get() {
        let cs = s_malloc(16);

        assert!(cs[17] == 18);
    }

    #[test]
    fn vec_test_overrun_set() {
        let mut cv = v_malloc(16);

        assert!(cv.get_mut(17).is_none());
    }

    #[test]
    fn vec_test_unwrap() {
        unsafe {
            let cv = CVec::new_with_dtor(Unique::new(1 as *mut isize),
                                         0,
                                         |_| panic!("Don't run this destructor!"));
            let p = cv.into_inner();
            assert_eq!(p, 1 as *mut isize);
        }
    }

    #[test]
    fn vec_to_slice_test() {
        unsafe {
            let mut cv = v_malloc(2);

            *cv.get_mut(0).unwrap() = 10;
            *cv.get_mut(1).unwrap() = 12;
            let cs = cv.as_cslice();

            assert_eq!(cs[0], 10);
            assert_eq!(cs[1], 12);
        }
    }

    #[test]
    fn slice_to_vec_test() {
        let cv = v_malloc(2);
        let mut cs = cv.as_cslice();

        cs[0] = 13;
        cs[1] = 26;
        assert_eq!(*cv.get(0).unwrap(), 13);
        assert_eq!(*cv.get(1).unwrap(), 26);
    }
}
<|endoftext|>


<commit_before>//! This module represents a basic, rule-agnostic 32-cards system.

use ::rand::{
    thread_rng,
    Rng,
    IsaacRng,
    SeedableRng
};
use std::num::Wrapping;
use std::string::ToString;
use rustc_serialize;

/// One of the four Suits: Heart, Spade, Diamond, Club
#[derive(PartialEq,Clone,Copy)]
pub struct Suit(u32);

// TODO: Make these associated const when it's stable

/// The Heart suit
pub const HEART: Suit = Suit(1 << 0);
/// The Spade suit
pub const SPADE: Suit = Suit(1 << 8);
/// The Diamond suit
pub const DIAMOND: Suit = Suit(1 << 16);
/// The Club suit
pub const CLUB: Suit = Suit(1 << 24);

impl rustc_serialize::Encodable for Suit {
    fn encode<S: rustc_serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        match *self {
            HEART | SPADE | DIAMOND | CLUB => self.0.encode(s),
            _ => "??".encode(s),
        }
    }
}

impl Suit {
    /// Returns the suit corresponding to the number:
    ///
    /// * `0`: Heart
    /// * `1`: Spade
    /// * `2`: Diamond
    /// * `3`: Club
    /// * `>=4`: panics
    pub fn from_n(n: u32) -> Self {
        if n >= 4 { panic!("Bad suit number"); }
        Suit(1 << 8*n)
    }

    /// Returns a UTF-8 character representing the suit.
    pub fn to_string(self) -> String {
        match self {
            HEART => "♥",
            SPADE => "♠",
            DIAMOND => "♦",
            CLUB => "♣",
            _ => "?",
        }.to_string()
    }
}

/// Rank of a card in a suit
#[derive(PartialEq,Clone,Copy)]
pub struct Rank(u32);
/// 7
pub const RANK_7: Rank = Rank(1 << 0);
/// 8
pub const RANK_8: Rank = Rank(1 << 1);
/// 9
pub const RANK_9: Rank = Rank(1 << 2);
/// Jack
pub const RANK_J: Rank = Rank(1 << 3);
/// Queen
pub const RANK_Q: Rank = Rank(1 << 4);
/// King
pub const RANK_K: Rank = Rank(1 << 5);
/// 10
pub const RANK_X: Rank = Rank(1 << 6);
/// Ace
pub const RANK_A: Rank = Rank(1 << 7);
/// Bit mask over all ranks
pub const RANK_MASK: Rank = Rank(255);

impl Rank {

    /// Returns the rank corresponding to the given number:
    /// * `0`: 7
    /// * `1`: 8
    /// * `2`: 9
    /// * `3`: J
    /// * `4`: Q
    /// * `5`: K
    /// * `6`: X
    /// * `7`: A
    /// * `>=8`: panics
    pub fn from_n(n: u32) -> Self {
        if n >= 8 { panic!("Invalid rank number: {}", n); }
        Rank(1 << n)
    }

    /// Returns a character representing the given rank
    pub fn to_string(self) -> String {
        match self {
            RANK_7 => "7",
            RANK_8 => "8",
            RANK_9 => "9",
            RANK_J => "J",
            RANK_Q => "Q",
            RANK_K => "K",
            RANK_X => "X",
            RANK_A => "A",
            _ => "?",
        }.to_string()
    }
}

/// Represents a single card
#[derive(PartialEq,Clone,Copy,Debug)]
pub struct Card(u32);

// TODO: Add card constants? (8 of heart, Queen of spades, ...?)

impl rustc_serialize::Encodable for Card {
    fn encode<S: rustc_serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        self.0.encode(s)
    }
}

impl Card {
    /// Returns the card number (from 0 to 31)
    pub fn id(self) -> u32 {
        let mut i = 0;
        let Card(mut v) = self;
        while v != 0 {
            i+=1;
            v = v>>1;
        }

        i-1
    }

    /// Returns an invalid card
    pub fn null() -> Self {
        Card(0)
    }

    /// Returns the card corresponding to the given number
    pub fn from_id(id: u32) -> Self {
        if id > 31 { panic!("invalid card id"); }
        Card(1 << id)
    }

    /// Returns the card's rank
    pub fn rank(self) -> Rank {
        let Card(mut v) = self;
        let mut r: u32 = 0;
        let Rank(mask) = RANK_MASK;

        r |= mask & v;
        v = v >> 8;
        r |= mask & v;
        v = v >> 8;
        r |= mask & v;
        v = v >> 8;
        r |= v;

        Rank(r)
    }

    /// Returns the card's suit
    pub fn suit(self) -> Suit {
        let Card(v) = self;
        let Rank(r) = self.rank();
        Suit(v / r)
    }

    /// Returns a string representation of the card
    pub fn to_string(self) -> String {
        let r = self.rank();
        let s = self.suit();
        r.to_string() + &s.to_string()
    }

    /// Creates a card from the given suit and rank
    pub fn new(suit: Suit, rank: Rank) -> Self {
        let Suit(s) = suit;
        let Rank(r) = rank;

        Card(s * r)
    }
}

/// Represents an unordered set of cards
#[derive(PartialEq,Clone,Copy)]
pub struct Hand(u32);

impl rustc_serialize::Encodable for Hand {
    fn encode<S: rustc_serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        self.0.encode(s)
    }
}

impl Hand {
    /// Returns an empty hand.
    pub fn new() -> Self {
        Hand(0)
    }

    /// Add `card` to `self`.
    ///
    /// No effect if `self` already contains `card`.
    pub fn add(&mut self, card: Card) -> &mut Hand {
        self.0 |= card.0;
        self
    }

    /// Removes `card` from `self`.
    ///
    /// No effect if `self` does not contains `card`.
    pub fn remove(&mut self, card: Card) {
        self.0 &= !card.0;
    }

    /// Remove all cards from `self`.
    pub fn clean(&mut self) {
        *self = Hand::new();
    }

    /// Returns `true` if `self` contains `card`.
    pub fn has(self, card: Card) -> bool {
        (self.0 & card.0) != 0
    }

    /// Returns `true` if the hand contains any card of the given suit.
    pub fn has_any(self, suit: Suit) -> bool {
        (self.0 & (RANK_MASK.0 * suit.0)) != 0
    }

    /// Returns `true` if `self` contains no card.
    pub fn is_empty(self) -> bool {
        self.0 == 0
    }

    /// Returns a card from `self`.
    ///
    /// Returns an invalid card if `self` is empty.
    pub fn get_card(self) -> Card {
        if self.is_empty() {
            return Card(0);
        }

        let Hand(h) = self;
        // Finds the rightmost bit, shifted to the left by 1.
        // let n = 1 << (h.trailing_zeroes());
        let n = Wrapping(h ^ (h - 1)) + Wrapping(1);
        if n.0 == 0 {
            // We got an overflow. This means the desired bit it the leftmost one.
            Card::from_id(31)
        } else {
            // We just need to shift it back.
            Card(n.0 >> 1)
        }
    }

    /// Returns the cards contained in `self` as a `Vec`.
    pub fn list(self) -> Vec<Card> {
        let mut cards = Vec::new();
        let mut h = self;

        while !h.is_empty() {
            let c = h.get_card();
            h.remove(c);
            cards.push(c);
        }

        cards
    }

    /// Returns the number of cards in `self`.
    pub fn size(self) -> usize {
        self.list().len()
    }
}

impl ToString for Hand {
    /// Returns a string representation of `self`.
    fn to_string(&self) -> String {
        let mut s = "[".to_string();

        for c in (*self).list().iter() {
            s = s + &c.to_string();
            s = s +",";
        }

        s + "]"
    }
}

/// A deck of cards.
pub struct Deck{
    cards: Vec<Card>,
}

impl Deck {
    /// Returns a full, sorted deck of 32 cards.
    pub fn new() -> Self {
        let mut d = Deck{cards:Vec::with_capacity(32)};

        for i in 0..32 {
            d.cards.push(Card::from_id(i));
        }

        d
    }

    /// Shuffle this deck.
    pub fn shuffle(&mut self) {
        self.shuffle_from(thread_rng());
    }

    /// Shuffle this deck with the given random seed.
    ///
    /// Result is determined by the seed.
    pub fn shuffle_seeded(&mut self, seed: &[u32]) {
        let mut rng = IsaacRng::new_unseeded();
        rng.reseed(seed);
        self.shuffle_from(rng);
    }

    fn shuffle_from<RNG: Rng>(&mut self, mut rng: RNG) {
        rng.shuffle(&mut self.cards[..]);
    }

    /// Draw the top card from the deck.
    ///
    /// # Panics
    /// If `self` is empty.
    pub fn draw(&mut self) -> Card {
        self.cards.pop().expect("deck is empty")
    }

    /// Returns `true` if this deck is empty.
    pub fn is_empty(&self) -> bool {
        self.cards.is_empty()
    }

    /// Returns the number of cards left in this deck.
    pub fn len(&self) -> usize {
        self.cards.len()
    }

    /// Deal `n` cards to each hand.
    ///
    /// # Panics
    /// If `self.len() < 4 * n`
    pub fn deal_each(&mut self, hands: &mut [Hand; 4], n: usize) {
        if self.len() < 4*n {
            panic!("Deck has too few cards!");
        }

        for hand in hands.iter_mut() {
            for _ in 0..n {
                hand.add(self.draw());
            }
        }
    }
}

impl ToString for Deck {
    fn to_string(&self) -> String {
        let mut s = "[".to_string();

        for c in self.cards.iter() {
            s = s + &c.to_string();
            s = s +",";
        }

        s + "]"
    }
}

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

    #[test]
    fn test_cards() {
        for i in 0..32 {
            let card = Card::from_id(i);
            assert!(i == card.id());
        }

        for s in 0..4 {
            let suit = Suit::from_n(s);
            for r in 0..8 {
                let rank = Rank::from_n(r);
                let card = Card::new(suit, rank);
                assert!(card.rank() == rank);
                assert!(card.suit() == suit);
            }
        }
    }

    #[test]
    fn test_hand() {
        let mut hand = Hand::new();

        let cards: Vec<Card> = vec![
            Card::new(HEART, RANK_7),
            Card::new(HEART, RANK_8),
            Card::new(SPADE, RANK_9),
            Card::new(SPADE, RANK_J),
            Card::new(CLUB, RANK_Q),
            Card::new(CLUB, RANK_K),
            Card::new(DIAMOND, RANK_X),
            Card::new(DIAMOND, RANK_A),
        ];

        assert!(hand.is_empty());

        for card in cards.iter() {
            assert!(!hand.has(*card));
            hand.add(*card);
            assert!(hand.has(*card));
        }

        assert!(hand.size() == cards.len());

        for card in cards.iter() {
            assert!(hand.has(*card));
            hand.remove(*card);
            assert!(!hand.has(*card));
        }
    }

    #[test]
    fn test_deck() {
        let mut deck = Deck::new();
        deck.shuffle();

        assert!(deck.len() == 32);

        let mut count = [0; 32];
        while !deck.is_empty() {
            let card = deck.draw();
            count[card.id() as usize] += 1;
        }

        for c in count.iter() {
            assert!(*c == 1);
        }
    }
}

#[cfg(feature="use_bench")]
mod benchs {
    use ::test::Bencher;
    use ::deal_seeded_hands;

    #[bench]
    fn bench_deal(b: &mut Bencher) {
        let seed = &[1,2,3,4,5];
        b.iter(|| {
            deal_seeded_hands(seed);
        });
    }

    #[bench]
    fn bench_add(b: &mut Bencher) {
        let seed = &[1,2,3,4,5];
        let hands = deal_seeded_hands(seed);
        b.iter(|| {
            let mut hands = hands.clone();
            for hand in hands.iter_mut() {
                for c in hand.list() {
                    hand.remove(c);
                }
            }
        });
    }
}
<commit_msg>Fix doc on cards::Rank<commit_after>//! This module represents a basic, rule-agnostic 32-cards system.

use ::rand::{
    thread_rng,
    Rng,
    IsaacRng,
    SeedableRng
};
use std::num::Wrapping;
use std::string::ToString;
use rustc_serialize;

/// One of the four Suits: Heart, Spade, Diamond, Club
#[derive(PartialEq,Clone,Copy)]
pub struct Suit(u32);

// TODO: Make these associated const when it's stable

/// The Heart suit
pub const HEART: Suit = Suit(1 << 0);
/// The Spade suit
pub const SPADE: Suit = Suit(1 << 8);
/// The Diamond suit
pub const DIAMOND: Suit = Suit(1 << 16);
/// The Club suit
pub const CLUB: Suit = Suit(1 << 24);

impl rustc_serialize::Encodable for Suit {
    fn encode<S: rustc_serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        match *self {
            HEART | SPADE | DIAMOND | CLUB => self.0.encode(s),
            _ => "??".encode(s),
        }
    }
}

impl Suit {
    /// Returns the suit corresponding to the number:
    ///
    /// * `0`: Heart
    /// * `1`: Spade
    /// * `2`: Diamond
    /// * `3`: Club
    /// * `>=4`: panics
    pub fn from_n(n: u32) -> Self {
        if n >= 4 { panic!("Bad suit number"); }
        Suit(1 << 8*n)
    }

    /// Returns a UTF-8 character representing the suit.
    pub fn to_string(self) -> String {
        match self {
            HEART => "♥",
            SPADE => "♠",
            DIAMOND => "♦",
            CLUB => "♣",
            _ => "?",
        }.to_string()
    }
}

/// Rank of a card in a suit
#[derive(PartialEq,Clone,Copy)]
pub struct Rank(u32);
/// 7
pub const RANK_7: Rank = Rank(1 << 0);
/// 8
pub const RANK_8: Rank = Rank(1 << 1);
/// 9
pub const RANK_9: Rank = Rank(1 << 2);
/// Jack
pub const RANK_J: Rank = Rank(1 << 3);
/// Queen
pub const RANK_Q: Rank = Rank(1 << 4);
/// King
pub const RANK_K: Rank = Rank(1 << 5);
/// 10
pub const RANK_X: Rank = Rank(1 << 6);
/// Ace
pub const RANK_A: Rank = Rank(1 << 7);
/// Bit mask over all ranks
pub const RANK_MASK: Rank = Rank(255);

impl Rank {

    /// Returns the rank corresponding to the given number:
    ///
    /// * `0`: 7
    /// * `1`: 8
    /// * `2`: 9
    /// * `3`: J
    /// * `4`: Q
    /// * `5`: K
    /// * `6`: X
    /// * `7`: A
    /// * `>=8`: panics
    pub fn from_n(n: u32) -> Self {
        if n >= 8 { panic!("Invalid rank number: {}", n); }
        Rank(1 << n)
    }

    /// Returns a character representing the given rank
    pub fn to_string(self) -> String {
        match self {
            RANK_7 => "7",
            RANK_8 => "8",
            RANK_9 => "9",
            RANK_J => "J",
            RANK_Q => "Q",
            RANK_K => "K",
            RANK_X => "X",
            RANK_A => "A",
            _ => "?",
        }.to_string()
    }
}

/// Represents a single card
#[derive(PartialEq,Clone,Copy,Debug)]
pub struct Card(u32);

// TODO: Add card constants? (8 of heart, Queen of spades, ...?)

impl rustc_serialize::Encodable for Card {
    fn encode<S: rustc_serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        self.0.encode(s)
    }
}

impl Card {
    /// Returns the card number (from 0 to 31)
    pub fn id(self) -> u32 {
        let mut i = 0;
        let Card(mut v) = self;
        while v != 0 {
            i+=1;
            v = v>>1;
        }

        i-1
    }

    /// Returns an invalid card
    pub fn null() -> Self {
        Card(0)
    }

    /// Returns the card corresponding to the given number
    pub fn from_id(id: u32) -> Self {
        if id > 31 { panic!("invalid card id"); }
        Card(1 << id)
    }

    /// Returns the card's rank
    pub fn rank(self) -> Rank {
        let Card(mut v) = self;
        let mut r: u32 = 0;
        let Rank(mask) = RANK_MASK;

        r |= mask & v;
        v = v >> 8;
        r |= mask & v;
        v = v >> 8;
        r |= mask & v;
        v = v >> 8;
        r |= v;

        Rank(r)
    }

    /// Returns the card's suit
    pub fn suit(self) -> Suit {
        let Card(v) = self;
        let Rank(r) = self.rank();
        Suit(v / r)
    }

    /// Returns a string representation of the card
    pub fn to_string(self) -> String {
        let r = self.rank();
        let s = self.suit();
        r.to_string() + &s.to_string()
    }

    /// Creates a card from the given suit and rank
    pub fn new(suit: Suit, rank: Rank) -> Self {
        let Suit(s) = suit;
        let Rank(r) = rank;

        Card(s * r)
    }
}

/// Represents an unordered set of cards
#[derive(PartialEq,Clone,Copy)]
pub struct Hand(u32);

impl rustc_serialize::Encodable for Hand {
    fn encode<S: rustc_serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        self.0.encode(s)
    }
}

impl Hand {
    /// Returns an empty hand.
    pub fn new() -> Self {
        Hand(0)
    }

    /// Add `card` to `self`.
    ///
    /// No effect if `self` already contains `card`.
    pub fn add(&mut self, card: Card) -> &mut Hand {
        self.0 |= card.0;
        self
    }

    /// Removes `card` from `self`.
    ///
    /// No effect if `self` does not contains `card`.
    pub fn remove(&mut self, card: Card) {
        self.0 &= !card.0;
    }

    /// Remove all cards from `self`.
    pub fn clean(&mut self) {
        *self = Hand::new();
    }

    /// Returns `true` if `self` contains `card`.
    pub fn has(self, card: Card) -> bool {
        (self.0 & card.0) != 0
    }

    /// Returns `true` if the hand contains any card of the given suit.
    pub fn has_any(self, suit: Suit) -> bool {
        (self.0 & (RANK_MASK.0 * suit.0)) != 0
    }

    /// Returns `true` if `self` contains no card.
    pub fn is_empty(self) -> bool {
        self.0 == 0
    }

    /// Returns a card from `self`.
    ///
    /// Returns an invalid card if `self` is empty.
    pub fn get_card(self) -> Card {
        if self.is_empty() {
            return Card(0);
        }

        let Hand(h) = self;
        // Finds the rightmost bit, shifted to the left by 1.
        // let n = 1 << (h.trailing_zeroes());
        let n = Wrapping(h ^ (h - 1)) + Wrapping(1);
        if n.0 == 0 {
            // We got an overflow. This means the desired bit it the leftmost one.
            Card::from_id(31)
        } else {
            // We just need to shift it back.
            Card(n.0 >> 1)
        }
    }

    /// Returns the cards contained in `self` as a `Vec`.
    pub fn list(self) -> Vec<Card> {
        let mut cards = Vec::new();
        let mut h = self;

        while !h.is_empty() {
            let c = h.get_card();
            h.remove(c);
            cards.push(c);
        }

        cards
    }

    /// Returns the number of cards in `self`.
    pub fn size(self) -> usize {
        self.list().len()
    }
}

impl ToString for Hand {
    /// Returns a string representation of `self`.
    fn to_string(&self) -> String {
        let mut s = "[".to_string();

        for c in (*self).list().iter() {
            s = s + &c.to_string();
            s = s +",";
        }

        s + "]"
    }
}

/// A deck of cards.
pub struct Deck{
    cards: Vec<Card>,
}

impl Deck {
    /// Returns a full, sorted deck of 32 cards.
    pub fn new() -> Self {
        let mut d = Deck{cards:Vec::with_capacity(32)};

        for i in 0..32 {
            d.cards.push(Card::from_id(i));
        }

        d
    }

    /// Shuffle this deck.
    pub fn shuffle(&mut self) {
        self.shuffle_from(thread_rng());
    }

    /// Shuffle this deck with the given random seed.
    ///
    /// Result is determined by the seed.
    pub fn shuffle_seeded(&mut self, seed: &[u32]) {
        let mut rng = IsaacRng::new_unseeded();
        rng.reseed(seed);
        self.shuffle_from(rng);
    }

    fn shuffle_from<RNG: Rng>(&mut self, mut rng: RNG) {
        rng.shuffle(&mut self.cards[..]);
    }

    /// Draw the top card from the deck.
    ///
    /// # Panics
    /// If `self` is empty.
    pub fn draw(&mut self) -> Card {
        self.cards.pop().expect("deck is empty")
    }

    /// Returns `true` if this deck is empty.
    pub fn is_empty(&self) -> bool {
        self.cards.is_empty()
    }

    /// Returns the number of cards left in this deck.
    pub fn len(&self) -> usize {
        self.cards.len()
    }

    /// Deal `n` cards to each hand.
    ///
    /// # Panics
    /// If `self.len() < 4 * n`
    pub fn deal_each(&mut self, hands: &mut [Hand; 4], n: usize) {
        if self.len() < 4*n {
            panic!("Deck has too few cards!");
        }

        for hand in hands.iter_mut() {
            for _ in 0..n {
                hand.add(self.draw());
            }
        }
    }
}

impl ToString for Deck {
    fn to_string(&self) -> String {
        let mut s = "[".to_string();

        for c in self.cards.iter() {
            s = s + &c.to_string();
            s = s +",";
        }

        s + "]"
    }
}

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

    #[test]
    fn test_cards() {
        for i in 0..32 {
            let card = Card::from_id(i);
            assert!(i == card.id());
        }

        for s in 0..4 {
            let suit = Suit::from_n(s);
            for r in 0..8 {
                let rank = Rank::from_n(r);
                let card = Card::new(suit, rank);
                assert!(card.rank() == rank);
                assert!(card.suit() == suit);
            }
        }
    }

    #[test]
    fn test_hand() {
        let mut hand = Hand::new();

        let cards: Vec<Card> = vec![
            Card::new(HEART, RANK_7),
            Card::new(HEART, RANK_8),
            Card::new(SPADE, RANK_9),
            Card::new(SPADE, RANK_J),
            Card::new(CLUB, RANK_Q),
            Card::new(CLUB, RANK_K),
            Card::new(DIAMOND, RANK_X),
            Card::new(DIAMOND, RANK_A),
        ];

        assert!(hand.is_empty());

        for card in cards.iter() {
            assert!(!hand.has(*card));
            hand.add(*card);
            assert!(hand.has(*card));
        }

        assert!(hand.size() == cards.len());

        for card in cards.iter() {
            assert!(hand.has(*card));
            hand.remove(*card);
            assert!(!hand.has(*card));
        }
    }

    #[test]
    fn test_deck() {
        let mut deck = Deck::new();
        deck.shuffle();

        assert!(deck.len() == 32);

        let mut count = [0; 32];
        while !deck.is_empty() {
            let card = deck.draw();
            count[card.id() as usize] += 1;
        }

        for c in count.iter() {
            assert!(*c == 1);
        }
    }
}

#[cfg(feature="use_bench")]
mod benchs {
    use ::test::Bencher;
    use ::deal_seeded_hands;

    #[bench]
    fn bench_deal(b: &mut Bencher) {
        let seed = &[1,2,3,4,5];
        b.iter(|| {
            deal_seeded_hands(seed);
        });
    }

    #[bench]
    fn bench_add(b: &mut Bencher) {
        let seed = &[1,2,3,4,5];
        let hands = deal_seeded_hands(seed);
        b.iter(|| {
            let mut hands = hands.clone();
            for hand in hands.iter_mut() {
                for c in hand.list() {
                    hand.remove(c);
                }
            }
        });
    }
}
<|endoftext|>


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

use metadata;

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

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

enum ParserState {
  Marker,
  Metadata,
  Frame,
}

pub struct Stream {
  info: StreamInfo,
  pub metadata: Vec<Metadata>,
  pub frames: Vec<Frame>,
  state: ParserState,
}

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

impl Stream {
  pub fn new() -> Stream {
    Stream {
      info: StreamInfo::new(),
      metadata: Vec::new(),
      frames: Vec::new(),
      state: ParserState::Marker,
    }
  }

  pub fn info(&self) -> StreamInfo {
    self.info
  }

  pub fn from_file(filename: &str) -> io::Result<Stream> {
    File::open(filename).and_then(|file| {
      let mut reader   = ReadStream::new(file);
      let mut is_error = false;
      let mut stream   = Stream {
        info: StreamInfo::new(),
        metadata: Vec::new(),
        frames: Vec::new(),
        state: ParserState::Marker,
      };

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

            break;
          }
        }
      }

      if !is_error {
        Ok(stream)
      } else {
        let error_str = format!("parser: couldn't parse the given file {}",
                                filename);

        Err(io::Error::new(io::ErrorKind::InvalidData, error_str))
      }
    })
  }

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

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

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

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

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

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

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

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

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

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

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

  pub fn handle<S: StreamProducer>(&mut self, stream: &mut S)
                                   -> Result<(), ErrorKind> {
    stream.parse(|input| {
      match self.state {
        ParserState::Marker   => self.handle_marker(input),
        ParserState::Metadata => self.handle_metadata(input),
        ParserState::Frame    => self.handle_frame(input),
      }
    })
  }
}
<commit_msg>Add a general function for handling StreamProducer<commit_after>use nom;
use nom::{Err, IResult};

use metadata;

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

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

enum ParserState {
  Marker,
  Metadata,
  Frame,
}

pub struct Stream {
  info: StreamInfo,
  pub metadata: Vec<Metadata>,
  pub frames: Vec<Frame>,
  state: ParserState,
}

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

impl Stream {
  pub fn new() -> Stream {
    Stream {
      info: StreamInfo::new(),
      metadata: Vec::new(),
      frames: Vec::new(),
      state: ParserState::Marker,
    }
  }

  pub fn info(&self) -> StreamInfo {
    self.info
  }

  pub fn from_file(filename: &str) -> io::Result<Stream> {
    File::open(filename).and_then(|file| {
      let mut reader   = ReadStream::new(file);
      let mut is_error = false;
      let mut stream   = Stream {
        info: StreamInfo::new(),
        metadata: Vec::new(),
        frames: Vec::new(),
        state: ParserState::Marker,
      };

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

            break;
          }
        }
      }

      if !is_error {
        Ok(stream)
      } else {
        let error_str = format!("parser: couldn't parse the given file {}",
                                filename);

        Err(io::Error::new(io::ErrorKind::InvalidData, error_str))
      }
    })
  }

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

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

          break;
        }
      }
    }

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

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

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

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

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

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

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

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

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

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

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

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

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


<commit_before>#![feature(convert)]
#![feature(slice_patterns)]
#![feature(collections)]
use std::env;
use std::fs::File;
use std::io::Read;
use std::collections::HashMap;

#[derive(Clone)]
enum Expr {
  Int(i64),
  Str(String)
}

struct VM<'a> {
  stack: Vec<Expr>,
  instructions: Vec<&'a str>,
  locals: HashMap<&'a str, Expr>,
}

impl<'a> VM<'a> {
  pub fn new(instructions: Vec<&'a str>) -> VM {
    VM {
      stack: Vec::new(),
      instructions: instructions,
      locals: HashMap::new(),
    }
  }

  fn unsafe_pop(&mut self) -> Expr {
    match self.stack.pop() {
      Some(expr) => expr,
      None => panic!("VM error: stack is empty"),
    }
  }

  pub fn run(&mut self) {
    // just some aliases for brevity
    let len = self.instructions.len();

    // VM variables (might be moved back to the struct itself)
    let mut ip = 0; // instruction pointer
    let mut carry = false;

    while ip < len {
      let instr = self.instructions[ip];
      ip += 1;
      match instr.split(" ").collect::<Vec<_>>().as_slice() {
        ["push", "int", n] => self.stack.push(Expr::Int(n.parse::<i64>().unwrap())),
        ["push", "str", n] => self.stack.push(Expr::Str(String::from_str(n))),

        ["dup"] => {
          let expr = self.unsafe_pop();
          self.stack.push(expr.clone());
          self.stack.push(expr);
        },

        // convert to string
        ["strconv", "int"] => if let Some(&Expr::Int(arg)) = self.stack.last() {
          self.stack.push(Expr::Str(arg.to_string()));
        } else {
          panic!("VM error: cannot convert int to string");
        },

        // how = "carry" | "always"
        ["jump", how, n] => {
          let new_ip = n.parse::<usize>().unwrap();

          if new_ip < len {
            // only check carry if we are conditionally jumping
            if how != "carry" || carry {
              ip = new_ip;
            }
            // only reset carry if it was used
            if how == "carry" {
              carry = false;
            }
          } else {
            panic!("VM error: trying to jump past end of bytecode ({} > {})", new_ip, len);
          }
        },

        ["carry", "set", val] => carry = val == "true",
        ["carry", "invert"] => carry = !carry,

        ["call", "say"] => if let Some(Expr::Str(arg)) = self.stack.pop() {
          println!("hey {}", arg);
        } else {
          panic!("VM error: incorrect arguments to `say`");
        },

        // NOTE: it's stack[*-1] OP stack[*-2]
        // which means if have stack=[1, 2]
        // you'll have 2 OP 1
        /// XXX this should JUST be a call!
        ["math", op] => if let
            (Some(Expr::Int(arg1)), Some(Expr::Int(arg2)))
            =
            (self.stack.pop(), self.stack.pop()) {
          let value = match op {
            "+" => arg1 + arg2,
            "-" => arg1 + arg2,
            //"/" => TODO. this should have very specific rules...
            "*" => arg1 * arg2,
            _ => panic!("VM error: unrecognized `op` operator: {}", op),
          };
          self.stack.push(Expr::Int(value));
        } else {
          panic!("VM error: not enough arguments to `add`");
        },

        // same note about "2 OP 1"
        // XXX same note about how this should be a `call`
        ["cmp", op] => if let
            (Some(Expr::Int(arg1)), Some(Expr::Int(arg2)))
            =
            (self.stack.pop(), self.stack.pop()) {
          carry = match op {
            "<" => arg1 < arg2,
            ">" => arg1 > arg2,
            "<=" => arg1 <= arg2,
            ">=" => arg1 >= arg2,
            "=" => arg1 == arg2,
            _ => panic!("VM error: unrecognized `cmp` operator: {}", op),
          };
        } else {
          panic!("VM error: not enough arguments to `cmp`");
        },

        // TODO this *shouldn't* be an identifier
        //      the backend should transform SSAF to tons of load/store
        //      (probably)
        //      (see backend#1)
        ["local", "load", name] => match self.locals.get(name) {
          Some(expr) => self.stack.push(expr.clone()),
          None       => panic!("VM error: unknown local variable {}", name),
        },

        ["local", "store", name] => if let Some(arg) = self.stack.pop() {
          let _ = self.locals.insert(name, arg);
        } else {
          panic!("VM error: not enough arguments for `local store`");
        },

        [instr, ..] => panic!("VM error: no such instruction {}", instr),
        [..] => panic!("VM error: Unrecognized instruction!"),
      }
    }
  }
}

fn main() {
	if let Some(path) = env::args().nth(1) {
		println!("Loading file {}", path);

    match File::open(&path) {
      Ok(mut file) => {
        let mut content = String::new();
        if let Ok(_) = file.read_to_string(&mut content) {
          // remove trailing newlines, split by line
          let instructions = content.trim_matches('\n').split('\n').collect();
          let mut vm = VM::new(instructions);
          vm.run();
        }
      },
      Err(err) => {
        panic!("Can't read file {} (error: {})", path, err);
      }
    }
	} else {
    panic!("Please give a file argument");
  }

  //     let path = Path::new("chry.fa");
  // let mut file = BufferedReader::new(File::open(&path));
  // for line in file.lines() {
  //  print!("{}", line.unwrap());
  //      }
}
<commit_msg>Implement comments & labels & change syntax for convert<commit_after><|endoftext|>


<commit_before>use std::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign};

#[derive(Debug, Copy, Clone)]
pub struct Vec3 {
  pub i : f64,
  pub j : f64,
  pub k : f64,
}

impl Vec3 {
  pub fn length(&self) -> f64 {
    (self.i * self.i + self.j * self.j + self.k * self.k).sqrt()
  }
}

impl Add for Vec3 {
  type Output = Vec3;
  fn add(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i + other.i, j: self.j + other.j, k: self.k + other.k}
  }
}

impl AddAssign for Vec3 {
  fn add_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i + other.i,
      j: self.j + other.j,
      k: self.k + other.k,
    };
  }
}

impl Sub for Vec3 {
  type Output = Vec3;
  fn sub(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i - other.i, j: self.j - other.j, k: self.k - other.k}
  }
}

impl SubAssign for Vec3 {
  fn sub_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i - other.i,
      j: self.j - other.j,
      k: self.k - other.k,
    }
  }
}

impl Mul for Vec3 {
  type Output = Vec3;
  fn mul(self, rhs: Vec3) -> Vec3 {
    Vec3 {i: self.i * rhs.i, j: self.j * rhs.j, k: self.k * rhs.k}
  }
}

impl MulAssign for Vec3 {
  fn mul_assign(&mut self, rhs: Vec3) {
    *self = Vec3 {
      i: self.i * rhs.i,
      j: self.j * rhs.j,
      k: self.k * rhs.k,
    }
  }
}
<commit_msg>Add test module and four tests<commit_after>use std::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign};

#[derive(Debug, Copy, Clone)]
pub struct Vec3 {
  pub i : f64,
  pub j : f64,
  pub k : f64,
}

impl Vec3 {
  pub fn length(&self) -> f64 {
    (self.i * self.i + self.j * self.j + self.k * self.k).sqrt()
  }
}

impl Add for Vec3 {
  type Output = Vec3;
  fn add(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i + other.i, j: self.j + other.j, k: self.k + other.k}
  }
}

impl AddAssign for Vec3 {
  fn add_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i + other.i,
      j: self.j + other.j,
      k: self.k + other.k,
    };
  }
}

impl Sub for Vec3 {
  type Output = Vec3;
  fn sub(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i - other.i, j: self.j - other.j, k: self.k - other.k}
  }
}

impl SubAssign for Vec3 {
  fn sub_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i - other.i,
      j: self.j - other.j,
      k: self.k - other.k,
    }
  }
}

impl Mul for Vec3 {
  type Output = Vec3;
  fn mul(self, rhs: Vec3) -> Vec3 {
    Vec3 {i: self.i * rhs.i, j: self.j * rhs.j, k: self.k * rhs.k}
  }
}

impl MulAssign for Vec3 {
  fn mul_assign(&mut self, rhs: Vec3) {
    *self = Vec3 {
      i: self.i * rhs.i,
      j: self.j * rhs.j,
      k: self.k * rhs.k,
    }
  }
}

#[cfg(test)]
mod should {
  use super::Vec3;
  #[test]
  fn add() {
    let v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let sum = v1 + v2;
    assert_eq!(sum.i, 3.0);
    assert_eq!(sum.j, 3.0);
    assert_eq!(sum.k, 3.0);
  }
  #[test]
  fn add_assign() {
    let mut v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1 += v2;
    assert_eq!(v1.i, 3.0);
    assert_eq!(v1.j, 3.0);
    assert_eq!(v1.k, 3.0);
  }
  #[test]
  fn subtract() {
    let v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let diff = v1 - v2;
    assert_eq!(diff.i, -1.0);
    assert_eq!(diff.j, -1.0);
    assert_eq!(diff.k, -1.0);
  }
  #[test]
  fn subtract_assign() {
    let mut v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1 -= v2;
    assert_eq!(v1.i, -1.0);
    assert_eq!(v1.j, -1.0);
    assert_eq!(v1.k, -1.0);
  }
}<|endoftext|>


<commit_before>//! Define trait for vectors

use std::iter::Sum;
use ndarray::{LinalgScalar, ArrayBase, Data, Dimension};
use num_traits::float::Float;

/// Methods for vectors
pub trait Vector {
    type Scalar;
    /// rename of norm_l2
    fn norm(&self) -> Self::Scalar {
        self.norm_l2()
    }
    /// L-1 norm
    fn norm_l1(&self) -> Self::Scalar;
    /// L-2 norm
    fn norm_l2(&self) -> Self::Scalar;
    /// maximum norm
    fn norm_max(&self) -> Self::Scalar;
}

impl<A, S, D, T> Vector for ArrayBase<S, D>
    where A: LinalgScalar + Squared<Output = T>,
          T: Float + Sum,
          S: Data<Elem = A>,
          D: Dimension
{
    type Scalar = T;
    fn norm_l1(&self) -> Self::Scalar {
        self.iter().map(|x| x.sq_abs()).sum()
    }
    fn norm_l2(&self) -> Self::Scalar {
        self.iter().map(|x| x.squared()).sum::<T>().sqrt()
    }
    fn norm_max(&self) -> Self::Scalar {
        self.iter().fold(T::zero(), |f, &val| {
            let v = val.sq_abs();
            if f > v { f } else { v }
        })
    }
}

pub trait Squared {
    type Output;
    fn squared(&self) -> Self::Output;
    fn sq_abs(&self) -> Self::Output;
}

impl<A: Float> Squared for A {
    type Output = A;
    fn squared(&self) -> A {
        *self * *self
    }
    fn sq_abs(&self) -> A {
        self.abs()
    }
}
<commit_msg>Implement Outer<commit_after>//! Define trait for vectors

use std::iter::Sum;
use ndarray::{Array, NdFloat, Ix1, Ix2, LinalgScalar, ArrayBase, Data, Dimension};
use num_traits::float::Float;
use super::outer::ImplOuter;

/// Methods for vectors
pub trait Vector {
    type Scalar;
    /// rename of norm_l2
    fn norm(&self) -> Self::Scalar {
        self.norm_l2()
    }
    /// L-1 norm
    fn norm_l1(&self) -> Self::Scalar;
    /// L-2 norm
    fn norm_l2(&self) -> Self::Scalar;
    /// maximum norm
    fn norm_max(&self) -> Self::Scalar;
}

impl<A, S, D, T> Vector for ArrayBase<S, D>
    where A: LinalgScalar + Squared<Output = T>,
          T: Float + Sum,
          S: Data<Elem = A>,
          D: Dimension
{
    type Scalar = T;
    fn norm_l1(&self) -> Self::Scalar {
        self.iter().map(|x| x.sq_abs()).sum()
    }
    fn norm_l2(&self) -> Self::Scalar {
        self.iter().map(|x| x.squared()).sum::<T>().sqrt()
    }
    fn norm_max(&self) -> Self::Scalar {
        self.iter().fold(T::zero(), |f, &val| {
            let v = val.sq_abs();
            if f > v { f } else { v }
        })
    }
}

pub trait Squared {
    type Output;
    fn squared(&self) -> Self::Output;
    fn sq_abs(&self) -> Self::Output;
}

impl<A: Float> Squared for A {
    type Output = A;
    fn squared(&self) -> A {
        *self * *self
    }
    fn sq_abs(&self) -> A {
        self.abs()
    }
}

pub fn outer<A, S1, S2>(a: &ArrayBase<S1, Ix1>, b: &ArrayBase<S2, Ix1>) -> Array<A, Ix2>
    where A: NdFloat + ImplOuter,
          S1: Data<Elem = A>,
          S2: Data<Elem = A>
{
    let m = a.len();
    let n = b.len();
    let mut ab = Array::zeros((m, n));
    ImplOuter::outer(m,
                     n,
                     a.as_slice_memory_order().unwrap(),
                     b.as_slice_memory_order().unwrap(),
                     ab.as_slice_memory_order_mut().unwrap());
    ab
}
<|endoftext|>