<commit_before>
use std::str;
use std::io::{self, Read, Write};
use std::fs::File;
use std::path::Path;

use hyper::{Get, Post, StatusCode, RequestUri, Decoder, Encoder, Next};
use hyper::header::{ContentLength, ContentType};
use hyper::net::HttpStream;

use hyper::server::Server;
use hyper::server::Handler as HyperHandler;
use hyper::server::Request as HyperRequest;
use hyper::server::Response as HyperResponse;
use hyper::method::Method;
use hyper::version::HttpVersion;

use std::result::Result as StdResult;
use std::error::Error as StdError;
use std::sync::Arc;
use std::marker::Reflect;
use std::clone::Clone;
use std::marker::PhantomData;

use mime_types::Types as MimeTypes;

pub use typemap::Key;
pub use hyper::header::Headers;
pub use hyper::header;
pub use hyper::mime;
pub use request::Request;
pub use response::Response;
pub use router::Router;
pub use srouter::SRouter;
pub use shandler::SHandler;

#[derive(Debug, PartialEq, Clone)]
pub enum Error {
    NotFound(String),
    InvalidConfig,
    InvalidRouterConfig,
    FileNotExist,
    ShouldRedirect(String),
    Prompt(String),
    Warning(String),
    Fatal(String),
    Custom(String),
}

pub type Result<T> = ::std::result::Result<T, Error>;

#[derive(Clone)]
pub struct ReqPathParams;

pub trait SModule {
    fn before(&self, &mut Request) -> Result<()>;

    fn after(&self, &Request, &mut Response) -> Result<()>;

    // here add routers ....
    fn router(&self, &mut SRouter) -> Result<()>;
    // fn router(&self, SRouter) -> Result<SRouter>;

}

pub trait SAppWrapper {
    fn before(&self, &mut Request) -> Result<()>;

    fn after(&self, &Request, &mut Response) -> Result<()>;

}

// later will add more fields
pub struct SApp<T: SModule + Send + 'static, W: SAppWrapper + Send + 'static> {
    pub address: String,
    pub port:    u32,
    // for app entry, global middeware
    pub wrapper: Option<W>,
    // for actually use to recognize
    pub routers: Router,
    // do simple static file service?
    pub static_service: bool,
    // marker for type T
    pub _marker: PhantomData<T>,
}

impl<T, W> SApp<T, W>
    where   T: SModule + Send + Sync + Reflect + Clone + 'static,
            W: SAppWrapper + Send + Sync + Reflect + Clone + 'static
    {
    pub fn new() -> SApp<T, W> {
        SApp {
            address: String::new(),
            port: 0,
            wrapper: None,
            routers: Router::new(),
            static_service: true,
            _marker: PhantomData
        }
    }

    pub fn run(self) {

        let listen_addr = self.address.clone() + ":" + &self.port.to_string();
        let arc_sapp = Arc::new(Box::new(self));

        let server = Server::http(&listen_addr.parse().unwrap()).unwrap();
        let _guard = server.handle(move |_| {
            RequestHandler::new(arc_sapp.clone())
        });
    }

    pub fn with_wrapper(&mut self, w: W) -> &mut Self {
        self.wrapper = Some(w);
        self
    }

    pub fn address(&mut self, address: &str) -> &mut Self {
        self.address = address.to_owned();
        self
    }

    pub fn port(&mut self, port: u32) -> &mut Self {
        self.port = port;
        self
    }

    pub fn static_service(&mut self, open: bool) -> &mut Self {
        self.static_service = open;
        self
    }

    // add methods of this smodule
    // prefix:  such as '/user'
    pub fn add_module(&mut self, sm: T) -> &mut Self {

        let mut router = SRouter::new();
        // get the sm router
        // pass self.router in
        sm.router(&mut router).unwrap();
        // combile this router to global big router
        // create a new closure, containing
        //      0. execute sapp.before();
        //      1. execute sm.before();
        //      2. execute a_router map pair value part function;
        //      3. execute sm.after();
        //      4. execute sapp.after();
        // fill the self.routers finally
        // assign this new closure to the routers router map pair  prefix + url part

        for (method, handler_vec) in router.into_router() {
            // add to wrapped router
            for &(glob, ref handler) in handler_vec.iter() {
                let method = method.clone();
                let glob = glob.clone();
                let handler = handler.clone();
                let sm = sm.clone();
                let wrapper = self.wrapper.clone().unwrap();
                self.routers.route(method, glob, Arc::new(Box::new(move |req: &mut Request| -> Result<Response> {
                    wrapper.before(req)?;
                    sm.before(req)?;
                    let mut response: Response = handler.handle(req)?;
                    sm.after(req, &mut response)?;
                    wrapper.after(req, &mut response)?;
                    Ok(response)
                })));
            }
        }

        // self.modules.push(sm);

        self
    }
}

fn simple_file_get(path: &str) -> Result<Vec<u8>> {
    let container = "static/".to_owned();
    match File::open(container + path) {
        Ok(ref mut file) => {
            let mut s: Vec<u8> = vec![];
            file.read_to_end(&mut s).unwrap_or(0);
            Ok(s)
        },
        Err(_) => Err(Error::FileNotExist)
    }
}

pub struct RequestHandler<
        T: SModule + Send + Sync + Reflect + Clone + 'static,
        W: SAppWrapper + Send + Sync + Reflect + Clone + 'static> {
    // router, keep the original handler function
    // pub router: SRouter,
    // wrapped router, keep the wrapped handler function
    // for actually use to recognize
    pub sapp: Arc<Box<SApp<T, W>>>,
    pub path: String,
    pub method: Method,
    pub version: HttpVersion,
    pub headers: Headers,
    pub buf: Vec<u8>,
    pub body: String,
    pub has_body: bool,
    // response deliver
    pub response: Result<Response>,
    pub static_file: Option<Vec<u8>>,
}

impl<T, W> RequestHandler<T, W>
where   T: SModule + Send + Sync + Reflect + Clone + 'static,
        W: SAppWrapper + Send + Sync + Reflect + Clone + 'static
{
    pub fn new(sapp: Arc<Box<SApp<T, W>>>) -> RequestHandler<T, W> {
        RequestHandler {
            sapp: sapp,
            path: String::new(),
            method: Default::default(),
            version: Default::default(),
            headers: Default::default(),
            buf: vec![0; 2048],
            body: String::new(),
            has_body: false,
            response: Err(Error::NotFound("/".to_owned())),
            static_file: None,
        }
    }

}

impl<T, W> HyperHandler<HttpStream> for RequestHandler<T, W>
where   T: SModule + Send + Sync + Reflect + Clone + 'static,
        W: SAppWrapper + Send + Sync + Reflect + Clone + 'static
 {
    fn on_request(&mut self, req: HyperRequest) -> Next {
        match *req.uri() {
            RequestUri::AbsolutePath(ref path) =>  {
                // if has_body
                if req.headers().get::<ContentLength>().is_some()
                    || req.headers().get::<ContentType>().is_some()
                 {
                    self.path = path.to_owned();
                    self.method = req.method().clone();
                    self.version = req.version().clone();
                    self.headers = req.headers().clone();
                    self.has_body = true;
                    Next::read_and_write()
                }
                else {
                    // if no body
                    let pathstr = &path[..];
                    let pathvec: Vec<&str> = pathstr.split('?').collect();
                    let path = pathvec[0].to_owned();
                    let mut query_string = None;

                    // if has query_string
                    if pathvec.len() > 1 {
                        query_string = Some(pathvec[1].to_owned());
                    }

                    // make swiftrs request from hyper request
                    let mut sreq = Request::new(
                        req.method().clone(),
                        req.version().clone(),
                        req.headers().clone(),
                        path.clone(),
                        query_string);

                    self.response = self.sapp.routers.handle_method(&mut sreq, &path).unwrap();

                    // match self.sapp.routers.handle_method(&mut sreq, &path).unwrap() {
                    //     Ok(response) => self.response = Some(response),
                    //     Err(e) => {
                    //         if e == Error::NotFoundError {
                    //             self.response = None
                    //         }
                    //     }
                    // }

                    Next::write()
                }

                // XXX: Need more work
                // self.response = self.routers.handle_method(&mut sreq, &path).unwrap().ok();

                // TODO: complete it later
                // .unwrap_or_else(||
                    // match req.method {
                    //     method::Options => Ok(self.handle_options(&path)),
                    //     // For HEAD, fall back to GET. Hyper ensures no response body is written.
                    //     method::Head => {
                    //         req.method = method::Get;
                    //         self.handle_method(req, &path).unwrap_or(
                    //             Err(IronError::new(NoRoute, status::NotFound))
                    //         )
                    //     }
                    //     _ => Err(IronError::new(NoRoute, status::NotFound))
                    // }
                // );
                // currently

                // if is_more {
                //     Next::read_and_write()
                // } else {
                //     Next::write()
                // }

                // Next::read_and_write()
                // Next::write()
            },
            _ => Next::write()
        }
    }
    fn on_request_readable(&mut self, transport: &mut Decoder<HttpStream>) -> Next {
        if self.has_body {
            match transport.read(&mut self.buf) {
                Ok(0) => {
                    debug!("Read 0, eof");

                    // TODO: need optimize
                    let pathstr = &self.path[..];
                    let pathvec: Vec<&str> = pathstr.split('?').collect();
                    let path = pathvec[0].to_owned();
                    let mut query_string = None;

                    // if has query_string
                    if pathvec.len() > 1 {
                        query_string = Some(pathvec[1].to_owned());
                    }
                    let mut sreq = Request::new(
                        self.method.clone(),
                        self.version.clone(),
                        self.headers.clone(),
                        path.clone(),
                        query_string);

                    // TODO: optimize this memory copy
                    sreq.set_raw_body(self.body.clone());

                    self.response = self.sapp.routers.handle_method(&mut sreq, &path).unwrap();

                    // match self.sapp.routers.handle_method(&mut sreq, &path).unwrap() {
                    //     Ok(response) => self.response = Some(response),
                    //     Err(e) => {
                    //         if e == Error::NotFoundError {
                    //             self.response = None
                    //         }
                    //     }
                    // }
                    //
                    return Next::write()
                },
                Ok(n) => {
                    self.body.push_str(str::from_utf8(&self.buf[0..n]).unwrap());
                    return Next::read_and_write()
                }
                Err(e) => match e.kind() {
                    io::ErrorKind::WouldBlock => return Next::read_and_write(),
                    _ => {
                        println!("read error {:?}", e);
                        return Next::end()
                    }
                }
            }
        }

        Next::write()
    }

    fn on_response(&mut self, res: &mut HyperResponse) -> Next {

        let mt = MimeTypes::new().unwrap();

        match self.response {
            Ok(ref response) => {
                if let &Some(ref body) = response.body() {
                    // default set content type as html
                    res.headers_mut().set(ContentType::html());

                    // update top level headers to low level headers
                    for header in response.headers().iter() {
                        res.headers_mut()
                            .set_raw(header.name().to_owned(),
                                vec![header.value_string().as_bytes().to_vec()]);
                    }

                    // here, set hyper response status code, and headers
                    res.headers_mut().set(ContentLength(body.len() as u64));
                }
                Next::write()
            },
            Err(ref e) => {
                // Inner Error
                // end
                match e {
                    &Error::NotFound(ref path) => {
                        if self.sapp.static_service {
                            match simple_file_get(path) {
                                Ok(avec) => {
                                    println!("serve file: {}", path);
                                    self.static_file = Some(avec);
                                    // TODO: need jude file mime type according to path
                                    // and set the header
                                    let mt_str = mt.mime_for_path(Path::new(path));
                                    res.headers_mut().set_raw("Content-Type", vec![mt_str.as_bytes().to_vec()])
                                },
                                Err(_) => {
                                    println!("NotFound: {}", path);
                                    res.set_status(StatusCode::NotFound);
                                    res.headers_mut().set(ContentLength("404 Not Found".len() as u64));
                                }
                            }
                        }
                        else {
                            println!("NotFound: {}", path);
                            res.set_status(StatusCode::NotFound);
                            res.headers_mut().set(ContentLength("404 Not Found".len() as u64));
                        }
                    },
                    &Error::Fatal(ref astr) => {
                        println!("fatal error: {}", astr);
                        res.set_status(StatusCode::InternalServerError);
                        return Next::end();
                    },
                    _ => {

                    }

                }

                Next::write()
            }
        }

    }

    fn on_response_writable(&mut self, transport: &mut Encoder<HttpStream>) -> Next {
        match self.response {
            Ok(ref response) => {
                if let &Some(ref body) = response.body() {
                    // write response.body.unwrap() to transport
                    transport.write(body).unwrap();
                }
                Next::end()
            },
            Err(ref e) => {
                match e {
                    &Error::NotFound(ref path) => {
                        if self.sapp.static_service {
                            match self.static_file {
                                Some(ref avec) => {
                                    transport.write(avec).unwrap();
                                },
                                None => {
                                    transport.write("404 Not Found".as_bytes()).unwrap();
                                }
                            }
                        }
                        else {
                            transport.write("404 Not Found".as_bytes()).unwrap();
                        }

                    },
                    _ => {

                    }
                }

                // end
                Next::end()
            }
        }

    }
}
<commit_msg>when serve file, add content length response header.<commit_after>
use std::str;
use std::io::{self, Read, Write};
use std::fs::File;
use std::path::Path;

use hyper::{Get, Post, StatusCode, RequestUri, Decoder, Encoder, Next};
use hyper::header::{ContentLength, ContentType};
use hyper::net::HttpStream;

use hyper::server::Server;
use hyper::server::Handler as HyperHandler;
use hyper::server::Request as HyperRequest;
use hyper::server::Response as HyperResponse;
use hyper::method::Method;
use hyper::version::HttpVersion;

use std::result::Result as StdResult;
use std::error::Error as StdError;
use std::sync::Arc;
use std::marker::Reflect;
use std::clone::Clone;
use std::marker::PhantomData;

use mime_types::Types as MimeTypes;

pub use typemap::Key;
pub use hyper::header::Headers;
pub use hyper::header;
pub use hyper::mime;
pub use request::Request;
pub use response::Response;
pub use router::Router;
pub use srouter::SRouter;
pub use shandler::SHandler;

#[derive(Debug, PartialEq, Clone)]
pub enum Error {
    NotFound(String),
    InvalidConfig,
    InvalidRouterConfig,
    FileNotExist,
    ShouldRedirect(String),
    Prompt(String),
    Warning(String),
    Fatal(String),
    Custom(String),
}

pub type Result<T> = ::std::result::Result<T, Error>;

#[derive(Clone)]
pub struct ReqPathParams;

pub trait SModule {
    fn before(&self, &mut Request) -> Result<()>;

    fn after(&self, &Request, &mut Response) -> Result<()>;

    // here add routers ....
    fn router(&self, &mut SRouter) -> Result<()>;
    // fn router(&self, SRouter) -> Result<SRouter>;

}

pub trait SAppWrapper {
    fn before(&self, &mut Request) -> Result<()>;

    fn after(&self, &Request, &mut Response) -> Result<()>;

}

// later will add more fields
pub struct SApp<T: SModule + Send + 'static, W: SAppWrapper + Send + 'static> {
    pub address: String,
    pub port:    u32,
    // for app entry, global middeware
    pub wrapper: Option<W>,
    // for actually use to recognize
    pub routers: Router,
    // do simple static file service?
    pub static_service: bool,
    // marker for type T
    pub _marker: PhantomData<T>,
}

impl<T, W> SApp<T, W>
    where   T: SModule + Send + Sync + Reflect + Clone + 'static,
            W: SAppWrapper + Send + Sync + Reflect + Clone + 'static
    {
    pub fn new() -> SApp<T, W> {
        SApp {
            address: String::new(),
            port: 0,
            wrapper: None,
            routers: Router::new(),
            static_service: true,
            _marker: PhantomData
        }
    }

    pub fn run(self) {

        let listen_addr = self.address.clone() + ":" + &self.port.to_string();
        let arc_sapp = Arc::new(Box::new(self));

        let server = Server::http(&listen_addr.parse().unwrap()).unwrap();
        let _guard = server.handle(move |_| {
            RequestHandler::new(arc_sapp.clone())
        });
    }

    pub fn with_wrapper(&mut self, w: W) -> &mut Self {
        self.wrapper = Some(w);
        self
    }

    pub fn address(&mut self, address: &str) -> &mut Self {
        self.address = address.to_owned();
        self
    }

    pub fn port(&mut self, port: u32) -> &mut Self {
        self.port = port;
        self
    }

    pub fn static_service(&mut self, open: bool) -> &mut Self {
        self.static_service = open;
        self
    }

    // add methods of this smodule
    // prefix:  such as '/user'
    pub fn add_module(&mut self, sm: T) -> &mut Self {

        let mut router = SRouter::new();
        // get the sm router
        // pass self.router in
        sm.router(&mut router).unwrap();
        // combile this router to global big router
        // create a new closure, containing
        //      0. execute sapp.before();
        //      1. execute sm.before();
        //      2. execute a_router map pair value part function;
        //      3. execute sm.after();
        //      4. execute sapp.after();
        // fill the self.routers finally
        // assign this new closure to the routers router map pair  prefix + url part

        for (method, handler_vec) in router.into_router() {
            // add to wrapped router
            for &(glob, ref handler) in handler_vec.iter() {
                let method = method.clone();
                let glob = glob.clone();
                let handler = handler.clone();
                let sm = sm.clone();
                let wrapper = self.wrapper.clone().unwrap();
                self.routers.route(method, glob, Arc::new(Box::new(move |req: &mut Request| -> Result<Response> {
                    wrapper.before(req)?;
                    sm.before(req)?;
                    let mut response: Response = handler.handle(req)?;
                    sm.after(req, &mut response)?;
                    wrapper.after(req, &mut response)?;
                    Ok(response)
                })));
            }
        }

        // self.modules.push(sm);

        self
    }
}

fn simple_file_get(path: &str) -> Result<Vec<u8>> {
    let container = "static/".to_owned();
    match File::open(container + path) {
        Ok(ref mut file) => {
            let mut s: Vec<u8> = vec![];
            file.read_to_end(&mut s).unwrap_or(0);
            Ok(s)
        },
        Err(_) => Err(Error::FileNotExist)
    }
}

pub struct RequestHandler<
        T: SModule + Send + Sync + Reflect + Clone + 'static,
        W: SAppWrapper + Send + Sync + Reflect + Clone + 'static> {
    // router, keep the original handler function
    // pub router: SRouter,
    // wrapped router, keep the wrapped handler function
    // for actually use to recognize
    pub sapp: Arc<Box<SApp<T, W>>>,
    pub path: String,
    pub method: Method,
    pub version: HttpVersion,
    pub headers: Headers,
    pub buf: Vec<u8>,
    pub body: String,
    pub has_body: bool,
    // response deliver
    pub response: Result<Response>,
    pub static_file: Option<Vec<u8>>,
}

impl<T, W> RequestHandler<T, W>
where   T: SModule + Send + Sync + Reflect + Clone + 'static,
        W: SAppWrapper + Send + Sync + Reflect + Clone + 'static
{
    pub fn new(sapp: Arc<Box<SApp<T, W>>>) -> RequestHandler<T, W> {
        RequestHandler {
            sapp: sapp,
            path: String::new(),
            method: Default::default(),
            version: Default::default(),
            headers: Default::default(),
            buf: vec![0; 2048],
            body: String::new(),
            has_body: false,
            response: Err(Error::NotFound("/".to_owned())),
            static_file: None,
        }
    }

}

impl<T, W> HyperHandler<HttpStream> for RequestHandler<T, W>
where   T: SModule + Send + Sync + Reflect + Clone + 'static,
        W: SAppWrapper + Send + Sync + Reflect + Clone + 'static
 {
    fn on_request(&mut self, req: HyperRequest) -> Next {
        match *req.uri() {
            RequestUri::AbsolutePath(ref path) =>  {
                // if has_body
                if req.headers().get::<ContentLength>().is_some()
                    || req.headers().get::<ContentType>().is_some()
                 {
                    self.path = path.to_owned();
                    self.method = req.method().clone();
                    self.version = req.version().clone();
                    self.headers = req.headers().clone();
                    self.has_body = true;
                    Next::read_and_write()
                }
                else {
                    // if no body
                    let pathstr = &path[..];
                    let pathvec: Vec<&str> = pathstr.split('?').collect();
                    let path = pathvec[0].to_owned();
                    let mut query_string = None;

                    // if has query_string
                    if pathvec.len() > 1 {
                        query_string = Some(pathvec[1].to_owned());
                    }

                    // make swiftrs request from hyper request
                    let mut sreq = Request::new(
                        req.method().clone(),
                        req.version().clone(),
                        req.headers().clone(),
                        path.clone(),
                        query_string);

                    self.response = self.sapp.routers.handle_method(&mut sreq, &path).unwrap();

                    // match self.sapp.routers.handle_method(&mut sreq, &path).unwrap() {
                    //     Ok(response) => self.response = Some(response),
                    //     Err(e) => {
                    //         if e == Error::NotFoundError {
                    //             self.response = None
                    //         }
                    //     }
                    // }

                    Next::write()
                }

                // XXX: Need more work
                // self.response = self.routers.handle_method(&mut sreq, &path).unwrap().ok();

                // TODO: complete it later
                // .unwrap_or_else(||
                    // match req.method {
                    //     method::Options => Ok(self.handle_options(&path)),
                    //     // For HEAD, fall back to GET. Hyper ensures no response body is written.
                    //     method::Head => {
                    //         req.method = method::Get;
                    //         self.handle_method(req, &path).unwrap_or(
                    //             Err(IronError::new(NoRoute, status::NotFound))
                    //         )
                    //     }
                    //     _ => Err(IronError::new(NoRoute, status::NotFound))
                    // }
                // );
                // currently

                // if is_more {
                //     Next::read_and_write()
                // } else {
                //     Next::write()
                // }

                // Next::read_and_write()
                // Next::write()
            },
            _ => Next::write()
        }
    }
    fn on_request_readable(&mut self, transport: &mut Decoder<HttpStream>) -> Next {
        if self.has_body {
            match transport.read(&mut self.buf) {
                Ok(0) => {
                    debug!("Read 0, eof");

                    // TODO: need optimize
                    let pathstr = &self.path[..];
                    let pathvec: Vec<&str> = pathstr.split('?').collect();
                    let path = pathvec[0].to_owned();
                    let mut query_string = None;

                    // if has query_string
                    if pathvec.len() > 1 {
                        query_string = Some(pathvec[1].to_owned());
                    }
                    let mut sreq = Request::new(
                        self.method.clone(),
                        self.version.clone(),
                        self.headers.clone(),
                        path.clone(),
                        query_string);

                    // TODO: optimize this memory copy
                    sreq.set_raw_body(self.body.clone());

                    self.response = self.sapp.routers.handle_method(&mut sreq, &path).unwrap();

                    // match self.sapp.routers.handle_method(&mut sreq, &path).unwrap() {
                    //     Ok(response) => self.response = Some(response),
                    //     Err(e) => {
                    //         if e == Error::NotFoundError {
                    //             self.response = None
                    //         }
                    //     }
                    // }
                    //
                    return Next::write()
                },
                Ok(n) => {
                    self.body.push_str(str::from_utf8(&self.buf[0..n]).unwrap());
                    return Next::read_and_write()
                }
                Err(e) => match e.kind() {
                    io::ErrorKind::WouldBlock => return Next::read_and_write(),
                    _ => {
                        println!("read error {:?}", e);
                        return Next::end()
                    }
                }
            }
        }

        Next::write()
    }

    fn on_response(&mut self, res: &mut HyperResponse) -> Next {

        let mt = MimeTypes::new().unwrap();

        match self.response {
            Ok(ref response) => {
                if let &Some(ref body) = response.body() {
                    // default set content type as html
                    res.headers_mut().set(ContentType::html());

                    // update top level headers to low level headers
                    for header in response.headers().iter() {
                        res.headers_mut()
                            .set_raw(header.name().to_owned(),
                                vec![header.value_string().as_bytes().to_vec()]);
                    }

                    // here, set hyper response status code, and headers
                    res.headers_mut().set(ContentLength(body.len() as u64));
                }
                Next::write()
            },
            Err(ref e) => {
                // Inner Error
                // end
                match e {
                    &Error::NotFound(ref path) => {
                        if self.sapp.static_service {
                            match simple_file_get(path) {
                                Ok(avec) => {
                                    println!("serve file: {}", path);
                                    let body_len = avec.len() as u64;
                                    self.static_file = Some(avec);
                                    // TODO: need jude file mime type according to path
                                    // and set the header
                                    let mt_str = mt.mime_for_path(Path::new(path));
                                    res.headers_mut().set_raw("Content-Type", vec![mt_str.as_bytes().to_vec()]);
                                    res.headers_mut().set(ContentLength(body_len));
                                },
                                Err(_) => {
                                    println!("NotFound: {}", path);
                                    res.set_status(StatusCode::NotFound);
                                    res.headers_mut().set(ContentLength("404 Not Found".len() as u64));
                                }
                            }
                        }
                        else {
                            println!("NotFound: {}", path);
                            res.set_status(StatusCode::NotFound);
                            res.headers_mut().set(ContentLength("404 Not Found".len() as u64));
                        }
                    },
                    &Error::Fatal(ref astr) => {
                        println!("fatal error: {}", astr);
                        res.set_status(StatusCode::InternalServerError);
                        return Next::end();
                    },
                    _ => {

                    }

                }

                Next::write()
            }
        }

    }

    fn on_response_writable(&mut self, transport: &mut Encoder<HttpStream>) -> Next {
        match self.response {
            Ok(ref response) => {
                if let &Some(ref body) = response.body() {
                    // write response.body.unwrap() to transport
                    transport.write(body).unwrap();
                }
                Next::end()
            },
            Err(ref e) => {
                match e {
                    &Error::NotFound(ref path) => {
                        if self.sapp.static_service {
                            match self.static_file {
                                Some(ref avec) => {
                                    transport.write(avec).unwrap();
                                },
                                None => {
                                    transport.write("404 Not Found".as_bytes()).unwrap();
                                }
                            }
                        }
                        else {
                            transport.write("404 Not Found".as_bytes()).unwrap();
                        }

                    },
                    _ => {

                    }
                }

                // end
                Next::end()
            }
        }

    }
}
<|endoftext|>


<commit_before>use std::process::{Command, exit};
use std::iter;
use std::env;
use std::ffi::OsStr;

use clap;

use cargo_shim::{
    Profile,
    CargoResult,
    TargetKind
};

use build::{BuildArgs, Backend};
use error::Error;
use utils::{
    CommandExt,
    find_cmd
};
use test_chromium::test_in_chromium;

fn test_in_nodejs(
    backend: Backend,
    build: CargoResult,
    arg_passthrough: &Vec< &OsStr >,
    any_failure: &mut bool
) -> Result< (), Error > {

    let possible_commands =
        if cfg!( windows ) {
            &[ "node.exe" ][..]
        } else {
            &[ "nodejs", "node" ][..]
        };

    let nodejs_name = find_cmd( possible_commands ).ok_or_else( || {
        Error::EnvironmentError( "node.js not found; please install it!".into() )
    })?;

    let js_files: Vec< _ > =
        build.artifacts()
        .iter()
        .filter( |artifact| artifact.extension().map( |ext| ext == "js" ).unwrap_or( false ) )
        .collect();

    if js_files.is_empty() {
        panic!( "internal error: no .js file found" );
    }

    let artifact = if let Some( artifact ) = js_files.iter().find( |artifact| !artifact.iter().any( |chunk| chunk == "deps" ) ) {
        artifact
    } else {
        js_files[ 0 ]
    };

    let test_args = iter::once( artifact.as_os_str() )
        .chain( arg_passthrough.iter().cloned() );

    let previous_cwd = env::current_dir().unwrap();
    if backend.is_emscripten_wasm() {
        // On the Emscripten target the `.wasm` file is in a different directory.
        let wasm_artifact = build.artifacts().iter()
            .find( |artifact| artifact.extension().map( |ext| ext == "wasm" ).unwrap_or( false ) )
            .expect( "internal error: no .wasm file found" );

        env::set_current_dir( wasm_artifact.parent().unwrap() ).unwrap();
    } else {
        env::set_current_dir( artifact.parent().unwrap() ).unwrap();
    }

    let mut command = Command::new( nodejs_name );
    command.args( test_args );

    debug!( "Launching: {:?}", command );

    let status = command.run();
    *any_failure = *any_failure || !status.is_ok();
    debug!( "Status: {:?}", status );

    env::set_current_dir( previous_cwd ).unwrap();

    Ok(())
}

pub fn command_test< 'a >( matches: &clap::ArgMatches< 'a > ) -> Result< (), Error > {
    let build_args = BuildArgs::new( matches )?;
    let project = build_args.load_project()?;

    let use_nodejs = matches.is_present( "nodejs" );
    let no_run = matches.is_present( "no-run" );
    if project.backend().is_native_wasm() && !use_nodejs {
        return Err( Error::ConfigurationError( "running tests for the native wasm target is currently only supported with `--nodejs`".into() ) );
    }

    let arg_passthrough = matches.values_of_os( "passthrough" )
        .map_or( vec![], |args| args.collect() );

    let targets = project.target_or_select( |target| {
        target.kind == TargetKind::Lib ||
        target.kind == TargetKind::CDyLib ||
        target.kind == TargetKind::Bin ||
        target.kind == TargetKind::Test
    })?;
    let config = project.aggregate_configuration( Profile::Test )?;

    let mut builds = Vec::new();
    for target in targets {
        builds.push( project.build( &config, target )? );
    }

    if no_run {
        exit( 0 );
    }

    let mut any_failure = false;
    if use_nodejs {
        for build in builds {
            test_in_nodejs( project.backend(), build, &arg_passthrough, &mut any_failure )?;
        }
    } else {
        for build in builds {
            test_in_chromium( project.backend(), build, &arg_passthrough, &mut any_failure )?;
        }
    }

    if any_failure {
        exit( 101 );
    } else {
        if project.backend().is_native_wasm() {
            eprintln!( "All tests passed!" );
            // At least **I hope** that's the case; there are no prints
            // when running those tests, so who knows what happens. *shrug*
        }
    }

    Ok(())
}
<commit_msg>Do not require `--nodejs` on `wasm32-unknown-unknown` when given `--no-run`<commit_after>use std::process::{Command, exit};
use std::iter;
use std::env;
use std::ffi::OsStr;

use clap;

use cargo_shim::{
    Profile,
    CargoResult,
    TargetKind
};

use build::{BuildArgs, Backend};
use error::Error;
use utils::{
    CommandExt,
    find_cmd
};
use test_chromium::test_in_chromium;

fn test_in_nodejs(
    backend: Backend,
    build: CargoResult,
    arg_passthrough: &Vec< &OsStr >,
    any_failure: &mut bool
) -> Result< (), Error > {

    let possible_commands =
        if cfg!( windows ) {
            &[ "node.exe" ][..]
        } else {
            &[ "nodejs", "node" ][..]
        };

    let nodejs_name = find_cmd( possible_commands ).ok_or_else( || {
        Error::EnvironmentError( "node.js not found; please install it!".into() )
    })?;

    let js_files: Vec< _ > =
        build.artifacts()
        .iter()
        .filter( |artifact| artifact.extension().map( |ext| ext == "js" ).unwrap_or( false ) )
        .collect();

    if js_files.is_empty() {
        panic!( "internal error: no .js file found" );
    }

    let artifact = if let Some( artifact ) = js_files.iter().find( |artifact| !artifact.iter().any( |chunk| chunk == "deps" ) ) {
        artifact
    } else {
        js_files[ 0 ]
    };

    let test_args = iter::once( artifact.as_os_str() )
        .chain( arg_passthrough.iter().cloned() );

    let previous_cwd = env::current_dir().unwrap();
    if backend.is_emscripten_wasm() {
        // On the Emscripten target the `.wasm` file is in a different directory.
        let wasm_artifact = build.artifacts().iter()
            .find( |artifact| artifact.extension().map( |ext| ext == "wasm" ).unwrap_or( false ) )
            .expect( "internal error: no .wasm file found" );

        env::set_current_dir( wasm_artifact.parent().unwrap() ).unwrap();
    } else {
        env::set_current_dir( artifact.parent().unwrap() ).unwrap();
    }

    let mut command = Command::new( nodejs_name );
    command.args( test_args );

    debug!( "Launching: {:?}", command );

    let status = command.run();
    *any_failure = *any_failure || !status.is_ok();
    debug!( "Status: {:?}", status );

    env::set_current_dir( previous_cwd ).unwrap();

    Ok(())
}

pub fn command_test< 'a >( matches: &clap::ArgMatches< 'a > ) -> Result< (), Error > {
    let build_args = BuildArgs::new( matches )?;
    let project = build_args.load_project()?;

    let use_nodejs = matches.is_present( "nodejs" );
    let no_run = matches.is_present( "no-run" );
    if project.backend().is_native_wasm() && !use_nodejs && !no_run {
        return Err( Error::ConfigurationError( "running tests for the native wasm target is currently only supported with `--nodejs`".into() ) );
    }

    let arg_passthrough = matches.values_of_os( "passthrough" )
        .map_or( vec![], |args| args.collect() );

    let targets = project.target_or_select( |target| {
        target.kind == TargetKind::Lib ||
        target.kind == TargetKind::CDyLib ||
        target.kind == TargetKind::Bin ||
        target.kind == TargetKind::Test
    })?;
    let config = project.aggregate_configuration( Profile::Test )?;

    let mut builds = Vec::new();
    for target in targets {
        builds.push( project.build( &config, target )? );
    }

    if no_run {
        exit( 0 );
    }

    let mut any_failure = false;
    if use_nodejs {
        for build in builds {
            test_in_nodejs( project.backend(), build, &arg_passthrough, &mut any_failure )?;
        }
    } else {
        for build in builds {
            test_in_chromium( project.backend(), build, &arg_passthrough, &mut any_failure )?;
        }
    }

    if any_failure {
        exit( 101 );
    } else {
        if project.backend().is_native_wasm() {
            eprintln!( "All tests passed!" );
            // At least **I hope** that's the case; there are no prints
            // when running those tests, so who knows what happens. *shrug*
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before>use distribution::Distribution;
use generator::Generator;

/// An exponential distribution.
#[derive(Clone, Copy)]
pub struct Exponential {
    lambda: f64,
}

impl Exponential {
    /// Create an exponential distribution with rate `lambda`.
    ///
    /// It should hold that `lambda > 0`.
    #[inline]
    pub fn new(lambda: f64) -> Exponential {
        should!(lambda > 0.0);
        Exponential { lambda: lambda }
    }

    /// Return the rate parameter.
    #[inline(always)] pub fn lambda(&self) -> f64 { self.lambda }
}

impl Distribution for Exponential {
    type Value = f64;

    #[inline]
    fn mean(&self) -> f64 {
        self.lambda.recip()
    }

    #[inline]
    fn var(&self) -> f64 {
        self.lambda.powi(-2)
    }

    #[inline] fn sd(&self) -> f64 {
        self.lambda.recip()
    }

    #[inline] fn skewness(&self) -> f64 { 2.0 }
    #[inline] fn kurtosis(&self) -> f64 { 6.0 }

    #[inline]
    fn median(&self) -> f64 {
        use std::f64::consts::LN_2;
        self.lambda.recip() * LN_2
    }

    #[inline]
    fn modes(&self) -> Vec<f64> {
        vec![0.0]
    }

    #[inline]
    fn entropy(&self) -> f64 {
        1.0 - self.lambda.ln()
    }

    #[inline]
    fn pdf(&self, x: f64) -> f64 {
        if x < 0.0 { 0.0 } else { self.lambda * (-self.lambda * x).exp() }
    }

    #[inline]
    fn cdf(&self, x: f64) -> f64 {
        if x <= 0.0 { 0.0 } else { -(-self.lambda * x).exp_m1() }
    }

    #[inline]
    fn inv_cdf(&self, p: f64) -> f64 {
        should!(0.0 <= p && p <= 1.0);
        -(-p).ln_1p() / self.lambda
    }

    #[inline]
    fn sample<G>(&self, generator: &mut G) -> f64 where G: Generator {
        -generator.next::<f64>().ln() / self.lambda
    }
}

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

    macro_rules! new(
        ($lambda:expr) => (Exponential::new($lambda));
    );

    #[test]
    fn mean() {
        assert_eq!(new!(2.0).mean(), 0.5);
    }

    #[test]
    fn var() {
        assert_eq!(new!(2.0).var(), 0.25);
    }

    #[test]
    fn sd() {
        assert_eq!(new!(2.0).sd(), 0.5);
    }

    #[test]
    fn skewness() {
        assert_eq!(new!(2.0).skewness(), 2.0);
    }

    #[test]
    fn kurtosis() {
        assert_eq!(new!(2.0).kurtosis(), 6.0);
    }

    #[test]
    fn median() {
        use std::f64::consts::LN_2;
        assert_eq!(new!(LN_2).median(), 1.0);
    }

    #[test]
    fn modes() {
        assert_eq!(new!(2.0).modes(), vec![0.0]);
    }

    #[test]
    fn entropy() {
        use std::f64::consts::E;
        assert_eq!(new!(E).entropy(), 0.0);
    }

    #[test]
    fn pdf() {
        let exponential = new!(2.0);
        let x = vec![-1.0, 0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 6.0, 12.0];
        let p = vec![
            0.000000000000000e+00, 2.000000000000000e+00, 7.357588823428847e-01,
            2.706705664732254e-01, 9.957413673572789e-02, 3.663127777746836e-02,
            1.347589399817093e-02, 4.957504353332717e-03, 6.709252558050237e-04,
            1.228842470665642e-05, 7.550269088558195e-11,
        ];

        assert::close(&x.iter().map(|&x| exponential.pdf(x)).collect::<Vec<_>>(), &p, 1e-15);
    }

    #[test]
    fn cdf() {
        let exponential = new!(2.0);
        let x = vec![-1.0, 0.0, 0.01, 0.05, 0.1, 0.15, 0.25, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0];
        let p = vec![
            0.000000000000000e+00, 0.000000000000000e+00, 1.980132669324470e-02,
            9.516258196404043e-02, 1.812692469220182e-01, 2.591817793182821e-01,
            3.934693402873666e-01, 6.321205588285577e-01, 8.646647167633873e-01,
            9.502129316321360e-01, 9.816843611112658e-01, 9.975212478233336e-01,
            9.996645373720975e-01
        ];

        assert::close(&x.iter().map(|&x| exponential.cdf(x)).collect::<Vec<_>>(), &p, 1e-15);
    }

    #[test]
    fn inv_cdf() {
        use std::f64::INFINITY;

        let exponential = new!(2.0);
        let x = vec![
            0.0, 0.01, 0.05, 0.1, 0.15, 0.25, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, INFINITY,
        ];
        let p = vec![
            0.000000000000000e+00, 1.980132669324470e-02, 9.516258196404043e-02,
            1.812692469220182e-01, 2.591817793182821e-01, 3.934693402873666e-01,
            6.321205588285577e-01, 8.646647167633873e-01, 9.502129316321360e-01,
            9.816843611112658e-01, 9.975212478233336e-01, 9.996645373720975e-01,
            1.000000000000000e-00,
        ];

        assert::close(&p.iter().map(|&p| exponential.inv_cdf(p)).collect::<Vec<_>>(), &x, 1e-14);
    }
}
<commit_msg>exponential: fix styles<commit_after>use distribution::Distribution;
use generator::Generator;

/// An exponential distribution.
#[derive(Clone, Copy)]
pub struct Exponential {
    lambda: f64,
}

impl Exponential {
    /// Create an exponential distribution with rate `lambda`.
    ///
    /// It should hold that `lambda > 0`.
    #[inline]
    pub fn new(lambda: f64) -> Exponential {
        should!(lambda > 0.0);
        Exponential { lambda: lambda }
    }

    /// Return the rate parameter.
    #[inline(always)] pub fn lambda(&self) -> f64 { self.lambda }
}

impl Distribution for Exponential {
    type Value = f64;

    #[inline]
    fn mean(&self) -> f64 {
        self.lambda.recip()
    }

    #[inline]
    fn var(&self) -> f64 {
        self.lambda.powi(-2)
    }

    #[inline]
    fn sd(&self) -> f64 {
        self.lambda.recip()
    }

    #[inline] fn skewness(&self) -> f64 { 2.0 }
    #[inline] fn kurtosis(&self) -> f64 { 6.0 }

    #[inline]
    fn median(&self) -> f64 {
        use std::f64::consts::LN_2;
        self.lambda.recip() * LN_2
    }

    #[inline]
    fn modes(&self) -> Vec<f64> {
        vec![0.0]
    }

    #[inline]
    fn entropy(&self) -> f64 {
        1.0 - self.lambda.ln()
    }

    #[inline]
    fn pdf(&self, x: f64) -> f64 {
        if x < 0.0 { 0.0 } else { self.lambda * (-self.lambda * x).exp() }
    }

    #[inline]
    fn cdf(&self, x: f64) -> f64 {
        if x <= 0.0 { 0.0 } else { -(-self.lambda * x).exp_m1() }
    }

    #[inline]
    fn inv_cdf(&self, p: f64) -> f64 {
        should!(0.0 <= p && p <= 1.0);
        -(-p).ln_1p() / self.lambda
    }

    #[inline]
    fn sample<G>(&self, generator: &mut G) -> f64 where G: Generator {
        -generator.next::<f64>().ln() / self.lambda
    }
}

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

    macro_rules! new(
        ($lambda:expr) => (Exponential::new($lambda));
    );

    #[test]
    fn mean() {
        assert_eq!(new!(2.0).mean(), 0.5);
    }

    #[test]
    fn var() {
        assert_eq!(new!(2.0).var(), 0.25);
    }

    #[test]
    fn sd() {
        assert_eq!(new!(2.0).sd(), 0.5);
    }

    #[test]
    fn skewness() {
        assert_eq!(new!(2.0).skewness(), 2.0);
    }

    #[test]
    fn kurtosis() {
        assert_eq!(new!(2.0).kurtosis(), 6.0);
    }

    #[test]
    fn median() {
        use std::f64::consts::LN_2;
        assert_eq!(new!(LN_2).median(), 1.0);
    }

    #[test]
    fn modes() {
        assert_eq!(new!(2.0).modes(), vec![0.0]);
    }

    #[test]
    fn entropy() {
        use std::f64::consts::E;
        assert_eq!(new!(E).entropy(), 0.0);
    }

    #[test]
    fn pdf() {
        let exponential = new!(2.0);
        let x = vec![-1.0, 0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 6.0, 12.0];
        let p = vec![
            0.000000000000000e+00, 2.000000000000000e+00, 7.357588823428847e-01,
            2.706705664732254e-01, 9.957413673572789e-02, 3.663127777746836e-02,
            1.347589399817093e-02, 4.957504353332717e-03, 6.709252558050237e-04,
            1.228842470665642e-05, 7.550269088558195e-11,
        ];

        assert::close(&x.iter().map(|&x| exponential.pdf(x)).collect::<Vec<_>>(), &p, 1e-15);
    }

    #[test]
    fn cdf() {
        let exponential = new!(2.0);
        let x = vec![-1.0, 0.0, 0.01, 0.05, 0.1, 0.15, 0.25, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0];
        let p = vec![
            0.000000000000000e+00, 0.000000000000000e+00, 1.980132669324470e-02,
            9.516258196404043e-02, 1.812692469220182e-01, 2.591817793182821e-01,
            3.934693402873666e-01, 6.321205588285577e-01, 8.646647167633873e-01,
            9.502129316321360e-01, 9.816843611112658e-01, 9.975212478233336e-01,
            9.996645373720975e-01
        ];

        assert::close(&x.iter().map(|&x| exponential.cdf(x)).collect::<Vec<_>>(), &p, 1e-15);
    }

    #[test]
    fn inv_cdf() {
        use std::f64::INFINITY;

        let exponential = new!(2.0);
        let x = vec![
            0.0, 0.01, 0.05, 0.1, 0.15, 0.25, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, INFINITY,
        ];
        let p = vec![
            0.000000000000000e+00, 1.980132669324470e-02, 9.516258196404043e-02,
            1.812692469220182e-01, 2.591817793182821e-01, 3.934693402873666e-01,
            6.321205588285577e-01, 8.646647167633873e-01, 9.502129316321360e-01,
            9.816843611112658e-01, 9.975212478233336e-01, 9.996645373720975e-01,
            1.000000000000000e-00,
        ];

        assert::close(&p.iter().map(|&p| exponential.inv_cdf(p)).collect::<Vec<_>>(), &x, 1e-14);
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate conrod;
use conrod::{widget, Borderable, Colorable, Positionable, Sizeable, Widget};
use conrod::backend::glium::glium;
use conrod::backend::glium::glium::{DisplayBuild, Surface};

struct AppState<'a> {
	board_data: Vec<bool>,
	board_rows: Vec<&'a mut [bool]>, // mutable slice for each row based on board_data.
	// mutable slice of mutable slice of bool, based on board_data. Emulate a 2D array.
	board: &'a mut [&'a mut [bool]],
	board_size: (usize, usize),
}

impl<'a> AppState<'a> {
	fn new() -> AppState<'a> {
		const BOARD_WIDTH: usize = 8;
		const BOARD_HEIGHT: usize = 8;
		let mut raw_board_data = vec![true; BOARD_WIDTH * BOARD_HEIGHT];
		// Notes an intermediate variable is required to force conversion from FromIterator<&mut [bool]> to Vec<&mut [bool]>.
		// This allows conversion to a slice of slice, emulating a 2D array.
		let mut grid_board_of_vec: Vec<&'a mut [bool]> = raw_board_data.as_mut_slice().chunks_mut(BOARD_WIDTH).collect();
		let mut grid_board: &mut [&mut [bool]] = grid_board_of_vec.as_mut_slice();

		AppState {
			board_data: raw_board_data,
			board_rows: grid_board_of_vec,
			board: grid_board,
			board_size: (BOARD_WIDTH, BOARD_HEIGHT)
		}
	}
}

fn main() {
	const WIDTH: u32 = 400;
	const HEIGHT: u32 = 400;

	let mut app_state = AppState::new();

	// Build the window.
	let display = glium::glutin::WindowBuilder::new()
		.with_vsync()
		.with_dimensions(WIDTH, HEIGHT)
		.with_title("Game of Life")
		.with_multisampling(4)
		.build_glium()
		.unwrap();

	// construct our `Ui`.
	let mut ui = conrod::UiBuilder::new([WIDTH as f64, HEIGHT as f64]).build();

	// Generate the widget identifiers.
	widget_ids!(struct Ids {
		title,
		info,
		board
	});
	let ids = Ids::new(ui.widget_id_generator());

	// Add a `Font` to the `Ui`'s `font::Map` from file.
	const FONT_PATH: &'static str =
		concat!(env!("CARGO_MANIFEST_DIR"), "/assets/fonts/NotoSans/NotoSans-Regular.ttf");
	ui.fonts.insert_from_file(FONT_PATH).unwrap();

	// A type used for converting `conrod::render::Primitives` into `Command`s that can be used
	// for drawing to the glium `Surface`.
	let mut renderer = conrod::backend::glium::Renderer::new(&display).unwrap();

	// The image map describing each of our widget->image mappings (in our case, none).
	let image_map = conrod::image::Map::<glium::texture::Texture2d>::new();

	// Poll events from the window.
	let mut last_update = std::time::Instant::now();
	let mut ui_needs_update = true;
	'main: loop {

		// We don't want to loop any faster than 60 FPS, so wait until it has been at least
		// 16ms since the last yield.
		let sixteen_ms = std::time::Duration::from_millis(16);
		let duration_since_last_update = std::time::Instant::now().duration_since(last_update);
		if duration_since_last_update < sixteen_ms {
			std::thread::sleep(sixteen_ms - duration_since_last_update);
		}

		// Collect all pending events.
		let mut events: Vec<_> = display.poll_events().collect();

		// If there are no events and the `Ui` does not need updating, wait for the next event.
		if events.is_empty() && !ui_needs_update {
			events.extend(display.wait_events().next());
		}

		// Reset the needs_update flag and time this update.
		ui_needs_update = false;
		last_update = std::time::Instant::now();

		// Handle all events.
		for event in events {

			// Use the `winit` backend feature to convert the winit event to a conrod one.
			if let Some(event) = conrod::backend::winit::convert(event.clone(), &display) {
				ui.handle_event(event);
				ui_needs_update = true;
			}

			match event {
				// Break from the loop upon `Escape`.
				glium::glutin::Event::KeyboardInput(_, _, Some(glium::glutin::VirtualKeyCode::Escape)) |
				glium::glutin::Event::Closed =>
					break 'main,
				_ => {},
			}
		}

		// Instantiate all widgets in the GUI.
		{
			let ui = &mut ui.set_widgets();

			// "Hello World!" in the middle of the screen.
			widget::Text::new("Game of Life")
				.mid_top_of(ui.window)
				.color(conrod::color::WHITE)
				.font_size(32)
				.set(ids.title, ui);
			widget::Text::new("Start")
				.down(5.0)
				.color(conrod::color::WHITE)
				.font_size(8)
				.set(ids.info, ui);

			// A demonstration using widget_matrix to easily draw a matrix of any kind of widget.
			let (cols, rows) = (8, 8);
			let mut elements = widget::Matrix::new(cols, rows)
				.down(20.0)
				.w_h(260.0, 260.0)
				.set(ids.board, ui);

			// The `Matrix` widget returns an `Elements`, which can be used similar to an `Iterator`.
			while let Some(elem) = elements.next(ui) {
				let (col, row) = (elem.col, elem.row);

				// Color effect for fun.
				let (r, g, b, a) = (
					0.5 + (elem.col as f32 / cols as f32) / 2.0,
					0.75,
					1.0 - (elem.row as f32 / rows as f32) / 2.0,
					1.0
				);

				// We can use `Element`s to instantiate any kind of widget we like.
				// The `Element` does all of the positioning and sizing work for us.
				// Here, we use the `Element` to `set` a `Toggle` widget for us.
				let toggle = widget::Toggle::new(app_state.board[col][row])
					.rgba(r, g, b, a)
					.border(1.0);
				if let Some(new_value) = elem.set(toggle, ui).last() {
					app_state.board[col][row] = new_value;
				}
			}

		}

		// Render the `Ui` and then display it on the screen.
		if let Some(primitives) = ui.draw_if_changed() {
			renderer.fill(&display, primitives, &image_map);
			let mut target = display.draw();
			target.clear_color(0.0, 0.0, 0.0, 1.0);
			renderer.draw(&display, &mut target, &image_map).unwrap();
			target.finish().unwrap();
		}
	}
}
<commit_msg>Added struct to represent the 2D board.<commit_after>#[macro_use]
extern crate conrod;
use conrod::{widget, Borderable, Colorable, Positionable, Sizeable, Widget};
use conrod::backend::glium::glium;
use conrod::backend::glium::glium::{DisplayBuild, Surface};

struct Board {
	width: usize,
	height: usize,
	data: Vec<bool>,
}

impl Board {
	fn new( width: usize, height: usize) -> Board {
		Board {
			width: width,
			height: height,
			data: vec![true; width* height],
		}
	}

	fn get(&self, x: usize, y: usize) -> bool {
		assert!( x <= self.width  &&  y <= self.height );
		self.data[ y * self.width + x ]
	}

	fn set(&mut self, x: usize, y: usize, new_value: bool) {
		assert!( x <= self.width  &&  y <= self.height );
		self.data[ y * self.width + x ] = new_value;
	}

}

struct AppState {
	board: Board,
}

impl AppState {
	fn new() -> AppState {
		const BOARD_WIDTH: usize = 8;
		const BOARD_HEIGHT: usize = 8;

		AppState {
			board: Board::new(BOARD_WIDTH, BOARD_HEIGHT),
		}
	}
}

fn main() {
	const WIDTH: u32 = 400;
	const HEIGHT: u32 = 400;

	let mut app_state = AppState::new();

	// Build the window.
	let display = glium::glutin::WindowBuilder::new()
		.with_vsync()
		.with_dimensions(WIDTH, HEIGHT)
		.with_title("Game of Life")
		.with_multisampling(4)
		.build_glium()
		.unwrap();

	// construct our `Ui`.
	let mut ui = conrod::UiBuilder::new([WIDTH as f64, HEIGHT as f64]).build();

	// Generate the widget identifiers.
	widget_ids!(struct Ids {
		title,
		info,
		board
	});
	let ids = Ids::new(ui.widget_id_generator());

	// Add a `Font` to the `Ui`'s `font::Map` from file.
	const FONT_PATH: &'static str =
		concat!(env!("CARGO_MANIFEST_DIR"), "/assets/fonts/NotoSans/NotoSans-Regular.ttf");
	ui.fonts.insert_from_file(FONT_PATH).unwrap();

	// A type used for converting `conrod::render::Primitives` into `Command`s that can be used
	// for drawing to the glium `Surface`.
	let mut renderer = conrod::backend::glium::Renderer::new(&display).unwrap();

	// The image map describing each of our widget->image mappings (in our case, none).
	let image_map = conrod::image::Map::<glium::texture::Texture2d>::new();

	// Poll events from the window.
	let mut last_update = std::time::Instant::now();
	let mut ui_needs_update = true;
	'main: loop {

		// We don't want to loop any faster than 60 FPS, so wait until it has been at least
		// 16ms since the last yield.
		let sixteen_ms = std::time::Duration::from_millis(16);
		let duration_since_last_update = std::time::Instant::now().duration_since(last_update);
		if duration_since_last_update < sixteen_ms {
			std::thread::sleep(sixteen_ms - duration_since_last_update);
		}

		// Collect all pending events.
		let mut events: Vec<_> = display.poll_events().collect();

		// If there are no events and the `Ui` does not need updating, wait for the next event.
		if events.is_empty() && !ui_needs_update {
			events.extend(display.wait_events().next());
		}

		// Reset the needs_update flag and time this update.
		ui_needs_update = false;
		last_update = std::time::Instant::now();

		// Handle all events.
		for event in events {

			// Use the `winit` backend feature to convert the winit event to a conrod one.
			if let Some(event) = conrod::backend::winit::convert(event.clone(), &display) {
				ui.handle_event(event);
				ui_needs_update = true;
			}

			match event {
				// Break from the loop upon `Escape`.
				glium::glutin::Event::KeyboardInput(_, _, Some(glium::glutin::VirtualKeyCode::Escape)) |
				glium::glutin::Event::Closed =>
					break 'main,
				_ => {},
			}
		}

		// Instantiate all widgets in the GUI.
		{
			let ui = &mut ui.set_widgets();

			// "Hello World!" in the middle of the screen.
			widget::Text::new("Game of Life")
				.mid_top_of(ui.window)
				.color(conrod::color::WHITE)
				.font_size(32)
				.set(ids.title, ui);
			widget::Text::new("Start")
				.down(5.0)
				.color(conrod::color::WHITE)
				.font_size(8)
				.set(ids.info, ui);

			// A demonstration using widget_matrix to easily draw a matrix of any kind of widget.
			let (cols, rows) = (8, 8);
			let mut elements = widget::Matrix::new(cols, rows)
				.down(20.0)
				.w_h(260.0, 260.0)
				.set(ids.board, ui);

			// The `Matrix` widget returns an `Elements`, which can be used similar to an `Iterator`.
			while let Some(elem) = elements.next(ui) {
				let (col, row) = (elem.col, elem.row);

				// Color effect for fun.
				let (r, g, b, a) = (
					0.5 + (elem.col as f32 / cols as f32) / 2.0,
					0.75,
					1.0 - (elem.row as f32 / rows as f32) / 2.0,
					1.0
				);

				// We can use `Element`s to instantiate any kind of widget we like.
				// The `Element` does all of the positioning and sizing work for us.
				// Here, we use the `Element` to `set` a `Toggle` widget for us.
				let toggle = widget::Toggle::new(app_state.board.get(col, row))
					.rgba(r, g, b, a)
					.border(1.0);
				if let Some(new_value) = elem.set(toggle, ui).last() {
					app_state.board.set(col, row, new_value);
				}
			}

		}

		// Render the `Ui` and then display it on the screen.
		if let Some(primitives) = ui.draw_if_changed() {
			renderer.fill(&display, primitives, &image_map);
			let mut target = display.draw();
			target.clear_color(0.0, 0.0, 0.0, 1.0);
			renderer.draw(&display, &mut target, &image_map).unwrap();
			target.finish().unwrap();
		}
	}
}
<|endoftext|>


<commit_before>//! Interfaces (traits) for graph implementations.

use std;
use std::fmt::Debug;
use std::iter::{Chain,Iterator,IntoIterator};

use super::visit::{self,Visit};
use super::iter::Successors;

/// Interface provided by node and edge identifiers.
pub trait Id: Copy + Debug {
    /// Create a new Id object with the given value.
    fn new(v: usize) -> Self;

    /// Retrieve the underlying integer value of the identifier.
    fn index(&self) -> usize;
}

/// Any directed edge type used by a graph.
pub trait Edge: Debug {
    /// Type used to identify source and destination nodes.
    type NodeId: Id;

    /// Get index of the edge's source node.
    fn source(&self) -> Self::NodeId;

    /// Get index of the edge's target node.
    fn target(&self) -> Self::NodeId;
}

/// Any node type used by a graph.
pub trait Node: Debug {
    /// Type used to identify incoming and outgoing edges.
    type EdgeId: Id;

    /// Get an iterator over all (incoming + outgoing) edges connected to
    /// the node.
    fn edges(&self) -> Chain<std::slice::Iter<Self::EdgeId>, std::slice::Iter<Self::EdgeId>> {
        self.incoming_edges().into_iter().chain(self.outgoing_edges().into_iter())
    }

    /// Get an iterator over incoming edges connected to the node.
    ///
    /// Note that if an edge has the node's index as both its source _and_ its
    /// target, it should appear in the set of values returned by this iterator
    /// **and** that returned by the iterator obtained from `outgoing_edges`.
    fn incoming_edges(&self) -> std::slice::Iter<Self::EdgeId>;

    /// Get the number of incoming edges.
    fn incoming_edge_count(&self) -> usize;

    /// Get an iterator over outgoing edges connected to the node.
    ///
    /// Note that if an edge has the node's index as both its source _and_ its
    /// target, it should appear in the set of values returned by this iterator
    /// **and** that returned by the iterator obtained from `incoming_edges`.
    fn outgoing_edges(&self) -> std::slice::Iter<Self::EdgeId>;

    /// Get the number of outgoing edges.
    fn outgoing_edge_count(&self) -> usize;

    /// Record the existence of an edge that terminates at this node.
    fn add_incoming_edge(&mut self, e: Self::EdgeId);

    /// Record the existence of an edge that originates from this node.
    fn add_outgoing_edge(&mut self, e: Self::EdgeId);
}

/// Common interface for all graph types.
pub trait Graph {
    /// Type used to identify nodes for lookup.
    type NodeId: Id;

    /// Type used to identify edges for lookup.
    type EdgeId: Id;

    /// Concrete node type used by a graph.
    type Node: Node<EdgeId=Self::EdgeId>;

    /// Concrete edge type used by a graph.
    type Edge: Edge<NodeId=Self::NodeId>;

    /// Iterator returned from `node_ids`.
    type NodeIdIterator: Iterator<Item=Self::NodeId>;

    /// Iterator returned from `edge_ids`.
    type EdgeIdIterator: Iterator<Item=Self::EdgeId>;

    // --------------------------------

    /// Create a new, empty instance of this graph type.
    fn new() -> Self
        where Self: Sized + Default {
        Default::default()
    }

    // --------------------------------

    /// Add an explicitly-specified node to the graph, returning its unique
    /// identifier.
    fn add_node<T: Into<Self::Node>>(&mut self, n: T) -> Self::NodeId;

    /// Fetch a reference to a node.
    ///
    /// If the given node ID is invalid, i.e. `self.contains_node(n)` is false,
    /// this call should **panic**.
    fn node(&self, n: Self::NodeId) -> &Self::Node;

    /// Fetch a mutable reference to a node.
    ///
    /// If the given node ID is invalid, i.e. `self.contains_node(n)` is false,
    /// this call should **panic**.
    fn node_mut(&mut self, n: Self::NodeId) -> &mut Self::Node;

    /// Check if a node ID is valid for this graph.
    fn contains_node(&self, n: Self::NodeId) -> bool;

    /// Fetch an iterator over the IDs of all nodes in the graph.
    fn node_ids(&self) -> Self::NodeIdIterator;

    /// Count the number of nodes in the graph.
    fn node_count(&self) -> usize;

    // --------------------------------

    /// Add an explicitly-specified edge to the graph, returning its
    /// unique identifier.
    fn add_edge<T: Into<Self::Edge>>(&mut self, e: T) -> Self::EdgeId;

    /// Fetch a reference to an edge.
    ///
    /// If the given node ID is invalid, i.e. `self.contains_node(n)` is false,
    /// this call should **panic**.
    fn edge(&self, e: Self::EdgeId) -> &Self::Edge;

    /// Check if an edge ID is valid for this graph.
    fn contains_edge(&self, e: Self::EdgeId) -> bool;

    /// Fetch an iterator over the IDs of all edges in the graph.
    fn edge_ids(&self) -> Self::EdgeIdIterator;

    /// Count the number of edges in the graph.
    fn edge_count(&self) -> usize;

    // --------------------------------

    /// Fetch an iterator over the direct successors of a node.
    ///
    /// If the given node ID is invalid, i.e. `self.contains_node(n)` is false,
    /// this call should **panic**.
    fn direct_successors(&self, n: Self::NodeId) -> Successors<Self>
        where Self: Sized {
        Successors::new(self, self.node(n).outgoing_edges())
    }

    /// Get an iterator over incoming edges connected to a node.
    ///
    /// Note that if an edge has a node's index as both its source _and_ its
    /// target, it should appear in the set of values returned by this iterator
    /// _and_ that returned by the iterator obtained from `outgoing_edges` for
    /// the same node.
    ///
    /// If the given node ID is invalid, i.e. `self.contains_node(n)` is false,
    /// this call should **panic**.
    fn incoming_edges(&self, n: Self::NodeId) -> std::slice::Iter<Self::EdgeId> {
        self.node(n).incoming_edges()
    }

    /// Get an iterator over outgoing edges connected to a node.
    ///
    /// Note that if an edge has a node's index as both its source _and_ its
    /// target, it should appear in the set of values returned by this iterator
    /// _and_ that returned by the iterator obtained from `incoming_edges` for
    /// the same node.
    ///
    /// If the given node ID is invalid, i.e. `self.contains_node(n)` is false,
    /// this call should **panic**.
    fn outgoing_edges(&self, n: Self::NodeId) -> std::slice::Iter<Self::EdgeId> {
        self.node(n).outgoing_edges()
    }

    /// Get an iterator over all edges connected to a node.
    ///
    /// Note that if a node is both the source source _and_ the target for an
    /// edge, that edge's index will be returned twice by the iterator.
    ///
    /// If the given node ID is invalid, i.e. `self.contains_node(n)` is false,
    /// this call will **panic**.
    fn edges(&self, n: Self::NodeId) -> Chain<std::slice::Iter<Self::EdgeId>,
                                              std::slice::Iter<Self::EdgeId>> {
        if self.contains_node(n) {
            self.node(n).edges()
        } else {
            panic!("Invalid node ID supplied to Graph::edges()");
        }
    }

    /// Convert all elements in a slice to edges, and add them to the graph.
    ///
    /// Each element of the slice can be any type convertible to an edge using
    /// `std::convert::From`; at the time of writing this means one of two
    /// tuple forms:
    ///
    ///   * `(source_node_index, target_node_index, payload)`, where the edge
    ///     is fully specified as arguments to `add_edge`, or
    ///   * `(source_node_index, target_node_index)`, where the edge's payload
    ///     is created using the `Default` trait.
    ///
    /// ```rust
    /// use cripes::util::graph::*;
    ///
    /// # fn main() {
    /// let mut g = WeightedGraph::<(),(),u8>::new();
    /// let n0 = g.add_node(());
    /// let n1 = g.add_node(());
    /// let n2 = g.add_node(());
    /// let n3 = g.add_node(());
    ///
    /// g.add_edges(&[(n0, n1), (n1, n2), (n1, n3), (n2, n3), (n3, n2)]);
    ///
    /// # }
    /// ```
    ///
    /// If any endpoint refers to a node that does not exist, this call will
    /// **panic**.
    fn add_edges<'a, D>(&mut self, edges: &'a [D]) where D: 'a, Self::Edge: From<&'a D> {
        for e in edges.iter() {
            let edge = Self::Edge::from(e);
            if ! self.contains_node(edge.source()) {
                panic!("Invalid source node ({:?}) specified for edge in argument to Graph::add_edges",
                       edge.source());
            } else if ! self.contains_node(edge.target()) {
                panic!("Invalid target node ({:?}) specified for edge in argument to Graph::add_edges",
                       edge.target());
            } else {
                self.add_edge(edge);
            }
        }
    }

    /// Fetch the IDs of an edge's source and target nodes.
    ///
    /// If the given edge ID is invalid, i.e. `self.contains_edge(e)` is false,
    /// this call should **panic**.
    fn edge_endpoints(&self, e: Self::EdgeId) -> (Self::NodeId, Self::NodeId) {
        let edge = self.edge(e);
        (edge.source(), edge.target())
    }

    /// Fetch the index of the node from which a given edge originates.
    ///
    /// If the given edge ID is invalid, i.e. `self.contains_edge(e)` is false,
    /// this call should **panic**.
    fn edge_source(&self, e: Self::EdgeId) -> Self::NodeId {
        self.edge(e).source()
    }

    /// Fetch the index of the node at which a given edge terminates.
    ///
    /// If the given edge ID is invalid, i.e. `self.contains_edge(e)` is false,
    /// this call should **panic**.
    fn edge_target(&self, e: Self::EdgeId) -> Self::NodeId {
        self.edge(e).target()
    }

    /*/// Iterate over the graph using a self-starting algorithm.
    ///
    /// Self-starting algorithms are those that select initial node(s) on
    /// their own.
    fn iter<A: visit::SelfStartingAlgorithm<Self>>(&self) -> visit::VisitorIter<Self, A>
        where Self: Sized {
        visit::Visitor::new::<Self, A>(self).into_iter(self)
    }*/

    /// Iterate over the graph using a rooted algorithm.
    ///
    /// Rooted algorithms are those that operate using a pre-defined root node
    /// or nodes.
    fn iter<A: visit::RootedAlgorithm<Self>>(&self, entry: Self::NodeId) -> visit::VisitorIter<Self, visit::Visitor<Self, A>>
        where Self: Sized {
        visit::Visitor::new(self, entry.into()).into_iter(self)
    }
}
<commit_msg>util/graph/interface: add PartialEq + PartialOrd bounds to `Id`<commit_after>//! Interfaces (traits) for graph implementations.

use std;
use std::fmt::Debug;
use std::iter::{Chain,Iterator,IntoIterator};

use super::visit::{self,Visit};
use super::iter::Successors;

/// Interface provided by node and edge identifiers.
pub trait Id: Copy + Debug + PartialEq + PartialOrd {
    /// Create a new Id object with the given value.
    fn new(v: usize) -> Self;

    /// Retrieve the underlying integer value of the identifier.
    fn index(&self) -> usize;
}

/// Any directed edge type used by a graph.
pub trait Edge: Debug {
    /// Type used to identify source and destination nodes.
    type NodeId: Id;

    /// Get index of the edge's source node.
    fn source(&self) -> Self::NodeId;

    /// Get index of the edge's target node.
    fn target(&self) -> Self::NodeId;
}

/// Any node type used by a graph.
pub trait Node: Debug {
    /// Type used to identify incoming and outgoing edges.
    type EdgeId: Id;

    /// Get an iterator over all (incoming + outgoing) edges connected to
    /// the node.
    fn edges(&self) -> Chain<std::slice::Iter<Self::EdgeId>, std::slice::Iter<Self::EdgeId>> {
        self.incoming_edges().into_iter().chain(self.outgoing_edges().into_iter())
    }

    /// Get an iterator over incoming edges connected to the node.
    ///
    /// Note that if an edge has the node's index as both its source _and_ its
    /// target, it should appear in the set of values returned by this iterator
    /// **and** that returned by the iterator obtained from `outgoing_edges`.
    fn incoming_edges(&self) -> std::slice::Iter<Self::EdgeId>;

    /// Get the number of incoming edges.
    fn incoming_edge_count(&self) -> usize;

    /// Get an iterator over outgoing edges connected to the node.
    ///
    /// Note that if an edge has the node's index as both its source _and_ its
    /// target, it should appear in the set of values returned by this iterator
    /// **and** that returned by the iterator obtained from `incoming_edges`.
    fn outgoing_edges(&self) -> std::slice::Iter<Self::EdgeId>;

    /// Get the number of outgoing edges.
    fn outgoing_edge_count(&self) -> usize;

    /// Record the existence of an edge that terminates at this node.
    fn add_incoming_edge(&mut self, e: Self::EdgeId);

    /// Record the existence of an edge that originates from this node.
    fn add_outgoing_edge(&mut self, e: Self::EdgeId);
}

/// Common interface for all graph types.
pub trait Graph {
    /// Type used to identify nodes for lookup.
    type NodeId: Id;

    /// Type used to identify edges for lookup.
    type EdgeId: Id;

    /// Concrete node type used by a graph.
    type Node: Node<EdgeId=Self::EdgeId>;

    /// Concrete edge type used by a graph.
    type Edge: Edge<NodeId=Self::NodeId>;

    /// Iterator returned from `node_ids`.
    type NodeIdIterator: Iterator<Item=Self::NodeId>;

    /// Iterator returned from `edge_ids`.
    type EdgeIdIterator: Iterator<Item=Self::EdgeId>;

    // --------------------------------

    /// Create a new, empty instance of this graph type.
    fn new() -> Self
        where Self: Sized + Default {
        Default::default()
    }

    // --------------------------------

    /// Add an explicitly-specified node to the graph, returning its unique
    /// identifier.
    fn add_node<T: Into<Self::Node>>(&mut self, n: T) -> Self::NodeId;

    /// Fetch a reference to a node.
    ///
    /// If the given node ID is invalid, i.e. `self.contains_node(n)` is false,
    /// this call should **panic**.
    fn node(&self, n: Self::NodeId) -> &Self::Node;

    /// Fetch a mutable reference to a node.
    ///
    /// If the given node ID is invalid, i.e. `self.contains_node(n)` is false,
    /// this call should **panic**.
    fn node_mut(&mut self, n: Self::NodeId) -> &mut Self::Node;

    /// Check if a node ID is valid for this graph.
    fn contains_node(&self, n: Self::NodeId) -> bool;

    /// Fetch an iterator over the IDs of all nodes in the graph.
    fn node_ids(&self) -> Self::NodeIdIterator;

    /// Count the number of nodes in the graph.
    fn node_count(&self) -> usize;

    // --------------------------------

    /// Add an explicitly-specified edge to the graph, returning its
    /// unique identifier.
    fn add_edge<T: Into<Self::Edge>>(&mut self, e: T) -> Self::EdgeId;

    /// Fetch a reference to an edge.
    ///
    /// If the given node ID is invalid, i.e. `self.contains_node(n)` is false,
    /// this call should **panic**.
    fn edge(&self, e: Self::EdgeId) -> &Self::Edge;

    /// Check if an edge ID is valid for this graph.
    fn contains_edge(&self, e: Self::EdgeId) -> bool;

    /// Fetch an iterator over the IDs of all edges in the graph.
    fn edge_ids(&self) -> Self::EdgeIdIterator;

    /// Count the number of edges in the graph.
    fn edge_count(&self) -> usize;

    // --------------------------------

    /// Fetch an iterator over the direct successors of a node.
    ///
    /// If the given node ID is invalid, i.e. `self.contains_node(n)` is false,
    /// this call should **panic**.
    fn direct_successors(&self, n: Self::NodeId) -> Successors<Self>
        where Self: Sized {
        Successors::new(self, self.node(n).outgoing_edges())
    }

    /// Get an iterator over incoming edges connected to a node.
    ///
    /// Note that if an edge has a node's index as both its source _and_ its
    /// target, it should appear in the set of values returned by this iterator
    /// _and_ that returned by the iterator obtained from `outgoing_edges` for
    /// the same node.
    ///
    /// If the given node ID is invalid, i.e. `self.contains_node(n)` is false,
    /// this call should **panic**.
    fn incoming_edges(&self, n: Self::NodeId) -> std::slice::Iter<Self::EdgeId> {
        self.node(n).incoming_edges()
    }

    /// Get an iterator over outgoing edges connected to a node.
    ///
    /// Note that if an edge has a node's index as both its source _and_ its
    /// target, it should appear in the set of values returned by this iterator
    /// _and_ that returned by the iterator obtained from `incoming_edges` for
    /// the same node.
    ///
    /// If the given node ID is invalid, i.e. `self.contains_node(n)` is false,
    /// this call should **panic**.
    fn outgoing_edges(&self, n: Self::NodeId) -> std::slice::Iter<Self::EdgeId> {
        self.node(n).outgoing_edges()
    }

    /// Get an iterator over all edges connected to a node.
    ///
    /// Note that if a node is both the source source _and_ the target for an
    /// edge, that edge's index will be returned twice by the iterator.
    ///
    /// If the given node ID is invalid, i.e. `self.contains_node(n)` is false,
    /// this call will **panic**.
    fn edges(&self, n: Self::NodeId) -> Chain<std::slice::Iter<Self::EdgeId>,
                                              std::slice::Iter<Self::EdgeId>> {
        if self.contains_node(n) {
            self.node(n).edges()
        } else {
            panic!("Invalid node ID supplied to Graph::edges()");
        }
    }

    /// Convert all elements in a slice to edges, and add them to the graph.
    ///
    /// Each element of the slice can be any type convertible to an edge using
    /// `std::convert::From`; at the time of writing this means one of two
    /// tuple forms:
    ///
    ///   * `(source_node_index, target_node_index, payload)`, where the edge
    ///     is fully specified as arguments to `add_edge`, or
    ///   * `(source_node_index, target_node_index)`, where the edge's payload
    ///     is created using the `Default` trait.
    ///
    /// ```rust
    /// use cripes::util::graph::*;
    ///
    /// # fn main() {
    /// let mut g = WeightedGraph::<(),(),u8>::new();
    /// let n0 = g.add_node(());
    /// let n1 = g.add_node(());
    /// let n2 = g.add_node(());
    /// let n3 = g.add_node(());
    ///
    /// g.add_edges(&[(n0, n1), (n1, n2), (n1, n3), (n2, n3), (n3, n2)]);
    ///
    /// # }
    /// ```
    ///
    /// If any endpoint refers to a node that does not exist, this call will
    /// **panic**.
    fn add_edges<'a, D>(&mut self, edges: &'a [D]) where D: 'a, Self::Edge: From<&'a D> {
        for e in edges.iter() {
            let edge = Self::Edge::from(e);
            if ! self.contains_node(edge.source()) {
                panic!("Invalid source node ({:?}) specified for edge in argument to Graph::add_edges",
                       edge.source());
            } else if ! self.contains_node(edge.target()) {
                panic!("Invalid target node ({:?}) specified for edge in argument to Graph::add_edges",
                       edge.target());
            } else {
                self.add_edge(edge);
            }
        }
    }

    /// Fetch the IDs of an edge's source and target nodes.
    ///
    /// If the given edge ID is invalid, i.e. `self.contains_edge(e)` is false,
    /// this call should **panic**.
    fn edge_endpoints(&self, e: Self::EdgeId) -> (Self::NodeId, Self::NodeId) {
        let edge = self.edge(e);
        (edge.source(), edge.target())
    }

    /// Fetch the index of the node from which a given edge originates.
    ///
    /// If the given edge ID is invalid, i.e. `self.contains_edge(e)` is false,
    /// this call should **panic**.
    fn edge_source(&self, e: Self::EdgeId) -> Self::NodeId {
        self.edge(e).source()
    }

    /// Fetch the index of the node at which a given edge terminates.
    ///
    /// If the given edge ID is invalid, i.e. `self.contains_edge(e)` is false,
    /// this call should **panic**.
    fn edge_target(&self, e: Self::EdgeId) -> Self::NodeId {
        self.edge(e).target()
    }

    /*/// Iterate over the graph using a self-starting algorithm.
    ///
    /// Self-starting algorithms are those that select initial node(s) on
    /// their own.
    fn iter<A: visit::SelfStartingAlgorithm<Self>>(&self) -> visit::VisitorIter<Self, A>
        where Self: Sized {
        visit::Visitor::new::<Self, A>(self).into_iter(self)
    }*/

    /// Iterate over the graph using a rooted algorithm.
    ///
    /// Rooted algorithms are those that operate using a pre-defined root node
    /// or nodes.
    fn iter<A: visit::RootedAlgorithm<Self>>(&self, entry: Self::NodeId) -> visit::VisitorIter<Self, visit::Visitor<Self, A>>
        where Self: Sized {
        visit::Visitor::new(self, entry.into()).into_iter(self)
    }
}
<|endoftext|>


<commit_before>use std::io::{BufRead, BufReader};
use std::fs::File;
use regex::Regex;

// data defining a RdYlBu ColorMap (taken from the matplotlib python module)
const RD_TL_BU_DATA: [[f32; 3]; 11] = [
    [0.6470588235294118 , 0.0                 , 0.14901960784313725],
    [0.84313725490196079, 0.18823529411764706 , 0.15294117647058825],
    [0.95686274509803926, 0.42745098039215684 , 0.2627450980392157 ],
    [0.99215686274509807, 0.68235294117647061 , 0.38039215686274508],
    [0.99607843137254903, 0.8784313725490196  , 0.56470588235294117],
    [1.0                , 1.0                 , 0.74901960784313726],
    [0.8784313725490196 , 0.95294117647058818 , 0.97254901960784312],
    [0.6705882352941176 , 0.85098039215686272 , 0.9137254901960784 ],
    [0.45490196078431372, 0.67843137254901964 , 0.81960784313725488],
    [0.27058823529411763, 0.45882352941176469 , 0.70588235294117652],
    [0.19215686274509805, 0.21176470588235294 , 0.58431372549019611]
];

// data defining a BrBG ColorMap (taken from the matplotlib python module)
const BR_BG_DATA: [[f32; 3]; 11] = [
    [0.32941176470588235,  0.18823529411764706,  0.0196078431372549 ],
    [0.5490196078431373 ,  0.31764705882352939,  0.0392156862745098 ],
    [0.74901960784313726,  0.50588235294117645,  0.17647058823529413],
    [0.87450980392156863,  0.76078431372549016,  0.49019607843137253],
    [0.96470588235294119,  0.90980392156862744,  0.76470588235294112],
    [0.96078431372549022,  0.96078431372549022,  0.96078431372549022],
    [0.7803921568627451 ,  0.91764705882352937,  0.89803921568627454],
    [0.50196078431372548,  0.80392156862745101,  0.75686274509803919],
    [0.20784313725490197,  0.59215686274509804,  0.5607843137254902 ],
    [0.00392156862745098,  0.4                ,  0.36862745098039218],
    [0.0                ,  0.23529411764705882,  0.18823529411764706]
];

/// This struct represents a user defined color map,
/// It should directly map values to colors
pub struct CustomColormap {
    values: Vec<f32>,
    colors: Vec<[u8; 3]>
}
impl CustomColormap {

    /// Create a Custom colormap from a QGis colormap file
    ///
    /// # Caution
    /// It only support interpolated colormap
    pub fn from_qgis_file(file: &str) -> Result<ColorMap, String> {
        let file = File::open(file).map_err(|e| e.to_string())?;
        let mut reader = BufReader::new(file);
        let mut colors: Vec<[u8; 3]> = Vec::new();
        let mut values: Vec<f32> = Vec::new();
        let mut line = String::new();

        // match a QGIS colormap value
        let data_regex =  Regex::new(
            r"^(?P<value>\d+),(?P<red>\d+),(?P<green>\d+),(?P<blue>\d+),\d+,\d+(\.\d*)?\s*$"
        ).unwrap();
        // Iter line of the file
        while let Ok(bytes_read) = reader.read_line(&mut line) {
            if bytes_read == 0 { break; }
            if let Some(capture) = data_regex.captures(&line) {
                // parse each value + pixel color using a big dirty regex
                let value: f32 = capture.name("value").unwrap().as_str().parse::<f32>().unwrap();
                let red: u8 = capture.name("red").unwrap().as_str().parse::<u8>().unwrap();
                let green: u8 = capture.name("green").unwrap().as_str().parse::<u8>().unwrap();
                let blue: u8 = capture.name("blue").unwrap().as_str().parse::<u8>().unwrap();
                colors.push([red, green, blue]);
                values.push(value);
            }
            line.clear();
        }
        if colors.len() > 0 && colors.len() == values.len() {
            return Ok(ColorMap::Custom(
                Self {
                    colors: colors,
                    values: values
                }
            ));
        }
        Err("Could not parse the QGis file".into())
    }

    /// returns a pixel value, from a dataset value.
    fn value_to_color(&self, value: f32) -> [u8; 3] {
        if self.values.len() == 1 || self.values[0] >= value {
            return self.colors[self.values.len() -1];
        }
        if value >= self.values[self.values.len() -1] {
            return self.colors[self.values.len() -1];
        }
        for i in 0..(self.values.len() - 1) {
            if value == self.values[i] {
                return self.colors[i];
            }
            if value > self.values[i] && value < self.values[i + 1] {
                let mut rgb: [u8; 3] = [0; 3];
                let lower_diff = value - self.values[i];
                let upper_diff = self.values[i+1] - value;
                let diff = self.values[i+1] - self.values[i];
                for j in 0..rgb.len() {
                    rgb[j] = ((
                          self.colors[i][j] as f32 * upper_diff + self.colors[i+1][j] as f32 * lower_diff
                       ) / diff ) as u8;
                }
                return rgb;
            }
        }
        [22; 3]
    }
}

/// Defines values to color association.
///
/// By convention, a `Foo_r` Colormap Variant represents the `Foo` colormap reversed.
///
#[allow(non_camel_case_types)]
pub enum ColorMap {
    /// black to gray colorMap
    Grayscale,
    /// Red Yellow Blue colorMap
    RdYlBu,
    /// Reversed Red Yellow Blue ColorMap
    RdYlBu_r,
    /// Brown to Green
    BrBG,
    /// Brown to Green, reversed
    BrBG_r,
    /// User defined
    Custom(CustomColormap),
}

fn value_to_grayscale(value: f32) -> [u8; 3] {
    let gray = ((value * 255.) % 255.) as u8;
    [gray, gray, gray]
}

/**
 * Returns pixel colors from a value (between 0 and 1),
 * It linearly interpolate the color between the colors defined in `data`
 */
fn value_to_color(value: f32, data: &[[f32; 3]], reverse: bool) -> [u8; 3] {
    // reverse the value if asked
    let scaled: f32 = if reverse {
        (1. - value) * ((data.len() -1) as f32)
    } else {
        value * ((data.len() -1) as f32)
    };
    // get the minimum indice needed for the interpolation
    let idx = scaled.floor() as usize;
    let weight = scaled % 1.;

    let mut rgb: [u8; 3] = [0; 3];
    if idx == data.len() -1 {
        // don't interpolate max values
        for i in 0..rgb.len() {
            rgb[i] = (data[data.len() -1][i] * 255.) as u8;
        }
    } else {
        // perform the interpolation for each pixel color (RGB)
        for i in 0..rgb.len() {
            // this is basically a weighted mean
            rgb[i] = ((data[idx][i] * (1. - weight) + weight * data[idx + 1][i]) * 255.) as u8;
        }
    }
    rgb
}

/**
 * Returns a pixel color from a [0; 1] f32 value
 * and a ColorMap variant
 */
pub fn rgb(value: f32, color_map: &ColorMap) -> [u8; 3] {
    match *color_map {
        ColorMap::Grayscale => { value_to_grayscale(value) },
        ColorMap::RdYlBu => {
            value_to_color(value, &RD_TL_BU_DATA, false)
        },
        ColorMap::RdYlBu_r => {
            value_to_color(value, &RD_TL_BU_DATA, true)
        },
        ColorMap::BrBG => {
            value_to_color(value, &BR_BG_DATA, false)
        },
        ColorMap::BrBG_r => {
            value_to_color(value, &BR_BG_DATA, true)
        },
        ColorMap::Custom(ref cmap) => {
            cmap.value_to_color(value)
        },
    }
}

#[test]
fn test_colormap_interpolation() {
    let data: [[f32; 3]; 4] = [
        [0., 0., 0.],
        [1./3., 1./3., 1./3.],
        [2./3., 2./3., 2./3.],
        [1., 1., 1.],
    ];
    // test interpolation for 0, 0.5 and 1
    assert_eq!(value_to_color(0., &data, false), [0u8; 3]);
    assert_eq!(value_to_color(1., &data, false), [255u8; 3]);
    assert_eq!(value_to_color(0.5, &data, false), [(255 / 2) as u8; 3]);

    // test interpolation for 0, 0.5 and 1 with revesed colormap
    assert_eq!(value_to_color(0., &data, true), [255u8; 3]);
    assert_eq!(value_to_color(1., &data, true), [0u8; 3]);
    assert_eq!(value_to_color(0.5, &data, true), [(255 / 2) as u8; 3]);
}

#[test]
/// Parse a sample QGis colormap file
fn qgis_colormap_parser() {
    let colormap_path = "./examples_data/qgis_colormap.txt";
    let colormap = CustomColormap::from_qgis_file(
        colormap_path
    ).unwrap();
    let expected_values = vec![
        0.,
        1000.,
        2000.,
        3000.,
        4000.,
        5000.,
        6000.,
    ];
    match colormap {
        ColorMap::Custom(cmap) => {
            assert_eq!(cmap.colors.len(), expected_values.len());
            assert_eq!(cmap.values, expected_values);
        }
        _ => { panic!("QGis colormap oarsing failed") }
    }
}
<commit_msg>Added reversed Grayscale<commit_after>use std::io::{BufRead, BufReader};
use std::fs::File;
use regex::Regex;

// data defining a RdYlBu ColorMap (taken from the matplotlib python module)
const RD_TL_BU_DATA: [[f32; 3]; 11] = [
    [0.6470588235294118 , 0.0                 , 0.14901960784313725],
    [0.84313725490196079, 0.18823529411764706 , 0.15294117647058825],
    [0.95686274509803926, 0.42745098039215684 , 0.2627450980392157 ],
    [0.99215686274509807, 0.68235294117647061 , 0.38039215686274508],
    [0.99607843137254903, 0.8784313725490196  , 0.56470588235294117],
    [1.0                , 1.0                 , 0.74901960784313726],
    [0.8784313725490196 , 0.95294117647058818 , 0.97254901960784312],
    [0.6705882352941176 , 0.85098039215686272 , 0.9137254901960784 ],
    [0.45490196078431372, 0.67843137254901964 , 0.81960784313725488],
    [0.27058823529411763, 0.45882352941176469 , 0.70588235294117652],
    [0.19215686274509805, 0.21176470588235294 , 0.58431372549019611]
];

// data defining a BrBG ColorMap (taken from the matplotlib python module)
const BR_BG_DATA: [[f32; 3]; 11] = [
    [0.32941176470588235,  0.18823529411764706,  0.0196078431372549 ],
    [0.5490196078431373 ,  0.31764705882352939,  0.0392156862745098 ],
    [0.74901960784313726,  0.50588235294117645,  0.17647058823529413],
    [0.87450980392156863,  0.76078431372549016,  0.49019607843137253],
    [0.96470588235294119,  0.90980392156862744,  0.76470588235294112],
    [0.96078431372549022,  0.96078431372549022,  0.96078431372549022],
    [0.7803921568627451 ,  0.91764705882352937,  0.89803921568627454],
    [0.50196078431372548,  0.80392156862745101,  0.75686274509803919],
    [0.20784313725490197,  0.59215686274509804,  0.5607843137254902 ],
    [0.00392156862745098,  0.4                ,  0.36862745098039218],
    [0.0                ,  0.23529411764705882,  0.18823529411764706]
];

/// This struct represents a user defined color map,
/// It should directly map values to colors
pub struct CustomColormap {
    values: Vec<f32>,
    colors: Vec<[u8; 3]>
}
impl CustomColormap {

    /// Create a Custom colormap from a QGis colormap file
    ///
    /// # Caution
    /// It only support interpolated colormap
    pub fn from_qgis_file(file: &str) -> Result<ColorMap, String> {
        let file = File::open(file).map_err(|e| e.to_string())?;
        let mut reader = BufReader::new(file);
        let mut colors: Vec<[u8; 3]> = Vec::new();
        let mut values: Vec<f32> = Vec::new();
        let mut line = String::new();

        // match a QGIS colormap value
        let data_regex =  Regex::new(
            r"^(?P<value>\d+),(?P<red>\d+),(?P<green>\d+),(?P<blue>\d+),\d+,\d+(\.\d*)?\s*$"
        ).unwrap();
        // Iter line of the file
        while let Ok(bytes_read) = reader.read_line(&mut line) {
            if bytes_read == 0 { break; }
            if let Some(capture) = data_regex.captures(&line) {
                // parse each value + pixel color using a big dirty regex
                let value: f32 = capture.name("value").unwrap().as_str().parse::<f32>().unwrap();
                let red: u8 = capture.name("red").unwrap().as_str().parse::<u8>().unwrap();
                let green: u8 = capture.name("green").unwrap().as_str().parse::<u8>().unwrap();
                let blue: u8 = capture.name("blue").unwrap().as_str().parse::<u8>().unwrap();
                colors.push([red, green, blue]);
                values.push(value);
            }
            line.clear();
        }
        if colors.len() > 0 && colors.len() == values.len() {
            return Ok(ColorMap::Custom(
                Self {
                    colors: colors,
                    values: values
                }
            ));
        }
        Err("Could not parse the QGis file".into())
    }

    /// returns a pixel value, from a dataset value.
    fn value_to_color(&self, value: f32) -> [u8; 3] {
        if self.values.len() == 1 || self.values[0] >= value {
            return self.colors[self.values.len() -1];
        }
        if value >= self.values[self.values.len() -1] {
            return self.colors[self.values.len() -1];
        }
        for i in 0..(self.values.len() - 1) {
            if value == self.values[i] {
                return self.colors[i];
            }
            if value > self.values[i] && value < self.values[i + 1] {
                let mut rgb: [u8; 3] = [0; 3];
                let lower_diff = value - self.values[i];
                let upper_diff = self.values[i+1] - value;
                let diff = self.values[i+1] - self.values[i];
                for j in 0..rgb.len() {
                    rgb[j] = ((
                          self.colors[i][j] as f32 * upper_diff + self.colors[i+1][j] as f32 * lower_diff
                       ) / diff ) as u8;
                }
                return rgb;
            }
        }
        [22; 3]
    }
}

/// Defines values to color association.
///
/// By convention, a `Foo_r` Colormap Variant represents the `Foo` colormap reversed.
///
#[allow(non_camel_case_types)]
pub enum ColorMap {
    /// black to white colorMap
    Grayscale,
    /// white to black colorMap
    Grayscale_r,
    /// Red Yellow Blue colorMap
    RdYlBu,
    /// Reversed Red Yellow Blue ColorMap
    RdYlBu_r,
    /// Brown to Green
    BrBG,
    /// Brown to Green, reversed
    BrBG_r,
    /// User defined
    Custom(CustomColormap),
}

fn value_to_grayscale(value: f32) -> [u8; 3] {
    let gray = ((value * 255.) % 255.) as u8;
    [gray, gray, gray]
}

/**
 * Returns pixel colors from a value (between 0 and 1),
 * It linearly interpolate the color between the colors defined in `data`
 */
fn value_to_color(value: f32, data: &[[f32; 3]], reverse: bool) -> [u8; 3] {
    // reverse the value if asked
    let scaled: f32 = if reverse {
        (1. - value) * ((data.len() -1) as f32)
    } else {
        value * ((data.len() -1) as f32)
    };
    // get the minimum indice needed for the interpolation
    let idx = scaled.floor() as usize;
    let weight = scaled % 1.;

    let mut rgb: [u8; 3] = [0; 3];
    if idx == data.len() -1 {
        // don't interpolate max values
        for i in 0..rgb.len() {
            rgb[i] = (data[data.len() -1][i] * 255.) as u8;
        }
    } else {
        // perform the interpolation for each pixel color (RGB)
        for i in 0..rgb.len() {
            // this is basically a weighted mean
            rgb[i] = ((data[idx][i] * (1. - weight) + weight * data[idx + 1][i]) * 255.) as u8;
        }
    }
    rgb
}

/**
 * Returns a pixel color from a [0; 1] f32 value
 * and a ColorMap variant
 */
pub fn rgb(value: f32, color_map: &ColorMap) -> [u8; 3] {
    match *color_map {
        ColorMap::Grayscale => { value_to_grayscale(value) },
        ColorMap::Grayscale_r => { value_to_grayscale(1. - value) },
        ColorMap::RdYlBu => {
            value_to_color(value, &RD_TL_BU_DATA, false)
        },
        ColorMap::RdYlBu_r => {
            value_to_color(value, &RD_TL_BU_DATA, true)
        },
        ColorMap::BrBG => {
            value_to_color(value, &BR_BG_DATA, false)
        },
        ColorMap::BrBG_r => {
            value_to_color(value, &BR_BG_DATA, true)
        },
        ColorMap::Custom(ref cmap) => {
            cmap.value_to_color(value)
        },
    }
}

#[test]
fn test_colormap_interpolation() {
    let data: [[f32; 3]; 4] = [
        [0., 0., 0.],
        [1./3., 1./3., 1./3.],
        [2./3., 2./3., 2./3.],
        [1., 1., 1.],
    ];
    // test interpolation for 0, 0.5 and 1
    assert_eq!(value_to_color(0., &data, false), [0u8; 3]);
    assert_eq!(value_to_color(1., &data, false), [255u8; 3]);
    assert_eq!(value_to_color(0.5, &data, false), [(255 / 2) as u8; 3]);

    // test interpolation for 0, 0.5 and 1 with revesed colormap
    assert_eq!(value_to_color(0., &data, true), [255u8; 3]);
    assert_eq!(value_to_color(1., &data, true), [0u8; 3]);
    assert_eq!(value_to_color(0.5, &data, true), [(255 / 2) as u8; 3]);
}

#[test]
/// Parse a sample QGis colormap file
fn qgis_colormap_parser() {
    let colormap_path = "./examples_data/qgis_colormap.txt";
    let colormap = CustomColormap::from_qgis_file(
        colormap_path
    ).unwrap();
    let expected_values = vec![
        0.,
        1000.,
        2000.,
        3000.,
        4000.,
        5000.,
        6000.,
    ];
    match colormap {
        ColorMap::Custom(cmap) => {
            assert_eq!(cmap.colors.len(), expected_values.len());
            assert_eq!(cmap.values, expected_values);
        }
        _ => { panic!("QGis colormap oarsing failed") }
    }
}
<|endoftext|>