<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,
            W: SAppWrapper + Send + Sync + Reflect + Clone
    {
    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
    }
}

// this is very expensive in time
// should make it as global
lazy_static! {
    static ref MTYPES: MimeTypes = { MimeTypes::new().unwrap() };
}

fn simple_file_get(path: &str) -> Result<(Vec<u8>, String)> {
    let new_path;
    if &path[(path.len()-1)..] == "/" {
        new_path = "static/".to_owned() + path + "index.html";
    }
    else {
        new_path = "static/".to_owned() + path;
    }
    //println!("file path: {}", new_path);
    match File::open(&new_path) {
        Ok(ref mut file) => {
            let mut s: Vec<u8> = vec![];
            file.read_to_end(&mut s).unwrap_or(0);

            let mt_str = MTYPES.mime_for_path(Path::new(&new_path));

            Ok((s, mt_str.to_owned()))
        },
        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 {

        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, mt_str)) => {
                                    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 = MTYPES.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()
            }
        }

    }
}
<commit_msg>try to use chunked encoding to response.<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,
            W: SAppWrapper + Send + Sync + Reflect + Clone
    {
    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
    }
}

// this is very expensive in time
// should make it as global
lazy_static! {
    static ref MTYPES: MimeTypes = { MimeTypes::new().unwrap() };
}

fn simple_file_get(path: &str) -> Result<(Vec<u8>, String)> {
    let new_path;
    if &path[(path.len()-1)..] == "/" {
        new_path = "static/".to_owned() + path + "index.html";
    }
    else {
        new_path = "static/".to_owned() + path;
    }
    //println!("file path: {}", new_path);
    match File::open(&new_path) {
        Ok(ref mut file) => {
            let mut s: Vec<u8> = vec![];
            file.read_to_end(&mut s).unwrap_or(0);

            let mt_str = MTYPES.mime_for_path(Path::new(&new_path));

            Ok((s, mt_str.to_owned()))
        },
        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 {

        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, mt_str)) => {
                                    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 = MTYPES.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 core::prelude::*;
use core::cmp::{min, max};
use core::mem::{size_of, zeroed, replace, swap, transmute};
use core::ptr;

/// The smallest number of elements that may be quicksorted.
/// Must be at least 9.
const MIN_QUICKSORT_ELEMS: uint = 10;

/// The maximum number of elements to be insertion sorted.
const MAX_INSERTION_SORT_ELEMS: uint = 42;

/// Controls the number of elements to be insertion sorted.
/// Higher values give more insertion sorted elements.
const INSERTION_SORT_FACTOR: uint = 450;

pub fn sort_by<'a, T: 'a, C: Fn<(&'a T, &'a T), Ordering>>(v: &mut [T], compare: &C) {
    if maybe_insertion_sort(v, compare) { return; }
    let heapsort_depth = (3 * log2(v.len())) / 2;
    do_introsort(v, compare, 0, heapsort_depth);
}

#[inline]
pub fn sort<T: Ord>(v: &mut [T]) {
    sort_by(v, &|&: a: &T, b| a.cmp(b));
}

fn introsort<'a, T: 'a, C: Fn<(&'a T, &'a T), Ordering>>(v: &mut [T], compare: &C, rec: u32, heapsort_depth: u32) {
    if maybe_insertion_sort(v, compare) { return; }
    do_introsort(v, compare, rec, heapsort_depth);
}

fn do_introsort<'a, T: 'a, C: Fn<(&'a T, &'a T), Ordering>>(v: &mut [T], compare: &C, rec: u32, heapsort_depth: u32) {
    // This works around some bugs with unboxed closures
    macro_rules! maybe_swap(
        ($v: expr, $a: expr, $b: expr, $compare: expr) => {
            if compare_idxs($v, *$a, *$b, $compare) == Greater {
                swap($a, $b);
            }
        }
    )

    if rec > heapsort_depth {
        heapsort(v, compare);
        return;
    }

    let n = v.len();

    // Pivot selection algorithm based on Java's DualPivotQuicksort.

    // Fast approximation of n / 7
    let seventh = (n / 8) + (n / 64) + 1;

    // Pick five element evenly spaced around the middle (inclusive) of the slice.
    let mut e3 = n / 2;
    let mut e2 = e3 - seventh;
    let mut e1 = e3 - 2*seventh;
    let mut e4 = e3 + seventh;
    let mut e5 = e3 + 2*seventh;

    // Sort them with a sorting network.
    unsafe {
        maybe_swap!(v, &mut e1, &mut e2, compare);
        maybe_swap!(v, &mut e4, &mut e5, compare);
        maybe_swap!(v, &mut e3, &mut e5, compare);
        maybe_swap!(v, &mut e3, &mut e4, compare);
        maybe_swap!(v, &mut e2, &mut e5, compare);
        maybe_swap!(v, &mut e1, &mut e4, compare);
        maybe_swap!(v, &mut e1, &mut e3, compare);
        maybe_swap!(v, &mut e2, &mut e4, compare);
        maybe_swap!(v, &mut e2, &mut e3, compare);
    }

    if unsafe { compare_idxs(v, e1, e2, compare) != Equal &&
                compare_idxs(v, e2, e3, compare) != Equal &&
                compare_idxs(v, e3, e4, compare) != Equal &&
                compare_idxs(v, e4, e5, compare) != Equal } {
        // No consecutive pivot candidates are the same, meaning there is some variaton.
        dual_pivot_sort(v, (e1, e2, e3, e4, e5), compare, rec, heapsort_depth);
    } else {
        // Two consecutive pivots candidates where the same.
        // There are probably many similar elements.
        single_pivot_sort(v, e3, compare, rec, heapsort_depth);
    }
}

fn maybe_insertion_sort<'a, T: 'a, C: Fn<(&'a T, &'a T), Ordering>>(v: &mut [T], compare: &C) -> bool {
    let n = v.len();
    if n <= 1 {
        return true;
    }

    let threshold = min(MAX_INSERTION_SORT_ELEMS,
                        max(MIN_QUICKSORT_ELEMS, INSERTION_SORT_FACTOR / size_of::<T>()));
    if n <= threshold {
        insertion_sort(v, compare);
        return true;
    }
    return false;
}

pub fn insertion_sort<'a, T: 'a, C: Fn<(&'a T, &'a T), Ordering>>(v: &mut [T], compare: &C) {
    let mut i = 1;
    let n = v.len();
    while i < n {
        let mut j = i;
        while j > 0 && unsafe { compare_idxs(v, j-1, j, compare) } == Greater {
            unsafe { unsafe_swap(v, j, j-1); }
            j -= 1;
        }
        i += 1;
    }
}

fn dual_pivot_sort<'a, T: 'a, C: Fn<(&'a T, &'a T), Ordering>>(v: &mut [T], pivots: (uint, uint, uint, uint, uint),
                                                               compare: &C, rec: u32, heapsort_depth: u32) {
    let (pmin, p1, _pmid, p2, pmax) = pivots;
    let n = v.len();

    let lp = 0;
    let rp = n - 1;

    v.swap(p1, lp);
    v.swap(p2, rp);

    let mut lesser = 1;
    let mut greater = n - 2;

    unsafe {
        // Skip elements that are already in the correct position
        while compare_idxs(v, lesser, lp, compare) == Less { lesser += 1; }
        while compare_idxs(v, greater, rp, compare) == Greater { greater -= 1; }

        let mut k = lesser;
        // XXX We make some unecessary swaps since we can't leave uninitialized values
        // in `v` in case `compare` unwinds.
        while k <= greater {
            if compare_idxs(v, k, lp, compare) == Less {
                unsafe_swap(v, k, lesser);
                lesser += 1;
            } else {
                let cmp = compare_idxs(v, k, rp, compare);
                if cmp == Greater || cmp == Equal {
                    while k < greater && compare_idxs(v, greater, rp, compare) == Greater {
                        greater -= 1;
                    }
                    unsafe_swap(v, k, greater);
                    greater -= 1;
                    if compare_idxs(v, k, lp, compare) == Less {
                        unsafe_swap(v, k, lesser);
                        lesser += 1;
                    }
                }
            }
            k += 1;
        }
    }

    lesser -= 1;
    greater += 1;

    // Swap back pivots
    unsafe {
        unsafe_swap(v, lp, lesser);
        unsafe_swap(v, rp, greater);
    }

    // Sort left and right partition
    introsort(v[mut ..lesser], compare, rec + 1, heapsort_depth);
    introsort(v[mut greater+1..], compare, rec + 1, heapsort_depth);

    // Sort center partition
    let left = lesser+1;
    let right = greater;
    if lesser >= pmin || greater <= pmax {
        // Center partition is small
        let mid = (right - left) / 2;
        if maybe_insertion_sort(v[mut left..right], compare) { return; }
        single_pivot_sort(v[mut left..right], mid, compare, rec + 1, heapsort_depth);
    } else {
        // Center partition is big
        introsort(v[mut left..right], compare, rec + 1, heapsort_depth);
    }
}

fn single_pivot_sort<'a, T: 'a, C: Fn<(&'a T, &'a T), Ordering>>(v: &mut [T], pivot: uint, compare: &C, rec: u32, heapsort_depth: u32) {
    let (l, r) = fat_partition(v, pivot, compare);
    let n = v.len();
    if l > 1 {
        introsort(v[mut ..l], compare, rec + 1, heapsort_depth);
    }
    if r > 1 {
        introsort(v[mut n - r..], compare, rec + 1, heapsort_depth);
    }
}

/// Partitions elements, using the element at `pivot` as pivot.
/// After partitioning, the array looks as following:
/// <<<<<==>>>
/// Return (number of < elements, number of > elements)
fn fat_partition<'a, T: 'a, C: Fn<(&'a T, &'a T), Ordering>>(v: &mut [T], pivot: uint, compare: &C) -> (uint, uint)  {
    let mut a = 0;
    let mut b = a;
    let mut c = v.len() - 1;
    let mut d = c;
    v.swap(0, pivot);
    loop {
        while b <= c {
            let r = compare_idxs_safe(v, b, 0, compare);
            if r == Greater { break; }
            if r == Equal {
                unsafe { unsafe_swap(v, a, b); }
                a += 1;
            }
            b += 1;
        }
        while c >= b {
            let r = compare_idxs_safe(v, c, 0, compare);
            if r == Less { break; }
            if r == Equal {
                unsafe { unsafe_swap(v, c, d); }
                d -= 1;
            }
            c -= 1;
        }
        if b > c { break; }
        unsafe { unsafe_swap(v, b, c); }
        b += 1;
        c -= 1;
    }

    let n = v.len();
    let l = min(a, b - a);
    unsafe { swap_many(v, 0, b - l, l); }
    let r = min(d - c, n - 1 - d);
    unsafe { swap_many(v, b, n - r, r); }

    return (b - a, d - c);
}

unsafe fn swap_many<T>(v: &mut [T], a: uint, b: uint, n: uint) {
    let mut i = 0;
    while i < n {
        unsafe_swap(v, a + i, b + i);
        i += 1;
    }
}

#[cold]
#[inline(never)]
pub fn heapsort<'a, T: 'a, C: Fn<(&'a T, &'a T), Ordering>>(v: &mut [T], compare: &C) {
    heapify(v, compare);
    let mut end = v.len();
    while end > 0 {
        end -= 1;
        v.swap(0, end);
        siftdown_range(v, 0, end, compare);
    }
}

#[inline]
fn heapify<'a, T: 'a, C: Fn<(&'a T, &'a T), Ordering>>(v: &mut [T], compare: &C) {
    let mut n = v.len() / 2;
    while n > 0 {
        n -= 1;
        siftdown(v, n, compare)
    }
}

#[inline]
fn siftup<'a, T: 'a, C: Fn<(&'a T, &'a T), Ordering>>(v: &mut [T], start: uint, mut pos: uint, compare: &C) {
    unsafe {
        let new = replace(&mut v[pos], zeroed());

        while pos > start {
            let parent = (pos - 1) >> 1;
            // TODO: Get rid of transmute when high-rank lifetimes work
            if (*compare)(transmute(&new), transmute(v.unsafe_get(parent))) == Greater {
                let x = replace(&mut v[parent], zeroed());
                ptr::write(&mut v[pos], x);
                pos = parent;
                continue
            }
            break
        }
        ptr::write(&mut v[pos], new);
    }
}

#[inline]
fn siftdown_range<'a, T: 'a, C: Fn<(&'a T, &'a T), Ordering>>(v: &mut [T], mut pos: uint, end: uint, compare: &C) {
    unsafe {
        let start = pos;
        let new = replace(&mut v[pos], zeroed());

        let mut child = 2 * pos + 1;
        while child < end {
            let right = child + 1;
            if right < end && compare_idxs(v, child, right, compare) != Greater {
                child = right;
            }
            let x = replace(&mut v[child], zeroed());
            ptr::write(&mut v[pos], x);
            pos = child;
            child = 2 * pos + 1;
        }

        ptr::write(&mut v[pos], new);
        siftup(v, start, pos, compare);
    }
}

#[inline]
fn siftdown<'a, T: 'a, C: Fn<(&'a T, &'a T), Ordering>>(v: &mut [T], pos: uint, compare: &C) {
    let len = v.len();
    siftdown_range(v, pos, len, compare);
}

fn log2(x: uint) -> u32 {
    if x <= 1 { return 0; }
    let n = if size_of::<uint>() == 8 {
        (unsafe { ::core::intrinsics::ctlz64(x as u64) }) as u32
    } else {
        unsafe { ::core::intrinsics::ctlz32(x as u32) }
    };
    size_of::<uint>() as u32 * 8 - n
}

// TODO Replace this function when unboxed closures work properly
// Blocked on https://github.com/rust-lang/rust/issues/17661
#[inline(always)]
unsafe fn compare_idxs<'a, T: 'a, C: Fn<(&'a T, &'a T), Ordering>>(v: &[T], a: uint, b: uint, compare: &C) -> Ordering {
    let x = v.unsafe_get(a);
    let y = v.unsafe_get(b);
    (*compare)(transmute(x), transmute(y))
}

#[inline(always)]
fn compare_idxs_safe<'a, T: 'a, C: Fn<(&'a T, &'a T), Ordering>>(v: &[T], a: uint, b: uint, compare: &C) -> Ordering {
    unsafe { (*compare)(transmute(&v[a]), transmute(&v[b])) }
}

#[inline(always)]
unsafe fn unsafe_swap<T>(v: &mut[T], a: uint, b: uint) {
    ptr::swap(v.unsafe_mut(a) as *mut T, v.unsafe_mut(b) as *mut T);
}
<commit_msg>Improve performance by not special casing small center partitons<commit_after>use core::prelude::*;
use core::cmp::{min, max};
use core::mem::{size_of, zeroed, replace, swap, transmute};
use core::ptr;

/// The smallest number of elements that may be quicksorted.
/// Must be at least 9.
const MIN_QUICKSORT_ELEMS: uint = 10;

/// The maximum number of elements to be insertion sorted.
const MAX_INSERTION_SORT_ELEMS: uint = 42;

/// Controls the number of elements to be insertion sorted.
/// Higher values give more insertion sorted elements.
const INSERTION_SORT_FACTOR: uint = 450;

pub fn sort_by<'a, T: 'a, C: Fn<(&'a T, &'a T), Ordering>>(v: &mut [T], compare: &C) {
    if maybe_insertion_sort(v, compare) { return; }
    let heapsort_depth = (3 * log2(v.len())) / 2;
    do_introsort(v, compare, 0, heapsort_depth);
}

#[inline]
pub fn sort<T: Ord>(v: &mut [T]) {
    sort_by(v, &|&: a: &T, b| a.cmp(b));
}

fn introsort<'a, T: 'a, C: Fn<(&'a T, &'a T), Ordering>>(v: &mut [T], compare: &C, rec: u32, heapsort_depth: u32) {
    if maybe_insertion_sort(v, compare) { return; }
    do_introsort(v, compare, rec, heapsort_depth);
}

fn do_introsort<'a, T: 'a, C: Fn<(&'a T, &'a T), Ordering>>(v: &mut [T], compare: &C, rec: u32, heapsort_depth: u32) {
    // This works around some bugs with unboxed closures
    macro_rules! maybe_swap(
        ($v: expr, $a: expr, $b: expr, $compare: expr) => {
            if compare_idxs($v, *$a, *$b, $compare) == Greater {
                swap($a, $b);
            }
        }
    )

    if rec > heapsort_depth {
        heapsort(v, compare);
        return;
    }

    let n = v.len();

    // Pivot selection algorithm based on Java's DualPivotQuicksort.

    // Fast approximation of n / 7
    let seventh = (n / 8) + (n / 64) + 1;

    // Pick five element evenly spaced around the middle (inclusive) of the slice.
    let mut e3 = n / 2;
    let mut e2 = e3 - seventh;
    let mut e1 = e3 - 2*seventh;
    let mut e4 = e3 + seventh;
    let mut e5 = e3 + 2*seventh;

    // Sort them with a sorting network.
    unsafe {
        maybe_swap!(v, &mut e1, &mut e2, compare);
        maybe_swap!(v, &mut e4, &mut e5, compare);
        maybe_swap!(v, &mut e3, &mut e5, compare);
        maybe_swap!(v, &mut e3, &mut e4, compare);
        maybe_swap!(v, &mut e2, &mut e5, compare);
        maybe_swap!(v, &mut e1, &mut e4, compare);
        maybe_swap!(v, &mut e1, &mut e3, compare);
        maybe_swap!(v, &mut e2, &mut e4, compare);
        maybe_swap!(v, &mut e2, &mut e3, compare);
    }

    if unsafe { compare_idxs(v, e1, e2, compare) != Equal &&
                compare_idxs(v, e2, e3, compare) != Equal &&
                compare_idxs(v, e3, e4, compare) != Equal &&
                compare_idxs(v, e4, e5, compare) != Equal } {
        // No consecutive pivot candidates are the same, meaning there is some variaton.
        dual_pivot_sort(v, (e1, e2, e3, e4, e5), compare, rec, heapsort_depth);
    } else {
        // Two consecutive pivots candidates where the same.
        // There are probably many similar elements.
        single_pivot_sort(v, e3, compare, rec, heapsort_depth);
    }
}

fn maybe_insertion_sort<'a, T: 'a, C: Fn<(&'a T, &'a T), Ordering>>(v: &mut [T], compare: &C) -> bool {
    let n = v.len();
    if n <= 1 {
        return true;
    }

    let threshold = min(MAX_INSERTION_SORT_ELEMS,
                        max(MIN_QUICKSORT_ELEMS, INSERTION_SORT_FACTOR / size_of::<T>()));
    if n <= threshold {
        insertion_sort(v, compare);
        return true;
    }
    return false;
}

pub fn insertion_sort<'a, T: 'a, C: Fn<(&'a T, &'a T), Ordering>>(v: &mut [T], compare: &C) {
    let mut i = 1;
    let n = v.len();
    while i < n {
        let mut j = i;
        while j > 0 && unsafe { compare_idxs(v, j-1, j, compare) } == Greater {
            unsafe { unsafe_swap(v, j, j-1); }
            j -= 1;
        }
        i += 1;
    }
}

fn dual_pivot_sort<'a, T: 'a, C: Fn<(&'a T, &'a T), Ordering>>(v: &mut [T], pivots: (uint, uint, uint, uint, uint),
                                                               compare: &C, rec: u32, heapsort_depth: u32) {
    let (pmin, p1, _pmid, p2, pmax) = pivots;
    let n = v.len();

    let lp = 0;
    let rp = n - 1;

    v.swap(p1, lp);
    v.swap(p2, rp);

    let mut lesser = 1;
    let mut greater = n - 2;

    unsafe {
        // Skip elements that are already in the correct position
        while compare_idxs(v, lesser, lp, compare) == Less { lesser += 1; }
        while compare_idxs(v, greater, rp, compare) == Greater { greater -= 1; }

        let mut k = lesser;
        // XXX We make some unecessary swaps since we can't leave uninitialized values
        // in `v` in case `compare` unwinds.
        while k <= greater {
            if compare_idxs(v, k, lp, compare) == Less {
                unsafe_swap(v, k, lesser);
                lesser += 1;
            } else {
                let cmp = compare_idxs(v, k, rp, compare);
                if cmp == Greater || cmp == Equal {
                    while k < greater && compare_idxs(v, greater, rp, compare) == Greater {
                        greater -= 1;
                    }
                    unsafe_swap(v, k, greater);
                    greater -= 1;
                    if compare_idxs(v, k, lp, compare) == Less {
                        unsafe_swap(v, k, lesser);
                        lesser += 1;
                    }
                }
            }
            k += 1;
        }
    }

    lesser -= 1;
    greater += 1;

    // Swap back pivots
    unsafe {
        unsafe_swap(v, lp, lesser);
        unsafe_swap(v, rp, greater);
    }

    introsort(v[mut ..lesser], compare, rec + 1, heapsort_depth);
    introsort(v[mut greater+1..], compare, rec + 1, heapsort_depth);
    introsort(v[mut left..right], compare, rec + 1, heapsort_depth);
}

fn single_pivot_sort<'a, T: 'a, C: Fn<(&'a T, &'a T), Ordering>>(v: &mut [T], pivot: uint, compare: &C, rec: u32, heapsort_depth: u32) {
    let (l, r) = fat_partition(v, pivot, compare);
    let n = v.len();
    if l > 1 {
        introsort(v[mut ..l], compare, rec + 1, heapsort_depth);
    }
    if r > 1 {
        introsort(v[mut n - r..], compare, rec + 1, heapsort_depth);
    }
}

/// Partitions elements, using the element at `pivot` as pivot.
/// After partitioning, the array looks as following:
/// <<<<<==>>>
/// Return (number of < elements, number of > elements)
fn fat_partition<'a, T: 'a, C: Fn<(&'a T, &'a T), Ordering>>(v: &mut [T], pivot: uint, compare: &C) -> (uint, uint)  {
    let mut a = 0;
    let mut b = a;
    let mut c = v.len() - 1;
    let mut d = c;
    v.swap(0, pivot);
    loop {
        while b <= c {
            let r = compare_idxs_safe(v, b, 0, compare);
            if r == Greater { break; }
            if r == Equal {
                unsafe { unsafe_swap(v, a, b); }
                a += 1;
            }
            b += 1;
        }
        while c >= b {
            let r = compare_idxs_safe(v, c, 0, compare);
            if r == Less { break; }
            if r == Equal {
                unsafe { unsafe_swap(v, c, d); }
                d -= 1;
            }
            c -= 1;
        }
        if b > c { break; }
        unsafe { unsafe_swap(v, b, c); }
        b += 1;
        c -= 1;
    }

    let n = v.len();
    let l = min(a, b - a);
    unsafe { swap_many(v, 0, b - l, l); }
    let r = min(d - c, n - 1 - d);
    unsafe { swap_many(v, b, n - r, r); }

    return (b - a, d - c);
}

unsafe fn swap_many<T>(v: &mut [T], a: uint, b: uint, n: uint) {
    let mut i = 0;
    while i < n {
        unsafe_swap(v, a + i, b + i);
        i += 1;
    }
}

#[cold]
#[inline(never)]
pub fn heapsort<'a, T: 'a, C: Fn<(&'a T, &'a T), Ordering>>(v: &mut [T], compare: &C) {
    heapify(v, compare);
    let mut end = v.len();
    while end > 0 {
        end -= 1;
        v.swap(0, end);
        siftdown_range(v, 0, end, compare);
    }
}

#[inline]
fn heapify<'a, T: 'a, C: Fn<(&'a T, &'a T), Ordering>>(v: &mut [T], compare: &C) {
    let mut n = v.len() / 2;
    while n > 0 {
        n -= 1;
        siftdown(v, n, compare)
    }
}

#[inline]
fn siftup<'a, T: 'a, C: Fn<(&'a T, &'a T), Ordering>>(v: &mut [T], start: uint, mut pos: uint, compare: &C) {
    unsafe {
        let new = replace(&mut v[pos], zeroed());

        while pos > start {
            let parent = (pos - 1) >> 1;
            // TODO: Get rid of transmute when high-rank lifetimes work
            if (*compare)(transmute(&new), transmute(v.unsafe_get(parent))) == Greater {
                let x = replace(&mut v[parent], zeroed());
                ptr::write(&mut v[pos], x);
                pos = parent;
                continue
            }
            break
        }
        ptr::write(&mut v[pos], new);
    }
}

#[inline]
fn siftdown_range<'a, T: 'a, C: Fn<(&'a T, &'a T), Ordering>>(v: &mut [T], mut pos: uint, end: uint, compare: &C) {
    unsafe {
        let start = pos;
        let new = replace(&mut v[pos], zeroed());

        let mut child = 2 * pos + 1;
        while child < end {
            let right = child + 1;
            if right < end && compare_idxs(v, child, right, compare) != Greater {
                child = right;
            }
            let x = replace(&mut v[child], zeroed());
            ptr::write(&mut v[pos], x);
            pos = child;
            child = 2 * pos + 1;
        }

        ptr::write(&mut v[pos], new);
        siftup(v, start, pos, compare);
    }
}

#[inline]
fn siftdown<'a, T: 'a, C: Fn<(&'a T, &'a T), Ordering>>(v: &mut [T], pos: uint, compare: &C) {
    let len = v.len();
    siftdown_range(v, pos, len, compare);
}

fn log2(x: uint) -> u32 {
    if x <= 1 { return 0; }
    let n = if size_of::<uint>() == 8 {
        (unsafe { ::core::intrinsics::ctlz64(x as u64) }) as u32
    } else {
        unsafe { ::core::intrinsics::ctlz32(x as u32) }
    };
    size_of::<uint>() as u32 * 8 - n
}

// TODO Replace this function when unboxed closures work properly
// Blocked on https://github.com/rust-lang/rust/issues/17661
#[inline(always)]
unsafe fn compare_idxs<'a, T: 'a, C: Fn<(&'a T, &'a T), Ordering>>(v: &[T], a: uint, b: uint, compare: &C) -> Ordering {
    let x = v.unsafe_get(a);
    let y = v.unsafe_get(b);
    (*compare)(transmute(x), transmute(y))
}

#[inline(always)]
fn compare_idxs_safe<'a, T: 'a, C: Fn<(&'a T, &'a T), Ordering>>(v: &[T], a: uint, b: uint, compare: &C) -> Ordering {
    unsafe { (*compare)(transmute(&v[a]), transmute(&v[b])) }
}

#[inline(always)]
unsafe fn unsafe_swap<T>(v: &mut[T], a: uint, b: uint) {
    ptr::swap(v.unsafe_mut(a) as *mut T, v.unsafe_mut(b) as *mut T);
}
<|endoftext|>


<commit_before>use countminsketch::CountMinSketch;
use std::cmp::Ordering;
use std::collections::hash_map::Entry;
use std::collections::{BTreeSet, HashMap};
use std::fmt;
use std::hash::Hash;
use std::rc::Rc;

struct TreeEntry<T>
where
    T: Eq + Ord,
{
    obj: Rc<T>,
    n: usize,
}

impl<T> Clone for TreeEntry<T>
where
    T: Eq + Ord,
{
    fn clone(&self) -> Self {
        TreeEntry {
            obj: Rc::clone(&self.obj),
            n: self.n,
        }
    }
}

impl<T> PartialEq for TreeEntry<T>
where
    T: Eq + Ord,
{
    fn eq(&self, other: &TreeEntry<T>) -> bool {
        self.obj == other.obj
    }
}

impl<T> Eq for TreeEntry<T>
where
    T: Eq + Ord,
{
}

impl<T> PartialOrd for TreeEntry<T>
where
    T: Eq + Ord,
{
    fn partial_cmp(&self, other: &TreeEntry<T>) -> Option<Ordering> {
        match self.n.cmp(&other.n) {
            Ordering::Greater => Some(Ordering::Greater),
            Ordering::Less => Some(Ordering::Less),
            Ordering::Equal => Some(self.obj.cmp(&other.obj)),
        }
    }
}

impl<T> Ord for TreeEntry<T>
where
    T: Eq + Ord,
{
    fn cmp(&self, other: &TreeEntry<T>) -> Ordering {
        self.partial_cmp(other).unwrap()
    }
}

/// Top-K implementation.
///
/// This data structure keeps the `k` most frequent data points of a stream.
#[derive(Clone)]
pub struct TopK<T>
where
    T: Clone + Eq + Hash + Ord,
{
    cms: CountMinSketch,
    obj2count: HashMap<Rc<T>, usize>,
    tree: BTreeSet<TreeEntry<T>>,
    k: usize,
}

impl<T> TopK<T>
where
    T: Clone + Eq + Hash + Ord,
{
    /// Create new Top-K data structure.
    ///
    /// - `k`: number of elements to remember
    /// - `cms`: CountMinSketch that is used for guessing the frequency of elements not currently
    ///   hold. Refer to its documentation about parameter selection.
    ///
    /// Panics if `k == 0`.
    pub fn new(k: usize, cms: CountMinSketch) -> TopK<T> {
        assert!(k > 0);
        TopK {
            cms: cms,
            obj2count: HashMap::new(),
            tree: BTreeSet::new(),
            k: k,
        }
    }

    /// Number of data points to remember.
    pub fn k(&self) -> usize {
        return self.k;
    }

    /// Observe a data point.
    pub fn add(&mut self, obj: T) {
        // create Rc so we can use obj in multiple data structs
        let rc = Rc::new(obj);

        // always increase CountMinSketch counts
        self.cms.add(&rc);

        // check if entry is in top K
        let size = self.obj2count.len();
        let mut update_obj2count: Option<(usize, Rc<T>)> = None;
        match self.obj2count.entry(Rc::clone(&rc)) {
            Entry::Occupied(mut o) => {
                // it is => increase exact counter
                let mut n = o.get_mut();
                *n += 1;

                // update tree data
                let mut entry = TreeEntry {
                    obj: Rc::clone(&rc),
                    n: *n - 1,
                };
                self.tree.remove(&entry);
                entry.n += 1;
                self.tree.insert(entry);
            }
            Entry::Vacant(v) => {
                // it's not => check capicity
                if size < self.k {
                    // space left => add to top k
                    v.insert(1);
                    self.tree.insert(TreeEntry {
                        obj: Rc::clone(&rc),
                        n: 1,
                    });
                } else {
                    // not enough space => check if it would be a top k element
                    let count = self.cms.query_point(&rc);
                    let min: TreeEntry<T> = (*self.tree.iter().next().unwrap()).clone();
                    if count > min.n {
                        // => kick out minimal element of top k
                        self.tree.remove(&min);
                        self.tree.insert(TreeEntry {
                            obj: Rc::clone(&rc),
                            n: count,
                        });

                        // delay obj2count changes, because it is currently borrowed
                        update_obj2count = Some((count, min.obj));
                    }
                }
            }
        }

        // trick the borrow checker
        if let Some((count, obj)) = update_obj2count {
            self.obj2count.insert(rc, count);
            self.obj2count.remove(&obj);
        }
    }

    /// Iterates over collected top-k values.
    ///
    /// The result may contain less than `k` values if less than `k` unique data points where
    /// observed.
    pub fn iter<'a>(&'a self) -> impl 'a + Iterator<Item = T> {
        self.tree.iter().map(|x| (*x.obj).clone())
    }

    /// Check whether the sampler is empty (i.e. no data points observer so far)
    pub fn is_empty(&self) -> bool {
        self.obj2count.is_empty()
    }

    /// Clear sampler, so that it behaves like it never observed any data points.
    pub fn clear(&mut self) {
        self.cms.clear();
        self.tree.clear();
        self.obj2count.clear();
    }
}

impl<T> fmt::Debug for TopK<T>
where
    T: Clone + Eq + Hash + Ord,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "TopK {{ k: {} }}", self.k)
    }
}

impl<T> Extend<T> for TopK<T>
where
    T: Clone + Eq + Hash + Ord,
{
    fn extend<S: IntoIterator<Item = T>>(&mut self, iter: S) {
        for elem in iter {
            self.add(elem);
        }
    }
}

#[cfg(test)]
mod tests {
    use super::TopK;
    use countminsketch::CountMinSketch;

    #[test]
    fn getter() {
        let cms = CountMinSketch::with_params(10, 20);
        let tk: TopK<usize> = TopK::new(2, cms);

        assert_eq!(tk.k(), 2);
    }

    #[test]
    fn add_1() {
        let cms = CountMinSketch::with_params(10, 20);
        let mut tk = TopK::new(2, cms);

        tk.add(1);
        assert_eq!(tk.iter().collect::<Vec<u32>>(), vec![1]);
    }

    #[test]
    fn add_2_same() {
        let cms = CountMinSketch::with_params(10, 20);
        let mut tk = TopK::new(2, cms);

        tk.add(1);
        tk.add(1);
        assert_eq!(tk.iter().collect::<Vec<u32>>(), vec![1]);
    }

    #[test]
    fn add_2_different() {
        let cms = CountMinSketch::with_params(10, 20);
        let mut tk = TopK::new(2, cms);

        tk.add(1);
        tk.add(2);
        assert_eq!(tk.iter().collect::<Vec<u32>>(), vec![1, 2]);
    }

    #[test]
    fn add_n() {
        let cms = CountMinSketch::with_params(10, 20);
        let mut tk = TopK::new(2, cms);

        for i in 0..5 {
            tk.add(i);
        }
        for _ in 0..100 {
            tk.add(99);
        }
        for _ in 0..100 {
            tk.add(100);
        }
        for i in 0..5 {
            tk.add(i);
        }
        assert_eq!(tk.iter().collect::<Vec<u32>>(), vec![99, 100]);
    }

    #[test]
    fn is_empty() {
        let cms = CountMinSketch::with_params(10, 20);
        let mut tk = TopK::new(2, cms);
        assert_eq!(tk.is_empty(), true);

        tk.add(0);
        assert_eq!(tk.is_empty(), false);
    }

    #[test]
    fn clear() {
        let cms = CountMinSketch::with_params(10, 20);
        let mut tk = TopK::new(2, cms);
        tk.add(0);

        tk.clear();
        assert_eq!(tk.is_empty(), true);

        tk.add(1);
        assert_eq!(tk.iter().collect::<Vec<u32>>(), vec![1]);
    }

    #[test]
    fn clone() {
        let cms = CountMinSketch::with_params(10, 20);
        let mut tk1 = TopK::new(2, cms);
        tk1.add(0);

        let mut tk2 = tk1.clone();
        tk2.add(1);

        assert_eq!(tk1.iter().collect::<Vec<u32>>(), vec![0]);
        assert_eq!(tk2.iter().collect::<Vec<u32>>(), vec![0, 1]);
    }

    #[test]
    fn debug() {
        let cms = CountMinSketch::with_params(10, 20);
        let tk: TopK<usize> = TopK::new(2, cms);
        assert_eq!(format!("{:?}", tk), "TopK { k: 2 }");
    }

    #[test]
    fn extend() {
        let cms = CountMinSketch::with_params(10, 10);
        let mut tk = TopK::new(2, cms);

        tk.extend(vec![0, 1]);
        assert_eq!(tk.iter().collect::<Vec<u32>>(), vec![0, 1]);
    }
}
<commit_msg>topk: test asserts<commit_after>use countminsketch::CountMinSketch;
use std::cmp::Ordering;
use std::collections::hash_map::Entry;
use std::collections::{BTreeSet, HashMap};
use std::fmt;
use std::hash::Hash;
use std::rc::Rc;

struct TreeEntry<T>
where
    T: Eq + Ord,
{
    obj: Rc<T>,
    n: usize,
}

impl<T> Clone for TreeEntry<T>
where
    T: Eq + Ord,
{
    fn clone(&self) -> Self {
        TreeEntry {
            obj: Rc::clone(&self.obj),
            n: self.n,
        }
    }
}

impl<T> PartialEq for TreeEntry<T>
where
    T: Eq + Ord,
{
    fn eq(&self, other: &TreeEntry<T>) -> bool {
        self.obj == other.obj
    }
}

impl<T> Eq for TreeEntry<T>
where
    T: Eq + Ord,
{
}

impl<T> PartialOrd for TreeEntry<T>
where
    T: Eq + Ord,
{
    fn partial_cmp(&self, other: &TreeEntry<T>) -> Option<Ordering> {
        match self.n.cmp(&other.n) {
            Ordering::Greater => Some(Ordering::Greater),
            Ordering::Less => Some(Ordering::Less),
            Ordering::Equal => Some(self.obj.cmp(&other.obj)),
        }
    }
}

impl<T> Ord for TreeEntry<T>
where
    T: Eq + Ord,
{
    fn cmp(&self, other: &TreeEntry<T>) -> Ordering {
        self.partial_cmp(other).unwrap()
    }
}

/// Top-K implementation.
///
/// This data structure keeps the `k` most frequent data points of a stream.
#[derive(Clone)]
pub struct TopK<T>
where
    T: Clone + Eq + Hash + Ord,
{
    cms: CountMinSketch,
    obj2count: HashMap<Rc<T>, usize>,
    tree: BTreeSet<TreeEntry<T>>,
    k: usize,
}

impl<T> TopK<T>
where
    T: Clone + Eq + Hash + Ord,
{
    /// Create new Top-K data structure.
    ///
    /// - `k`: number of elements to remember
    /// - `cms`: CountMinSketch that is used for guessing the frequency of elements not currently
    ///   hold. Refer to its documentation about parameter selection.
    ///
    /// Panics if `k == 0`.
    pub fn new(k: usize, cms: CountMinSketch) -> TopK<T> {
        assert!(k > 0, "k must be greater than 0");

        TopK {
            cms: cms,
            obj2count: HashMap::new(),
            tree: BTreeSet::new(),
            k: k,
        }
    }

    /// Number of data points to remember.
    pub fn k(&self) -> usize {
        return self.k;
    }

    /// Observe a data point.
    pub fn add(&mut self, obj: T) {
        // create Rc so we can use obj in multiple data structs
        let rc = Rc::new(obj);

        // always increase CountMinSketch counts
        self.cms.add(&rc);

        // check if entry is in top K
        let size = self.obj2count.len();
        let mut update_obj2count: Option<(usize, Rc<T>)> = None;
        match self.obj2count.entry(Rc::clone(&rc)) {
            Entry::Occupied(mut o) => {
                // it is => increase exact counter
                let mut n = o.get_mut();
                *n += 1;

                // update tree data
                let mut entry = TreeEntry {
                    obj: Rc::clone(&rc),
                    n: *n - 1,
                };
                self.tree.remove(&entry);
                entry.n += 1;
                self.tree.insert(entry);
            }
            Entry::Vacant(v) => {
                // it's not => check capicity
                if size < self.k {
                    // space left => add to top k
                    v.insert(1);
                    self.tree.insert(TreeEntry {
                        obj: Rc::clone(&rc),
                        n: 1,
                    });
                } else {
                    // not enough space => check if it would be a top k element
                    let count = self.cms.query_point(&rc);
                    let min: TreeEntry<T> = (*self.tree.iter().next().unwrap()).clone();
                    if count > min.n {
                        // => kick out minimal element of top k
                        self.tree.remove(&min);
                        self.tree.insert(TreeEntry {
                            obj: Rc::clone(&rc),
                            n: count,
                        });

                        // delay obj2count changes, because it is currently borrowed
                        update_obj2count = Some((count, min.obj));
                    }
                }
            }
        }

        // trick the borrow checker
        if let Some((count, obj)) = update_obj2count {
            self.obj2count.insert(rc, count);
            self.obj2count.remove(&obj);
        }
    }

    /// Iterates over collected top-k values.
    ///
    /// The result may contain less than `k` values if less than `k` unique data points where
    /// observed.
    pub fn iter<'a>(&'a self) -> impl 'a + Iterator<Item = T> {
        self.tree.iter().map(|x| (*x.obj).clone())
    }

    /// Check whether the sampler is empty (i.e. no data points observer so far)
    pub fn is_empty(&self) -> bool {
        self.obj2count.is_empty()
    }

    /// Clear sampler, so that it behaves like it never observed any data points.
    pub fn clear(&mut self) {
        self.cms.clear();
        self.tree.clear();
        self.obj2count.clear();
    }
}

impl<T> fmt::Debug for TopK<T>
where
    T: Clone + Eq + Hash + Ord,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "TopK {{ k: {} }}", self.k)
    }
}

impl<T> Extend<T> for TopK<T>
where
    T: Clone + Eq + Hash + Ord,
{
    fn extend<S: IntoIterator<Item = T>>(&mut self, iter: S) {
        for elem in iter {
            self.add(elem);
        }
    }
}

#[cfg(test)]
mod tests {
    use super::TopK;
    use countminsketch::CountMinSketch;

    #[test]
    #[should_panic(expected = "k must be greater than 0")]
    fn new_panics_k0() {
        let cms = CountMinSketch::with_params(10, 20);
        TopK::<usize>::new(0, cms);
    }

    #[test]
    fn getter() {
        let cms = CountMinSketch::with_params(10, 20);
        let tk: TopK<usize> = TopK::new(2, cms);

        assert_eq!(tk.k(), 2);
    }

    #[test]
    fn add_1() {
        let cms = CountMinSketch::with_params(10, 20);
        let mut tk = TopK::new(2, cms);

        tk.add(1);
        assert_eq!(tk.iter().collect::<Vec<u32>>(), vec![1]);
    }

    #[test]
    fn add_2_same() {
        let cms = CountMinSketch::with_params(10, 20);
        let mut tk = TopK::new(2, cms);

        tk.add(1);
        tk.add(1);
        assert_eq!(tk.iter().collect::<Vec<u32>>(), vec![1]);
    }

    #[test]
    fn add_2_different() {
        let cms = CountMinSketch::with_params(10, 20);
        let mut tk = TopK::new(2, cms);

        tk.add(1);
        tk.add(2);
        assert_eq!(tk.iter().collect::<Vec<u32>>(), vec![1, 2]);
    }

    #[test]
    fn add_n() {
        let cms = CountMinSketch::with_params(10, 20);
        let mut tk = TopK::new(2, cms);

        for i in 0..5 {
            tk.add(i);
        }
        for _ in 0..100 {
            tk.add(99);
        }
        for _ in 0..100 {
            tk.add(100);
        }
        for i in 0..5 {
            tk.add(i);
        }
        assert_eq!(tk.iter().collect::<Vec<u32>>(), vec![99, 100]);
    }

    #[test]
    fn is_empty() {
        let cms = CountMinSketch::with_params(10, 20);
        let mut tk = TopK::new(2, cms);
        assert_eq!(tk.is_empty(), true);

        tk.add(0);
        assert_eq!(tk.is_empty(), false);
    }

    #[test]
    fn clear() {
        let cms = CountMinSketch::with_params(10, 20);
        let mut tk = TopK::new(2, cms);
        tk.add(0);

        tk.clear();
        assert_eq!(tk.is_empty(), true);

        tk.add(1);
        assert_eq!(tk.iter().collect::<Vec<u32>>(), vec![1]);
    }

    #[test]
    fn clone() {
        let cms = CountMinSketch::with_params(10, 20);
        let mut tk1 = TopK::new(2, cms);
        tk1.add(0);

        let mut tk2 = tk1.clone();
        tk2.add(1);

        assert_eq!(tk1.iter().collect::<Vec<u32>>(), vec![0]);
        assert_eq!(tk2.iter().collect::<Vec<u32>>(), vec![0, 1]);
    }

    #[test]
    fn debug() {
        let cms = CountMinSketch::with_params(10, 20);
        let tk: TopK<usize> = TopK::new(2, cms);
        assert_eq!(format!("{:?}", tk), "TopK { k: 2 }");
    }

    #[test]
    fn extend() {
        let cms = CountMinSketch::with_params(10, 10);
        let mut tk = TopK::new(2, cms);

        tk.extend(vec![0, 1]);
        assert_eq!(tk.iter().collect::<Vec<u32>>(), vec![0, 1]);
    }
}
<|endoftext|>


<commit_before>use std::thread;
use std::sync::{mpsc,Arc, Mutex};
use dispatcher::{self, DispatchType, Subscribe, SubscribeHandle, DispatchMessage, Broadcast, BroadcastHandle};
use ncurses::*;
use view_data::ViewData;
use message::Message;

pub struct View {
    max_x: i32,
    max_y: i32,
    messages: WINDOW,
    input: WINDOW,
    view_data: Option<ViewData>
}

impl View {
    pub fn new() -> View {
        initscr();

        let mut max_y = 0;
        let mut max_x = 0;
        getmaxyx(stdscr, &mut max_y, &mut max_x);

        let messages = init_messages(max_y, max_x);
        let input = init_input(max_y, max_x);

        View {
            max_x: max_x,
            max_y: max_y,
            messages: messages,
            input: input,
            view_data: None
        }
    }

    // Rather have ncurses call a callback
    // instead of a receiver to cut the dependency
    // but couldn't get it to work
    pub fn init(&mut self, on_input: Box<Fn(String)>, view_data_rx: mpsc::Receiver<ViewData>) {
        self.draw_prompt();
        let mut input = String::new();
        loop {
            match view_data_rx.try_recv() {
                Ok(view_data) => {
                    self.view_data = Some(view_data);
                    self.naive_redraw();
                    self.draw_prompt();
                }
                _ => ()
            }

            let ch = wgetch(self.input);
            if ch == ERR { continue };
            if ch != '\n' as i32 && ch != '\r' as i32 {
                // TODO This might send wrong keys
                unsafe { input.as_mut_vec().push(ch as u8); }
                mvwprintw(self.input, 1, 3, &input);
                wrefresh(self.input);
            } else {
                on_input(input);
                input = String::new();
                self.draw_prompt();
            }
        }
        // Doesn't work
        // mvwin(self.messages,1,1); // Padding for messages
    }

    pub fn print_message(&self, message: &Message) {
        let string = format!("{}", message) + "\n";
        wprintw(self.messages, &string);
    }

    pub fn print_debug(&self, string: &str) {
        let string = "DEBUG: ".to_string() + &string + "\n";
        wprintw(self.messages, &string);
        wrefresh(self.messages);
    }

    fn draw_prompt(&self) {
        wclear(self.input);
        let top = 0 as chtype;
        let bottom = ' ' as chtype;
        let empty = ' ' as chtype;
        wborder(self.input, empty,empty,top,bottom,empty,empty,empty,empty);
        mvwprintw(self.input, 1, 1, "> ");
        wmove(self.input, 1, 3); // Move physical cursor to prompt start
        wrefresh(self.input);
    }

    // Redraw whole messages screen for every message
    fn naive_redraw(&self) {
        if self.view_data.is_none() { return };

        wclear(self.messages);

        let view_data = self.view_data.as_ref().unwrap();
        for message in view_data.messages.iter() {
            self.print_message(message)
        }
        for debug in view_data.debug.iter() {
            self.print_debug(debug)
        }

        wrefresh(self.messages);
    }

}

impl Drop for View {
    fn drop(&mut self) {
        endwin();
    }
}

fn input_to_message(string: String) -> DispatchMessage {
    DispatchMessage {
        dispatch_type: DispatchType::UserInput,
        payload: string
    }
}

fn init_messages(max_y: i32, max_x: i32) -> WINDOW {
    let win = newwin(max_y - 2, max_x, 0, 0);
    let top = ' ' as chtype;
    let bottom = ' ' as chtype;
    let empty = ' ' as chtype;
    wborder(win, empty,empty,top,bottom,empty,empty,empty,empty);
    // box_(win, 0, 0);
    scrollok(win, true);
    wrefresh(win);
    win
}

fn init_input(max_y: i32, max_x: i32) -> WINDOW {
    let win = newwin(2, max_x, max_y - 2, 0);
    nodelay(win, true);
    // box_(win, 0, 0);
    wrefresh(win);
    win
}

<commit_msg>Show current channel name at prompt<commit_after>use std::thread;
use std::sync::{mpsc,Arc, Mutex};
use dispatcher::{self, DispatchType, Subscribe, SubscribeHandle, DispatchMessage, Broadcast, BroadcastHandle};
use ncurses::*;
use view_data::ViewData;
use message::Message;

pub struct View {
    max_x: i32,
    max_y: i32,
    messages: WINDOW,
    input: WINDOW,
    view_data: Option<ViewData>
}

impl View {
    pub fn new() -> View {
        initscr();

        let mut max_y = 0;
        let mut max_x = 0;
        getmaxyx(stdscr, &mut max_y, &mut max_x);

        let messages = init_messages(max_y, max_x);
        let input = init_input(max_y, max_x);

        View {
            max_x: max_x,
            max_y: max_y,
            messages: messages,
            input: input,
            view_data: None
        }
    }

    // Rather have ncurses call a callback
    // instead of a receiver to cut the dependency
    // but couldn't get it to work
    pub fn init(&mut self, on_input: Box<Fn(String)>, view_data_rx: mpsc::Receiver<ViewData>) {
        self.draw_prompt();
        let mut input = String::new();
        loop {
            match view_data_rx.try_recv() {
                Ok(view_data) => {
                    self.view_data = Some(view_data);
                    self.naive_redraw();
                    self.draw_prompt();
                }
                _ => ()
            }

            let ch = wgetch(self.input);
            if ch == ERR { continue };
            if ch != '\n' as i32 && ch != '\r' as i32 {
                // TODO This might send wrong keys
                unsafe { input.as_mut_vec().push(ch as u8); }
                mvwprintw(self.input, 1, (self.current_prompt().len() + 1) as i32, &input);
                wrefresh(self.input);
            } else {
                on_input(input);
                input = String::new();
                self.draw_prompt();
            }
        }
        // Doesn't work
        // mvwin(self.messages,1,1); // Padding for messages
    }

    pub fn print_message(&self, message: &Message) {
        let string = format!("{}", message) + "\n";
        wprintw(self.messages, &string);
    }

    pub fn print_debug(&self, string: &str) {
        let string = "DEBUG: ".to_string() + &string + "\n";
        wprintw(self.messages, &string);
        wrefresh(self.messages);
    }

    fn draw_prompt(&self) {
        wclear(self.input);
        let top = 0 as chtype;
        let bottom = ' ' as chtype;
        let empty = ' ' as chtype;
        wborder(self.input, empty,empty,top,bottom,empty,empty,empty,empty);
        let promptname: &str = &self.current_prompt();
        mvwprintw(self.input, 1, 1, promptname);
        wmove(self.input, 1, (promptname.len() + 1) as i32); // Move physical cursor to prompt start
        wrefresh(self.input);
    }

    fn current_prompt(&self) -> String {
        if self.view_data.is_none() { return "> ".to_string() }

        let name = &self.view_data.as_ref().unwrap().channel.name;
        format!("#{} > ", name)
    }

    // Naively redraws the whole UI by clearing all data
    fn naive_redraw(&self) {
        if self.view_data.is_none() { return };

        wclear(self.messages);

        // TODO extra debug iteration makes no sense
        let view_data = self.view_data.as_ref().unwrap();
        for message in view_data.messages.iter() {
            self.print_message(message)
        }
        for debug in view_data.debug.iter() {
            self.print_debug(debug)
        }

        wrefresh(self.messages);
    }

}

impl Drop for View {
    fn drop(&mut self) {
        endwin();
    }
}

fn input_to_message(string: String) -> DispatchMessage {
    DispatchMessage {
        dispatch_type: DispatchType::UserInput,
        payload: string
    }
}

fn init_messages(max_y: i32, max_x: i32) -> WINDOW {
    let win = newwin(max_y - 2, max_x, 0, 0);
    let top = ' ' as chtype;
    let bottom = ' ' as chtype;
    let empty = ' ' as chtype;
    wborder(win, empty,empty,top,bottom,empty,empty,empty,empty);
    // box_(win, 0, 0);
    scrollok(win, true);
    wrefresh(win);
    win
}

fn init_input(max_y: i32, max_x: i32) -> WINDOW {
    let win = newwin(2, max_x, max_y - 2, 0);
    nodelay(win, true);
    // box_(win, 0, 0);
    wrefresh(win);
    win
}

<|endoftext|>


<commit_before>struct WorkUnit {
    arg: int,
    callback: Sender<int>,
}

enum MessageToWorker {
    Work(WorkUnit),
    Halt,
}

struct WorkQueue {
    enqueue_work: Sender<MessageToWorker>,
    worker_count: int,
}

impl WorkQueue {
    pub fn create(worker_count: int) -> WorkQueue {
        use native;
        use std::comm::channel;

        let (want_work, worker_wants_work) = channel::<Sender<MessageToWorker>>();
        let (enqueue_work, have_new_job) = channel::<MessageToWorker>();

        for _ in range(0, worker_count) {
            // worker
            let want_work_copy = want_work.clone();
            native::task::spawn(proc() {
                let want_work = want_work_copy;
                loop {
                    let (reply_with_work, get_work_unit) = channel::<MessageToWorker>();
                    want_work.send(reply_with_work);
                    let work_unit = match get_work_unit.recv() {
                        Work(wu) => wu,
                        Halt     => return
                    };
                    let rv = work_unit.arg * 2;
                    work_unit.callback.send(rv);
                }
            });
        }

        // dispatcher
        native::task::spawn(proc() {
            let mut worker_count = worker_count;
            let have_new_job = have_new_job;
            let worker_wants_work = worker_wants_work;
            loop {
                let message_to_worker = have_new_job.recv();
                let worker = worker_wants_work.recv();
                match message_to_worker {
                    Halt => worker_count -= 1,
                    _    => {}
                }
                worker.send(message_to_worker);
                if worker_count == 0 {
                    return;
                }
            }
        });

        return WorkQueue{enqueue_work: enqueue_work, worker_count: worker_count};
    }

    pub fn execute(&self, arg: int) -> Receiver<int> {
        let (reply_with_rv, wait_for_rv) = channel::<int>();
        self.enqueue_work.send(Work(WorkUnit{arg: arg, callback: reply_with_rv}));
        return wait_for_rv;
    }
}

impl Drop for WorkQueue {
    fn drop(&mut self) {
        for _ in range(0, self.worker_count) {
            self.enqueue_work.send(Halt);
        }
    }
}

#[test]
fn test_queue() {
    let queue = WorkQueue::create(3);
    let mut promise_list: ~[Receiver<int>] = ~[];
    for c in range(0, 10) {
        let rv = queue.execute(c);
        promise_list.push(rv);
    }
    let return_list = promise_list.map(|promise| promise.recv());
    assert_eq!(return_list, ~[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]);
}
<commit_msg>rename variables, move imports to the top<commit_after>use native;
use std::comm::channel;

struct WorkUnit {
    arg: int,
    callback: Sender<int>,
}

enum MessageToWorker {
    Work(WorkUnit),
    Halt,
}

struct WorkQueue {
    dispatcher: Sender<MessageToWorker>,
    worker_count: int,
}

impl WorkQueue {
    pub fn create(worker_count: int) -> WorkQueue {
        let (want_work, idle_worker) = channel::<Sender<MessageToWorker>>();
        let (dispatcher, dispatcher_inbox) = channel::<MessageToWorker>();

        for _ in range(0, worker_count) {
            // worker
            let want_work_copy = want_work.clone();
            native::task::spawn(proc() {
                let want_work = want_work_copy;
                loop {
                    let (reply_with_work, get_work_unit) = channel::<MessageToWorker>();
                    want_work.send(reply_with_work);
                    let work_unit = match get_work_unit.recv() {
                        Work(wu) => wu,
                        Halt     => return
                    };
                    let rv = work_unit.arg * 2;
                    work_unit.callback.send(rv);
                }
            });
        }

        // dispatcher
        native::task::spawn(proc() {
            let mut worker_count = worker_count;
            let inbox = dispatcher_inbox;
            let idle_worker = idle_worker;
            loop {
                let message_to_worker = inbox.recv();
                let worker = idle_worker.recv();
                match message_to_worker {
                    Halt => worker_count -= 1,
                    _    => {}
                }
                worker.send(message_to_worker);
                if worker_count == 0 {
                    return;
                }
            }
        });

        return WorkQueue{dispatcher: dispatcher, worker_count: worker_count};
    }

    pub fn execute(&self, arg: int) -> Receiver<int> {
        let (reply_with_rv, wait_for_rv) = channel::<int>();
        self.dispatcher.send(Work(WorkUnit{arg: arg, callback: reply_with_rv}));
        return wait_for_rv;
    }
}

impl Drop for WorkQueue {
    fn drop(&mut self) {
        for _ in range(0, self.worker_count) {
            self.dispatcher.send(Halt);
        }
    }
}

#[test]
fn test_queue() {
    let queue = WorkQueue::create(3);
    let mut promise_list: ~[Receiver<int>] = ~[];
    for c in range(0, 10) {
        let rv = queue.execute(c);
        promise_list.push(rv);
    }
    let return_list = promise_list.map(|promise| promise.recv());
    assert_eq!(return_list, ~[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]);
}
<|endoftext|>


<commit_before>extern crate distance;
extern crate database;

use database::AthlDatabase;

fn main() {
    println!("Loading database, please wait...");
    let mut db = AthlDatabase::load("../../data/athletesTrainingSet.txt");
    // println!("{:?}", db);
    db.standarize();
    println!("Database ready!\n---------------------------------------------");
}
<commit_msg>Testing<commit_after>extern crate distance;
extern crate database;

use database::AthlDatabase;

fn main() {
    println!("Loading database, please wait...");
    let mut db = AthlDatabase::load("../../data/athletesTrainingSet.txt");
    db.standarize();
    // println!("{:?}", db);
    println!("Database ready!\n---------------------------------------------");
}
<|endoftext|>


<commit_before>// Copyright (C) 2020 Markus Ebner <info@ebner-markus.de>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

mod gifenc;

fn plugin_init(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
    gifenc::register(plugin)
}

gst::gst_plugin_define!(
    gifenc,
    env!("CARGO_PKG_DESCRIPTION"),
    plugin_init,
    concat!(env!("CARGO_PKG_VERSION"), "-", env!("COMMIT_ID")),
    "MIT/X11",
    env!("CARGO_PKG_NAME"),
    env!("CARGO_PKG_NAME"),
    env!("CARGO_PKG_REPOSITORY"),
    env!("BUILD_REL_DATE")
);
<commit_msg>gif: rename plugin to 'gif'<commit_after>// Copyright (C) 2020 Markus Ebner <info@ebner-markus.de>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

mod gifenc;

fn plugin_init(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
    gifenc::register(plugin)
}

gst::gst_plugin_define!(
    gif,
    env!("CARGO_PKG_DESCRIPTION"),
    plugin_init,
    concat!(env!("CARGO_PKG_VERSION"), "-", env!("COMMIT_ID")),
    "MIT/X11",
    env!("CARGO_PKG_NAME"),
    env!("CARGO_PKG_NAME"),
    env!("CARGO_PKG_REPOSITORY"),
    env!("BUILD_REL_DATE")
);
<|endoftext|>


<commit_before>use crate::{error::{Error,
                    Result},
            fs::find_command};
use std::{path::PathBuf,
          process::Command};

const DOCKER_CMD: &str = "docker";

pub fn command_path() -> Result<PathBuf> {
    find_command(DOCKER_CMD).ok_or_else(|| Error::DockerCommandNotFound(DOCKER_CMD))
}

/// Makes a best attempt to retrieve the appropriate image tag based on
/// https://hub.docker.com/_/microsoft-windows-servercore
/// Note that changes here should be mirrored in .buildkite/scripts/build_docker_image.ps1
pub fn default_base_tag_for_host() -> Result<&'static str> {
    if cfg!(windows) {
        let mut cmd = Command::new(command_path()?);
        cmd.arg("info").arg("--format='{{.Isolation}}'");
        let result = cmd.output().expect("Docker command failed to spawn");
        if String::from_utf8(result.stdout)?.trim() == "'hyperv'" {
            // hyperv isolation can build any version so we will default to 2016
            Ok("ltsc2016")
        } else {
            match os_info::get().version().version() {
                os_info::VersionType::Semantic(10, 0, 14393) => Ok("ltsc2016"),
                os_info::VersionType::Semantic(10, 0, 17134) => Ok("1803"),
                os_info::VersionType::Semantic(10, 0, 17763) => Ok("ltsc2019"),
                os_info::VersionType::Semantic(10, 0, 18362) => Ok("1903"),
                unsupported_version => {
                    Err(Error::UnsupportedDockerHostKernel(unsupported_version.to_string()))
                }
            }
        }
    } else {
        Ok("latest")
    }
}
<commit_msg>make the ltsc2019 docker image the default for studio and exporter if a hyper-v host supports it<commit_after>use crate::{error::{Error,
                    Result},
            fs::find_command};
use std::{path::PathBuf,
          process::Command};

const DOCKER_CMD: &str = "docker";

pub fn command_path() -> Result<PathBuf> {
    find_command(DOCKER_CMD).ok_or_else(|| Error::DockerCommandNotFound(DOCKER_CMD))
}

/// Makes a best attempt to retrieve the appropriate image tag based on
/// https://hub.docker.com/_/microsoft-windows-servercore
/// Note that changes here should be mirrored in .buildkite/scripts/build_docker_image.ps1
pub fn default_base_tag_for_host() -> Result<&'static str> {
    if cfg!(windows) {
        let mut cmd = Command::new(command_path()?);
        cmd.arg("info").arg("--format='{{.Isolation}}'");
        let result = cmd.output().expect("Docker command failed to spawn");
        if String::from_utf8(result.stdout)?.trim() == "'hyperv'" {
            // hyperv isolation can build any version so we will default to 2019
            // if the host supports it, otherwise 2016
            if os_info::get().version().version() >= &os_info::VersionType::Semantic(10, 0, 17763) {
                Ok("ltsc2019")
            } else {
                Ok("ltsc2016")
            }
        } else {
            match os_info::get().version().version() {
                os_info::VersionType::Semantic(10, 0, 14393) => Ok("ltsc2016"),
                os_info::VersionType::Semantic(10, 0, 17134) => Ok("1803"),
                os_info::VersionType::Semantic(10, 0, 17763) => Ok("ltsc2019"),
                os_info::VersionType::Semantic(10, 0, 18362) => Ok("1903"),
                unsupported_version => {
                    Err(Error::UnsupportedDockerHostKernel(unsupported_version.to_string()))
                }
            }
        }
    } else {
        Ok("latest")
    }
}
<|endoftext|>