<commit_before>/// Custom handlers service for responses.
use std::rc::Rc;

use actix_service::{Service, Transform};
use futures::future::{err, ok, Either, Future, FutureResult};
use futures::Poll;
use hashbrown::HashMap;

use crate::dev::{ServiceRequest, ServiceResponse};
use crate::error::{Error, Result};
use crate::http::StatusCode;

/// Error handler response
pub enum ErrorHandlerResponse<B> {
    /// New http response got generated
    Response(ServiceResponse<B>),
    /// Result is a future that resolves to a new http response
    Future(Box<Future<Item = ServiceResponse<B>, Error = Error>>),
}

type ErrorHandler<B> = Fn(ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>>;

/// `Middleware` for allowing custom handlers for responses.
///
/// You can use `ErrorHandlers::handler()` method  to register a custom error
/// handler for specific status code. You can modify existing response or
/// create completely new one.
///
/// ## Example
///
/// ```rust
/// use actix_web::middleware::errhandlers::{ErrorHandlers, ErrorHandlerResponse};
/// use actix_web::{web, http, dev, App, HttpRequest, HttpResponse, Result};
///
/// fn render_500<B>(mut res: dev::ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
///     res.response_mut()
///        .headers_mut()
///        .insert(http::header::CONTENT_TYPE, http::HeaderValue::from_static("Error"));
///     Ok(ErrorHandlerResponse::Response(res))
/// }
///
/// fn main() {
///     let app = App::new()
///         .middleware(
///             ErrorHandlers::new()
///                 .handler(http::StatusCode::INTERNAL_SERVER_ERROR, render_500),
///         )
///         .service(web::resource("/test")
///             .route(web::get().to(|| HttpResponse::Ok()))
///             .route(web::head().to(|| HttpResponse::MethodNotAllowed())
///         ));
/// }
/// ```
pub struct ErrorHandlers<B> {
    handlers: Rc<HashMap<StatusCode, Box<ErrorHandler<B>>>>,
}

impl<B> Default for ErrorHandlers<B> {
    fn default() -> Self {
        ErrorHandlers {
            handlers: Rc::new(HashMap::new()),
        }
    }
}

impl<B> ErrorHandlers<B> {
    /// Construct new `ErrorHandlers` instance
    pub fn new() -> Self {
        ErrorHandlers::default()
    }

    /// Register error handler for specified status code
    pub fn handler<F>(mut self, status: StatusCode, handler: F) -> Self
    where
        F: Fn(ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> + 'static,
    {
        Rc::get_mut(&mut self.handlers)
            .unwrap()
            .insert(status, Box::new(handler));
        self
    }
}

impl<S, P, B> Transform<S> for ErrorHandlers<B>
where
    S: Service<
        Request = ServiceRequest<P>,
        Response = ServiceResponse<B>,
        Error = Error,
    >,
    S::Future: 'static,
    S::Error: 'static,
    B: 'static,
{
    type Request = ServiceRequest<P>;
    type Response = ServiceResponse<B>;
    type Error = Error;
    type InitError = ();
    type Transform = ErrorHandlersMiddleware<S, B>;
    type Future = FutureResult<Self::Transform, Self::InitError>;

    fn new_transform(&self, service: S) -> Self::Future {
        ok(ErrorHandlersMiddleware {
            service,
            handlers: self.handlers.clone(),
        })
    }
}

#[doc(hidden)]
pub struct ErrorHandlersMiddleware<S, B> {
    service: S,
    handlers: Rc<HashMap<StatusCode, Box<ErrorHandler<B>>>>,
}

impl<S, P, B> Service for ErrorHandlersMiddleware<S, B>
where
    S: Service<
        Request = ServiceRequest<P>,
        Response = ServiceResponse<B>,
        Error = Error,
    >,
    S::Future: 'static,
    S::Error: 'static,
    B: 'static,
{
    type Request = ServiceRequest<P>;
    type Response = ServiceResponse<B>;
    type Error = Error;
    type Future = Box<Future<Item = Self::Response, Error = Self::Error>>;

    fn poll_ready(&mut self) -> Poll<(), Self::Error> {
        self.service.poll_ready()
    }

    fn call(&mut self, req: ServiceRequest<P>) -> Self::Future {
        let handlers = self.handlers.clone();

        Box::new(self.service.call(req).and_then(move |res| {
            if let Some(handler) = handlers.get(&res.status()) {
                match handler(res) {
                    Ok(ErrorHandlerResponse::Response(res)) => Either::A(ok(res)),
                    Ok(ErrorHandlerResponse::Future(fut)) => Either::B(fut),
                    Err(e) => Either::A(err(e)),
                }
            } else {
                Either::A(ok(res))
            }
        }))
    }
}

#[cfg(test)]
mod tests {
    use actix_service::FnService;
    use futures::future::ok;

    use super::*;
    use crate::http::{header::CONTENT_TYPE, HeaderValue, StatusCode};
    use crate::test::{self, TestRequest};
    use crate::HttpResponse;

    fn render_500<B>(mut res: ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
        res.response_mut()
            .headers_mut()
            .insert(CONTENT_TYPE, HeaderValue::from_static("0001"));
        Ok(ErrorHandlerResponse::Response(res))
    }

    #[test]
    fn test_handler() {
        let srv = FnService::new(|req: ServiceRequest<_>| {
            req.into_response(HttpResponse::InternalServerError().finish())
        });

        let mut mw = test::block_on(
            ErrorHandlers::new()
                .handler(StatusCode::INTERNAL_SERVER_ERROR, render_500)
                .new_transform(srv),
        )
        .unwrap();

        let resp = test::call_success(&mut mw, TestRequest::default().to_service());
        assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
    }

    fn render_500_async<B: 'static>(
        mut res: ServiceResponse<B>,
    ) -> Result<ErrorHandlerResponse<B>> {
        res.response_mut()
            .headers_mut()
            .insert(CONTENT_TYPE, HeaderValue::from_static("0001"));
        Ok(ErrorHandlerResponse::Future(Box::new(ok(res))))
    }

    #[test]
    fn test_handler_async() {
        let srv = FnService::new(|req: ServiceRequest<_>| {
            req.into_response(HttpResponse::InternalServerError().finish())
        });

        let mut mw = test::block_on(
            ErrorHandlers::new()
                .handler(StatusCode::INTERNAL_SERVER_ERROR, render_500_async)
                .new_transform(srv),
        )
        .unwrap();

        let resp = test::call_success(&mut mw, TestRequest::default().to_service());
        assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
    }
}
<commit_msg>fix errhandlers doc string<commit_after>//! Custom handlers service for responses.
use std::rc::Rc;

use actix_service::{Service, Transform};
use futures::future::{err, ok, Either, Future, FutureResult};
use futures::Poll;
use hashbrown::HashMap;

use crate::dev::{ServiceRequest, ServiceResponse};
use crate::error::{Error, Result};
use crate::http::StatusCode;

/// Error handler response
pub enum ErrorHandlerResponse<B> {
    /// New http response got generated
    Response(ServiceResponse<B>),
    /// Result is a future that resolves to a new http response
    Future(Box<Future<Item = ServiceResponse<B>, Error = Error>>),
}

type ErrorHandler<B> = Fn(ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>>;

/// `Middleware` for allowing custom handlers for responses.
///
/// You can use `ErrorHandlers::handler()` method  to register a custom error
/// handler for specific status code. You can modify existing response or
/// create completely new one.
///
/// ## Example
///
/// ```rust
/// use actix_web::middleware::errhandlers::{ErrorHandlers, ErrorHandlerResponse};
/// use actix_web::{web, http, dev, App, HttpRequest, HttpResponse, Result};
///
/// fn render_500<B>(mut res: dev::ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
///     res.response_mut()
///        .headers_mut()
///        .insert(http::header::CONTENT_TYPE, http::HeaderValue::from_static("Error"));
///     Ok(ErrorHandlerResponse::Response(res))
/// }
///
/// fn main() {
///     let app = App::new()
///         .middleware(
///             ErrorHandlers::new()
///                 .handler(http::StatusCode::INTERNAL_SERVER_ERROR, render_500),
///         )
///         .service(web::resource("/test")
///             .route(web::get().to(|| HttpResponse::Ok()))
///             .route(web::head().to(|| HttpResponse::MethodNotAllowed())
///         ));
/// }
/// ```
pub struct ErrorHandlers<B> {
    handlers: Rc<HashMap<StatusCode, Box<ErrorHandler<B>>>>,
}

impl<B> Default for ErrorHandlers<B> {
    fn default() -> Self {
        ErrorHandlers {
            handlers: Rc::new(HashMap::new()),
        }
    }
}

impl<B> ErrorHandlers<B> {
    /// Construct new `ErrorHandlers` instance
    pub fn new() -> Self {
        ErrorHandlers::default()
    }

    /// Register error handler for specified status code
    pub fn handler<F>(mut self, status: StatusCode, handler: F) -> Self
    where
        F: Fn(ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> + 'static,
    {
        Rc::get_mut(&mut self.handlers)
            .unwrap()
            .insert(status, Box::new(handler));
        self
    }
}

impl<S, P, B> Transform<S> for ErrorHandlers<B>
where
    S: Service<
        Request = ServiceRequest<P>,
        Response = ServiceResponse<B>,
        Error = Error,
    >,
    S::Future: 'static,
    S::Error: 'static,
    B: 'static,
{
    type Request = ServiceRequest<P>;
    type Response = ServiceResponse<B>;
    type Error = Error;
    type InitError = ();
    type Transform = ErrorHandlersMiddleware<S, B>;
    type Future = FutureResult<Self::Transform, Self::InitError>;

    fn new_transform(&self, service: S) -> Self::Future {
        ok(ErrorHandlersMiddleware {
            service,
            handlers: self.handlers.clone(),
        })
    }
}

#[doc(hidden)]
pub struct ErrorHandlersMiddleware<S, B> {
    service: S,
    handlers: Rc<HashMap<StatusCode, Box<ErrorHandler<B>>>>,
}

impl<S, P, B> Service for ErrorHandlersMiddleware<S, B>
where
    S: Service<
        Request = ServiceRequest<P>,
        Response = ServiceResponse<B>,
        Error = Error,
    >,
    S::Future: 'static,
    S::Error: 'static,
    B: 'static,
{
    type Request = ServiceRequest<P>;
    type Response = ServiceResponse<B>;
    type Error = Error;
    type Future = Box<Future<Item = Self::Response, Error = Self::Error>>;

    fn poll_ready(&mut self) -> Poll<(), Self::Error> {
        self.service.poll_ready()
    }

    fn call(&mut self, req: ServiceRequest<P>) -> Self::Future {
        let handlers = self.handlers.clone();

        Box::new(self.service.call(req).and_then(move |res| {
            if let Some(handler) = handlers.get(&res.status()) {
                match handler(res) {
                    Ok(ErrorHandlerResponse::Response(res)) => Either::A(ok(res)),
                    Ok(ErrorHandlerResponse::Future(fut)) => Either::B(fut),
                    Err(e) => Either::A(err(e)),
                }
            } else {
                Either::A(ok(res))
            }
        }))
    }
}

#[cfg(test)]
mod tests {
    use actix_service::FnService;
    use futures::future::ok;

    use super::*;
    use crate::http::{header::CONTENT_TYPE, HeaderValue, StatusCode};
    use crate::test::{self, TestRequest};
    use crate::HttpResponse;

    fn render_500<B>(mut res: ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
        res.response_mut()
            .headers_mut()
            .insert(CONTENT_TYPE, HeaderValue::from_static("0001"));
        Ok(ErrorHandlerResponse::Response(res))
    }

    #[test]
    fn test_handler() {
        let srv = FnService::new(|req: ServiceRequest<_>| {
            req.into_response(HttpResponse::InternalServerError().finish())
        });

        let mut mw = test::block_on(
            ErrorHandlers::new()
                .handler(StatusCode::INTERNAL_SERVER_ERROR, render_500)
                .new_transform(srv),
        )
        .unwrap();

        let resp = test::call_success(&mut mw, TestRequest::default().to_service());
        assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
    }

    fn render_500_async<B: 'static>(
        mut res: ServiceResponse<B>,
    ) -> Result<ErrorHandlerResponse<B>> {
        res.response_mut()
            .headers_mut()
            .insert(CONTENT_TYPE, HeaderValue::from_static("0001"));
        Ok(ErrorHandlerResponse::Future(Box::new(ok(res))))
    }

    #[test]
    fn test_handler_async() {
        let srv = FnService::new(|req: ServiceRequest<_>| {
            req.into_response(HttpResponse::InternalServerError().finish())
        });

        let mut mw = test::block_on(
            ErrorHandlers::new()
                .handler(StatusCode::INTERNAL_SERVER_ERROR, render_500_async)
                .new_transform(srv),
        )
        .unwrap();

        let resp = test::call_success(&mut mw, TestRequest::default().to_service());
        assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
    }
}
<|endoftext|>


<commit_before>#![feature(test)]
#[cfg(test)]

extern crate congalife;
extern crate test;

use congalife::Game;
use test::Bencher;

#[bench]
fn bench_new_game_64(b: &mut Bencher) {
    b.iter(|| Game::new(64, 0.2));
}

#[bench]
fn bench_new_game_128(b: &mut Bencher) {
    b.iter(|| Game::new(128, 0.2));
}

#[bench]
fn bench_new_game_512(b: &mut Bencher) {
    b.iter(|| Game::new(1024, 0.2));
}
<commit_msg>Fix typo and add larger new game benchmark<commit_after>#![feature(test)]
#[cfg(test)]

extern crate congalife;
extern crate test;

use congalife::Game;
use test::Bencher;

#[bench]
fn bench_new_game_64(b: &mut Bencher) {
    b.iter(|| Game::new(64, 0.2));
}

#[bench]
fn bench_new_game_128(b: &mut Bencher) {
    b.iter(|| Game::new(128, 0.2));
}

#[bench]
fn bench_new_game_512(b: &mut Bencher) {
    b.iter(|| Game::new(512, 0.2));
}

#[bench]
fn bench_new_game_1024(b: &mut Bencher) {
    b.iter(|| Game::new(1024, 0.2));
}
<|endoftext|>


<commit_before>use env_logger;
use std::borrow::Cow::{self, Borrowed, Owned};

use rustyline::completion::{Completer, FilenameCompleter, Pair};
use rustyline::config::OutputStreamType;
use rustyline::error::ReadlineError;
use rustyline::highlight::{Highlighter, MatchingBracketHighlighter};
use rustyline::hint::{Hinter, HistoryHinter};
use rustyline::{Cmd, CompletionType, Config, Context, EditMode, Editor, Helper, KeyPress};

struct MyHelper {
    completer: FilenameCompleter,
    highlighter: MatchingBracketHighlighter,
    hinter: HistoryHinter,
    colored_prompt: String,
}

impl Completer for MyHelper {
    type Candidate = Pair;

    fn complete(
        &self,
        line: &str,
        pos: usize,
        ctx: &Context<'_>,
    ) -> Result<(usize, Vec<Pair>), ReadlineError> {
        self.completer.complete(line, pos, ctx)
    }
}

impl Hinter for MyHelper {
    fn hint(&self, line: &str, pos: usize, ctx: &Context<'_>) -> Option<String> {
        self.hinter.hint(line, pos, ctx)
    }
}

impl Highlighter for MyHelper {
    fn highlight_prompt<'b, 's: 'b, 'p: 'b>(
        &'s self,
        prompt: &'p str,
        default: bool,
    ) -> Cow<'b, str> {
        if default {
            Borrowed(&self.colored_prompt)
        } else {
            Borrowed(prompt)
        }
    }

    fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> {
        Owned("\x1b[1m".to_owned() + hint + "\x1b[m")
    }

    fn highlight<'l>(&self, line: &'l str, pos: usize) -> Cow<'l, str> {
        self.highlighter.highlight(line, pos)
    }

    fn highlight_char(&self, line: &str, pos: usize) -> bool {
        self.highlighter.highlight_char(line, pos)
    }
}

impl Helper for MyHelper {}

fn main() {
    env_logger::init();
    let config = Config::builder()
        .history_ignore_space(true)
        .completion_type(CompletionType::List)
        .edit_mode(EditMode::Emacs)
        .output_stream(OutputStreamType::Stdout)
        .build();
    let h = MyHelper {
        completer: FilenameCompleter::new(),
        highlighter: MatchingBracketHighlighter::new(),
        hinter: HistoryHinter {},
        colored_prompt: "".to_owned(),
    };
    let mut rl = Editor::with_config(config);
    rl.set_helper(Some(h));
    rl.bind_sequence(KeyPress::Meta('N'), Cmd::HistorySearchForward);
    rl.bind_sequence(KeyPress::Meta('P'), Cmd::HistorySearchBackward);
    if rl.load_history("history.txt").is_err() {
        println!("No previous history.");
    }
    let mut count = 1;
    loop {
        let p = format!("{}> ", count);
        rl.helper_mut().unwrap().colored_prompt = format!("\x1b[1;32m{}\x1b[0m", p);
        let readline = rl.readline(&p);
        match readline {
            Ok(line) => {
                rl.add_history_entry(line.as_str());
                println!("Line: {}", line);
            }
            Err(ReadlineError::Interrupted) => {
                println!("CTRL-C");
                break;
            }
            Err(ReadlineError::Eof) => {
                println!("CTRL-D");
                break;
            }
            Err(err) => {
                println!("Error: {:?}", err);
                break;
            }
        }
        count += 1;
    }
    rl.save_history("history.txt").unwrap();
}
<commit_msg>Add a note to debug rustyline<commit_after>use env_logger;
use std::borrow::Cow::{self, Borrowed, Owned};

use rustyline::completion::{Completer, FilenameCompleter, Pair};
use rustyline::config::OutputStreamType;
use rustyline::error::ReadlineError;
use rustyline::highlight::{Highlighter, MatchingBracketHighlighter};
use rustyline::hint::{Hinter, HistoryHinter};
use rustyline::{Cmd, CompletionType, Config, Context, EditMode, Editor, Helper, KeyPress};

struct MyHelper {
    completer: FilenameCompleter,
    highlighter: MatchingBracketHighlighter,
    hinter: HistoryHinter,
    colored_prompt: String,
}

impl Completer for MyHelper {
    type Candidate = Pair;

    fn complete(
        &self,
        line: &str,
        pos: usize,
        ctx: &Context<'_>,
    ) -> Result<(usize, Vec<Pair>), ReadlineError> {
        self.completer.complete(line, pos, ctx)
    }
}

impl Hinter for MyHelper {
    fn hint(&self, line: &str, pos: usize, ctx: &Context<'_>) -> Option<String> {
        self.hinter.hint(line, pos, ctx)
    }
}

impl Highlighter for MyHelper {
    fn highlight_prompt<'b, 's: 'b, 'p: 'b>(
        &'s self,
        prompt: &'p str,
        default: bool,
    ) -> Cow<'b, str> {
        if default {
            Borrowed(&self.colored_prompt)
        } else {
            Borrowed(prompt)
        }
    }

    fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> {
        Owned("\x1b[1m".to_owned() + hint + "\x1b[m")
    }

    fn highlight<'l>(&self, line: &'l str, pos: usize) -> Cow<'l, str> {
        self.highlighter.highlight(line, pos)
    }

    fn highlight_char(&self, line: &str, pos: usize) -> bool {
        self.highlighter.highlight_char(line, pos)
    }
}

impl Helper for MyHelper {}

// To debug rustyline:
// RUST_LOG=rustyline=debug cargo run --example example 2> debug.log
fn main() {
    env_logger::init();
    let config = Config::builder()
        .history_ignore_space(true)
        .completion_type(CompletionType::List)
        .edit_mode(EditMode::Emacs)
        .output_stream(OutputStreamType::Stdout)
        .build();
    let h = MyHelper {
        completer: FilenameCompleter::new(),
        highlighter: MatchingBracketHighlighter::new(),
        hinter: HistoryHinter {},
        colored_prompt: "".to_owned(),
    };
    let mut rl = Editor::with_config(config);
    rl.set_helper(Some(h));
    rl.bind_sequence(KeyPress::Meta('N'), Cmd::HistorySearchForward);
    rl.bind_sequence(KeyPress::Meta('P'), Cmd::HistorySearchBackward);
    if rl.load_history("history.txt").is_err() {
        println!("No previous history.");
    }
    let mut count = 1;
    loop {
        let p = format!("{}> ", count);
        rl.helper_mut().unwrap().colored_prompt = format!("\x1b[1;32m{}\x1b[0m", p);
        let readline = rl.readline(&p);
        match readline {
            Ok(line) => {
                rl.add_history_entry(line.as_str());
                println!("Line: {}", line);
            }
            Err(ReadlineError::Interrupted) => {
                println!("CTRL-C");
                break;
            }
            Err(ReadlineError::Eof) => {
                println!("CTRL-D");
                break;
            }
            Err(err) => {
                println!("Error: {:?}", err);
                break;
            }
        }
        count += 1;
    }
    rl.save_history("history.txt").unwrap();
}
<|endoftext|>


<commit_before>pub mod markdown {
    use hoedown::renderer::Render;
    use hoedown::Buffer;
    use hoedown::Markdown;

    pub type LinkTitle  = String;
    pub type LinkURL    = String;

    pub struct Link {
        pub title: LinkTitle,
        pub url: LinkURL,
    }

    struct LinkExtractRenderer {
        links : Vec<Link>
    }

    impl LinkExtractRenderer {

        fn new() -> LinkExtractRenderer {
            LinkExtractRenderer {
                links: vec![],
            }
        }

        fn extract(self) -> Vec<Link> {
            self.links
        }

    }

    impl Render for LinkExtractRenderer {

        fn link(&mut self,
                output: &mut Buffer,
                content: &Buffer,
                link: &Buffer,
                title: &Buffer) -> bool {

            let l = String::from(link.to_str().unwrap_or("<<UTF8 Error>>"));
            let t = String::from(title.to_str().unwrap_or("<<UTF8 Error>>"));

            debug!("[Markdown] Push link: '{}' -> '{}'", t, l);
            self.links.push(Link {
                title:  t,
                url:    l,
            });
            true
        }

    }

    pub struct MarkdownParser {
        text: Markdown,
    }

    impl MarkdownParser {

        pub fn new(s: &String) -> MarkdownParser {
            MarkdownParser {
                text: Markdown::new(&s[..])
            }
        }

        pub fn links(&self) -> Vec<Link> {
            let mut renderer = LinkExtractRenderer::new();
            renderer.render(&self.text);
            renderer.extract()
        }

    }

}
<commit_msg>Add Markdown->HTML parsing<commit_after>pub mod markdown {
    use hoedown::renderer::Render;
    use hoedown::Buffer;
    use hoedown::Markdown;

    pub type LinkTitle  = String;
    pub type LinkURL    = String;

    pub struct Link {
        pub title: LinkTitle,
        pub url: LinkURL,
    }

    struct LinkExtractRenderer {
        links : Vec<Link>
    }

    impl LinkExtractRenderer {

        fn new() -> LinkExtractRenderer {
            LinkExtractRenderer {
                links: vec![],
            }
        }

        fn extract(self) -> Vec<Link> {
            self.links
        }

    }

    impl Render for LinkExtractRenderer {

        fn link(&mut self,
                output: &mut Buffer,
                content: &Buffer,
                link: &Buffer,
                title: &Buffer) -> bool {

            let l = String::from(link.to_str().unwrap_or("<<UTF8 Error>>"));
            let t = String::from(title.to_str().unwrap_or("<<UTF8 Error>>"));

            debug!("[Markdown] Push link: '{}' -> '{}'", t, l);
            self.links.push(Link {
                title:  t,
                url:    l,
            });
            true
        }

    }

    pub struct MarkdownParser {
        text: Markdown,
    }

    impl MarkdownParser {

        pub fn new(s: &String) -> MarkdownParser {
            MarkdownParser {
                text: Markdown::new(&s[..])
            }
        }

        pub fn links(&self) -> Vec<Link> {
            let mut renderer = LinkExtractRenderer::new();
            renderer.render(&self.text);
            renderer.extract()
        }

        pub fn to_html(self) -> String {
            use hoedown::renderer::html::Html;
            use hoedown::renderer::html;

            String::from(
                Html::new(html::Flags::empty(), 0)
                    .render(&self.text)
                    .to_str()
                    .unwrap_or("UTF8Error"))
        }

    }

}
<|endoftext|>


<commit_before>use decoders::Image;
use imageops::OpBuffer;

pub fn level_and_balance(img: &Image, buf: &mut OpBuffer) {
  // Calculate the blacklevels
  let mins = img.blacklevels.iter().map(|&x| x as f32).collect::<Vec<f32>>();
  let ranges = img.whitelevels.iter().enumerate().map(|(i, &x)| (x as f32) - mins[i]).collect::<Vec<f32>>();

  let coeffs = if img.wb_coeffs[0].is_nan() {
    img.neutralwb()
  } else {
    img.wb_coeffs
  };

  // Set green multiplier as 1.0
  let unity: f32 = coeffs[1];
  let mul = coeffs.iter().map(|x| if x.is_nan() { 1.0 } else { x / unity }).collect::<Vec<f32>>();

  buf.mutate_lines(&(|line: &mut [f32], _| {
    for pix in line.chunks_mut(4) {
      pix[0] = (((pix[0] - mins[0]) / ranges[0]) * mul[0]).min(1.0);
      pix[1] = (((pix[1] - mins[1]) / ranges[1]) * mul[1]).min(1.0);
      pix[2] = (((pix[2] - mins[2]) / ranges[2]) * mul[2]).min(1.0);
      pix[3] = (((pix[3] - mins[3]) / ranges[3]) * mul[3]).min(1.0);
    }
  }));
}
<commit_msg>level: ignore all non-normal float WB coeffs<commit_after>use decoders::Image;
use imageops::OpBuffer;

pub fn level_and_balance(img: &Image, buf: &mut OpBuffer) {
  // Calculate the blacklevels
  let mins = img.blacklevels.iter().map(|&x| x as f32).collect::<Vec<f32>>();
  let ranges = img.whitelevels.iter().enumerate().map(|(i, &x)| (x as f32) - mins[i]).collect::<Vec<f32>>();

  let coeffs = if img.wb_coeffs[0].is_nan() {
    img.neutralwb()
  } else {
    img.wb_coeffs
  };

  // Set green multiplier as 1.0
  let unity: f32 = coeffs[1];
  let mul = coeffs.iter().map(|x| if !x.is_normal() { 1.0 } else { x / unity }).collect::<Vec<f32>>();

  buf.mutate_lines(&(|line: &mut [f32], _| {
    for pix in line.chunks_mut(4) {
      pix[0] = (((pix[0] - mins[0]) / ranges[0]) * mul[0]).min(1.0);
      pix[1] = (((pix[1] - mins[1]) / ranges[1]) * mul[1]).min(1.0);
      pix[2] = (((pix[2] - mins[2]) / ranges[2]) * mul[2]).min(1.0);
      pix[3] = (((pix[3] - mins[3]) / ranges[3]) * mul[3]).min(1.0);
    }
  }));
}
<|endoftext|>


<commit_before>//! Implements the searching of the game tree -- iterative deepening,
//! aspiration windows, multi-PV.
//!
//! Iterative deepening works as follows: the program starts with a
//! one ply search, then increments the search depth and does another
//! search. This process is repeated until the time allocated for the
//! search is exhausted or the maximum search depth is reached. In
//! case of an unfinished search, the program can always fall back to
//! the move selected in the last iteration of the search.
//!
//! Aspiration windows are a way to reduce the search space in the
//! search. The way it works is that we get the value from the last
//! search iteration, calculate a window around it, and use this as
//! alpha-beta bounds for the next search. Because the window is
//! narrower, more beta cutoffs are achieved, and the search takes a
//! shorter time. The drawback is that if the true score is outside
//! this window, then a costly re-search must be made. But then most
//! probably the re-search will be much faster, because many positions
//! will be remembered from the transposition table.
//!
//! In multi-PV mode the engine calculates and sends to the GUI
//! several principal variations (PV), each one starting with a
//! different first move. This mode makes the search slower, but it is
//! very useful for chess analysis.

pub mod alpha_beta;
pub mod threading;

use std::cmp::{min, max};
use std::time::Duration;
use std::thread;
use std::sync::{Arc, Mutex, Condvar};
use std::sync::mpsc::{channel, Sender, Receiver, TryRecvError};
use basetypes::*;
use moves::*;
use tt::*;
use position::{Position, START_POSITION_FEN};
use self::threading::*;

/// The maximum search depth in half-moves.
pub const MAX_DEPTH: u8 = 63; // Should be less than 127.

/// Parameters describing a new search.
#[derive(Clone)]
pub struct SearchParams {
    /// A number identifying the new search.
    pub search_id: usize,

    /// The root position for the new search.
    pub position: Position,

    /// The requested search depth.
    pub depth: u8,

    /// The lower bound for the new search.
    pub lower_bound: Value,

    /// The upper bound for the new search.
    pub upper_bound: Value,

    /// The evaluation of the root position so far, or `VALUE_UNKNOWN`
    /// if not available.
    pub value: Value,

    /// Restricts the analysis of the root position to the supplied
    /// list of moves only. No restrictions if the supplied list is
    /// empty.
    pub searchmoves: Vec<Move>,

    /// Specifies how many best lines of play to calculate. (The first
    /// move in each line will be different.)
    pub variation_count: usize,
}

/// A progress report from a search.
#[derive(Clone)]
pub struct Report {
    /// The ID assigned to search.
    pub search_id: usize,

    /// The number of positions searched so far.
    pub searched_nodes: NodeCount,

    /// The search depth completed so far.
    pub depth: u8,

    /// The evaluation of the root position so far, or `VALUE_UNKNOWN`
    /// if not available.
    pub value: Value,

    /// The best moves found so far (sorted by descending strength),
    /// or an empty list if not available.
    pub best_moves: Vec<Move>,

    /// `true` if the search is done, `false` otherwise.
    pub done: bool,
}

/// The `SearchExecutor` trait is used to execute consecutive searches
/// in different starting positions.
pub trait SearchExecutor {
    /// Creates a new instance.
    fn new(tt: Arc<Tt>) -> Self;

    /// Starts a new search.
    ///
    /// After calling `start_search`, `try_recv_report` must be called
    /// periodically until the returned report indicates that the
    /// search is done. A new search must not be started until the
    /// previous search is done.
    fn start_search(&mut self, params: SearchParams);

    /// Attempts to return a search progress report without blocking.
    fn try_recv_report(&mut self) -> Result<Report, TryRecvError>;

    /// Waits until a search progress report is available, timing out
    /// after a specified duration or earlier.
    fn wait_report(&self, duration: Duration);

    /// Requests the termination of the current search.
    ///
    /// After calling `terminate`, `try_recv_report` must continue to
    /// be called periodically until the returned report indicates
    /// that the search is done.
    fn terminate_search(&mut self);
}

/// Executes alpha-beta searches.
///
/// `SimpleSearcher::new` will spawn a separate thread to do the
/// computational heavy lifting.
struct SimpleSearcher {
    thread_join_handle: Option<thread::JoinHandle<()>>,
    thread_commands: Sender<Command>,
    thread_reports: Receiver<Report>,
    has_reports_condition: Arc<(Mutex<bool>, Condvar)>,
}

impl SearchExecutor for SimpleSearcher {
    fn new(tt: Arc<Tt>) -> SimpleSearcher {
        let (commands_tx, commands_rx) = channel();
        let (reports_tx, reports_rx) = channel();
        let has_reports_condition = Arc::new((Mutex::new(false), Condvar::new()));
        SimpleSearcher {
            thread_commands: commands_tx,
            thread_reports: reports_rx,
            has_reports_condition: has_reports_condition.clone(),
            thread_join_handle: Some(thread::spawn(move || {
                serve_simple(tt, commands_rx, reports_tx, has_reports_condition);
            })),
        }
    }

    #[allow(unused_variables)]
    fn start_search(&mut self, params: SearchParams) {
        debug_assert!(params.depth <= MAX_DEPTH);
        debug_assert!(params.lower_bound < params.upper_bound);
        debug_assert!(params.lower_bound != VALUE_UNKNOWN);
        debug_assert!(params.searchmoves.is_empty());
        debug_assert_eq!(params.variation_count, 1);
        self.thread_commands.send(Command::Start(params)).unwrap();
    }

    fn try_recv_report(&mut self) -> Result<Report, TryRecvError> {
        let result = self.thread_reports.try_recv();
        if result.is_err() {
            *self.has_reports_condition.0.lock().unwrap() = false;
        }
        result
    }

    fn wait_report(&self, duration: Duration) {
        let &(ref has_reports, ref condition) = &*self.has_reports_condition;
        let has_reports = has_reports.lock().unwrap();
        if !*has_reports {
            condition.wait_timeout(has_reports, duration).unwrap();
        }
    }

    fn terminate_search(&mut self) {
        self.thread_commands.send(Command::Terminate).unwrap();
    }
}

impl Drop for SimpleSearcher {
    fn drop(&mut self) {
        self.thread_commands.send(Command::Exit).unwrap();
        self.thread_join_handle.take().unwrap().join().unwrap();
    }
}

/// Executes multi-PV searches.
///
/// `MultipvSearcher::new` will spawn a separate thread to do the
/// computational heavy lifting.
pub struct MultipvSearcher;

/// Executes multi-PV searches with aspiration windows.
///
/// `AspirationSearcher::new` will spawn a separate thread to do the
/// computational heavy lifting.
pub struct AspirationSearcher {
    params: SearchParams,

    /// `true` if the current search has been terminated.
    search_is_terminated: bool,

    /// The number of positions analyzed during previous failed searches.
    previously_searched_nodes: NodeCount,

    /// The evaluation of the root position so far.
    value: Value,

    /// The aspiration window will be widened by this value if the
    /// search fails. (We use `isize` to avoid overflows.)
    delta: isize,

    /// The lower bound of the aspiration window.
    alpha: Value,

    /// The upper bound of the aspiration window.
    beta: Value,

    /// The real work will be handed over to `SimpleSearcher`.
    searcher: SimpleSearcher, // TODO: should be `MultipvSearcher`
}

impl AspirationSearcher {
    /// A helper method. It tells `self.searcher` to run a new search.
    fn start_aspirated_search(&mut self) {
        self.searcher.start_search(SearchParams {
            search_id: 0,
            lower_bound: self.alpha,
            upper_bound: self.beta,
            value: self.value,
            searchmoves: vec![], // TODO: should be `self.searchmoves.clone(),`
            variation_count: 1, // TODO: should be  `self.variation_count,`
            ..self.params.clone()
        });
    }

    /// A helper method. It multiplies `self.delta` by a constant.
    fn increase_delta(&mut self) {
        self.delta += 3 * self.delta / 8;
        if self.delta > 1500 {
            self.delta = 1_000_000;
        }
    }

    /// A helper method. It widens the aspiration window if necessary.
    fn widen_aspiration_window(&mut self) -> bool {
        let SearchParams { lower_bound, upper_bound, .. } = self.params;
        if lower_bound < self.alpha && lower_bound < self.value && self.value <= self.alpha {
            // Set smaller `self.alpha`.
            self.alpha = max(self.value as isize - self.delta, lower_bound as isize) as Value;
            self.increase_delta();
            return true;
        } else if self.beta < upper_bound && self.beta <= self.value && self.value < upper_bound {
            // Set bigger `self.beta`.
            self.beta = min(self.value as isize + self.delta, upper_bound as isize) as Value;
            self.increase_delta();
            return true;
        }
        false
    }
}

impl SearchExecutor for AspirationSearcher {
    fn new(tt: Arc<Tt>) -> AspirationSearcher {
        AspirationSearcher {
            params: SearchParams {
                search_id: 0,
                position: Position::from_fen(START_POSITION_FEN).ok().unwrap(),
                depth: 0,
                lower_bound: VALUE_MIN,
                upper_bound: VALUE_MAX,
                value: VALUE_UNKNOWN,
                searchmoves: vec![],
                variation_count: 1,
            },
            search_is_terminated: false,
            previously_searched_nodes: 0,
            value: VALUE_UNKNOWN,
            delta: 0,
            alpha: VALUE_MIN,
            beta: VALUE_MAX,
            searcher: SimpleSearcher::new(tt),
        }
    }

    fn start_search(&mut self, params: SearchParams) {
        debug_assert!(params.depth <= MAX_DEPTH);
        debug_assert!(params.lower_bound < params.upper_bound);
        debug_assert!(params.lower_bound != VALUE_UNKNOWN);
        self.params = params;
        self.search_is_terminated = false;
        self.previously_searched_nodes = 0;
        self.value = self.params.value;

        // The half-width of the initial aspiration window.
        self.delta = 17; // TODO: make this `16`?

        // Set the initial aspiration window (`self.alpha`, `self.beta`).
        let SearchParams { value, lower_bound, upper_bound, .. } = self.params;
        let (a, b) = if value == VALUE_UNKNOWN || value < lower_bound || value > upper_bound {
            (lower_bound, upper_bound)
        } else {
            let v = value as isize;
            (max(v - self.delta, lower_bound as isize) as Value,
             min(v + self.delta, upper_bound as isize) as Value)
        };
        self.alpha = a;
        self.beta = b;

        self.start_aspirated_search();
    }

    fn try_recv_report(&mut self) -> Result<Report, TryRecvError> {
        let Report { searched_nodes, depth, value, best_moves, done, .. } =
            try!(self.searcher.try_recv_report());
        self.value = value;
        let searched_nodes = self.previously_searched_nodes + searched_nodes;
        let depth = if done && !self.search_is_terminated {
            self.previously_searched_nodes = searched_nodes;
            if self.widen_aspiration_window() {
                // Start a re-search.
                self.start_aspirated_search();
                return Err(TryRecvError::Empty);
            }
            depth
        } else {
            0
        };

        return Ok(Report {
            search_id: self.params.search_id,
            searched_nodes: searched_nodes,
            depth: depth,
            value: self.value,
            best_moves: best_moves,
            done: done,
        });
    }

    fn wait_report(&self, duration: Duration) {
        self.searcher.wait_report(duration);
    }

    fn terminate_search(&mut self) {
        self.search_is_terminated = true;
        self.searcher.terminate_search();
    }
}

/// Executes multi-PV searches with aspiration windows and iterative
/// deepening.
///
/// `DeepeningSearcher::new` will spawn a separate thread to do the
/// computational heavy lifting.
pub struct DeepeningSearcher {
    params: SearchParams,

    /// `true` if the current search has been terminated.
    search_is_terminated: bool,

    /// The number of positions analyzed during previous (shallower)
    /// searches.
    previously_searched_nodes: NodeCount,

    /// The evaluation of the root position so far.
    value: Value,

    /// The depth of the currently executing search.
    depth: u8,

    /// The real work will be handed over to `AspirationSearcher`.
    searcher: AspirationSearcher,
}

impl DeepeningSearcher {
    /// A helper method. It tells `self.searcher` to run a new search.
    fn start_deeper_search(&mut self) {
        self.depth += 1;
        let value = if self.depth < 5 {
            VALUE_UNKNOWN
        } else {
            self.value
        };
        self.searcher.start_search(SearchParams {
            search_id: 0,
            depth: self.depth,
            value: value,
            ..self.params.clone()
        });
    }
}

impl SearchExecutor for DeepeningSearcher {
    fn new(tt: Arc<Tt>) -> DeepeningSearcher {
        DeepeningSearcher {
            params: SearchParams {
                search_id: 0,
                position: Position::from_fen(START_POSITION_FEN).ok().unwrap(),
                depth: 0,
                lower_bound: VALUE_MIN,
                upper_bound: VALUE_MAX,
                value: VALUE_UNKNOWN,
                searchmoves: vec![],
                variation_count: 1,
            },
            search_is_terminated: false,
            previously_searched_nodes: 0,
            value: VALUE_UNKNOWN,
            depth: 0,
            searcher: AspirationSearcher::new(tt),
        }
    }

    fn start_search(&mut self, params: SearchParams) {
        debug_assert!(params.depth <= MAX_DEPTH);
        debug_assert!(params.lower_bound < params.upper_bound);
        debug_assert!(params.lower_bound != VALUE_UNKNOWN);
        self.params = params;
        self.search_is_terminated = false;
        self.previously_searched_nodes = 0;
        self.value = self.params.value;
        self.depth = 0;

        self.start_deeper_search();
    }

    fn try_recv_report(&mut self) -> Result<Report, TryRecvError> {
        let Report { searched_nodes, depth, value, best_moves, done, .. } =
            try!(self.searcher.try_recv_report());
        if value != VALUE_UNKNOWN {
            self.value = value;
        }
        let searched_nodes = self.previously_searched_nodes + searched_nodes;
        let depth = if done && !self.search_is_terminated {
            debug_assert_eq!(depth, self.depth);
            self.previously_searched_nodes = searched_nodes;
            if depth < self.params.depth {
                self.start_deeper_search();
                return Err(TryRecvError::Empty);
            }
            depth
        } else {
            self.depth - 1
        };

        return Ok(Report {
            search_id: self.params.search_id,
            searched_nodes: searched_nodes,
            depth: depth,
            value: self.value,
            best_moves: best_moves,
            done: done,
        });
    }

    fn wait_report(&self, duration: Duration) {
        self.searcher.wait_report(duration);
    }

    fn terminate_search(&mut self) {
        self.search_is_terminated = true;
        self.searcher.terminate_search();
    }
}
<commit_msg>beautify<commit_after>//! Implements the searching of the game tree -- iterative deepening,
//! aspiration windows, multi-PV.
//!
//! Iterative deepening works as follows: the program starts with a
//! one ply search, then increments the search depth and does another
//! search. This process is repeated until the time allocated for the
//! search is exhausted or the maximum search depth is reached. In
//! case of an unfinished search, the program can always fall back to
//! the move selected in the last iteration of the search.
//!
//! Aspiration windows are a way to reduce the search space in the
//! search. The way it works is that we get the value from the last
//! search iteration, calculate a window around it, and use this as
//! alpha-beta bounds for the next search. Because the window is
//! narrower, more beta cutoffs are achieved, and the search takes a
//! shorter time. The drawback is that if the true score is outside
//! this window, then a costly re-search must be made. But then most
//! probably the re-search will be much faster, because many positions
//! will be remembered from the transposition table.
//!
//! In multi-PV mode the engine calculates and sends to the GUI
//! several principal variations (PV), each one starting with a
//! different first move. This mode makes the search slower, but it is
//! very useful for chess analysis.

pub mod alpha_beta;
pub mod threading;

use std::cmp::{min, max};
use std::time::Duration;
use std::thread;
use std::sync::{Arc, Mutex, Condvar};
use std::sync::mpsc::{channel, Sender, Receiver, TryRecvError};
use basetypes::*;
use moves::*;
use tt::*;
use position::{Position, START_POSITION_FEN};
use self::threading::*;

/// The maximum search depth in half-moves.
pub const MAX_DEPTH: u8 = 63; // Should be less than 127.

/// Parameters describing a new search.
#[derive(Clone)]
pub struct SearchParams {
    /// A number identifying the new search.
    pub search_id: usize,

    /// The root position for the new search.
    pub position: Position,

    /// The requested search depth.
    pub depth: u8,

    /// The lower bound for the new search.
    pub lower_bound: Value,

    /// The upper bound for the new search.
    pub upper_bound: Value,

    /// The evaluation of the root position so far, or `VALUE_UNKNOWN`
    /// if not available.
    pub value: Value,

    /// Restricts the analysis of the root position to the supplied
    /// list of moves only. No restrictions if the supplied list is
    /// empty.
    pub searchmoves: Vec<Move>,

    /// Specifies how many best lines of play to calculate. (The first
    /// move in each line will be different.)
    pub variation_count: usize,
}

/// A progress report from a search.
#[derive(Clone)]
pub struct Report {
    /// The ID assigned to search.
    pub search_id: usize,

    /// The number of positions searched so far.
    pub searched_nodes: NodeCount,

    /// The search depth completed so far.
    pub depth: u8,

    /// The evaluation of the root position so far, or `VALUE_UNKNOWN`
    /// if not available.
    pub value: Value,

    /// The best moves found so far (sorted by descending strength),
    /// or an empty list if not available.
    pub best_moves: Vec<Move>,

    /// `true` if the search is done, `false` otherwise.
    pub done: bool,
}

/// The `SearchExecutor` trait is used to execute consecutive searches
/// in different starting positions.
pub trait SearchExecutor {
    /// Creates a new instance.
    fn new(tt: Arc<Tt>) -> Self;

    /// Starts a new search.
    ///
    /// After calling `start_search`, `try_recv_report` must be called
    /// periodically until the returned report indicates that the
    /// search is done. A new search must not be started until the
    /// previous search is done.
    fn start_search(&mut self, params: SearchParams);

    /// Attempts to return a search progress report without blocking.
    fn try_recv_report(&mut self) -> Result<Report, TryRecvError>;

    /// Waits until a search progress report is available, timing out
    /// after a specified duration or earlier.
    fn wait_report(&self, duration: Duration);

    /// Requests the termination of the current search.
    ///
    /// After calling `terminate`, `try_recv_report` must continue to
    /// be called periodically until the returned report indicates
    /// that the search is done.
    fn terminate_search(&mut self);
}

/// Executes alpha-beta searches.
///
/// `SimpleSearcher::new` will spawn a separate thread to do the
/// computational heavy lifting.
struct SimpleSearcher {
    thread_join_handle: Option<thread::JoinHandle<()>>,
    thread_commands: Sender<Command>,
    thread_reports: Receiver<Report>,
    has_reports_condition: Arc<(Mutex<bool>, Condvar)>,
}

impl SearchExecutor for SimpleSearcher {
    fn new(tt: Arc<Tt>) -> SimpleSearcher {
        let (commands_tx, commands_rx) = channel();
        let (reports_tx, reports_rx) = channel();
        let has_reports_condition = Arc::new((Mutex::new(false), Condvar::new()));
        SimpleSearcher {
            thread_commands: commands_tx,
            thread_reports: reports_rx,
            has_reports_condition: has_reports_condition.clone(),
            thread_join_handle: Some(thread::spawn(move || {
                serve_simple(tt, commands_rx, reports_tx, has_reports_condition);
            })),
        }
    }

    #[allow(unused_variables)]
    fn start_search(&mut self, params: SearchParams) {
        debug_assert!(params.depth <= MAX_DEPTH);
        debug_assert!(params.lower_bound < params.upper_bound);
        debug_assert!(params.lower_bound != VALUE_UNKNOWN);
        debug_assert!(params.searchmoves.is_empty());
        debug_assert_eq!(params.variation_count, 1);
        self.thread_commands.send(Command::Start(params)).unwrap();
    }

    fn try_recv_report(&mut self) -> Result<Report, TryRecvError> {
        let result = self.thread_reports.try_recv();
        if result.is_err() {
            *self.has_reports_condition.0.lock().unwrap() = false;
        }
        result
    }

    fn wait_report(&self, duration: Duration) {
        let &(ref has_reports, ref condition) = &*self.has_reports_condition;
        let has_reports = has_reports.lock().unwrap();
        if !*has_reports {
            condition.wait_timeout(has_reports, duration).unwrap();
        }
    }

    fn terminate_search(&mut self) {
        self.thread_commands.send(Command::Terminate).unwrap();
    }
}

impl Drop for SimpleSearcher {
    fn drop(&mut self) {
        self.thread_commands.send(Command::Exit).unwrap();
        self.thread_join_handle.take().unwrap().join().unwrap();
    }
}

/// Executes multi-PV searches.
///
/// `MultipvSearcher::new` will spawn a separate thread to do the
/// computational heavy lifting.
pub struct MultipvSearcher;

/// Executes multi-PV searches with aspiration windows.
///
/// `AspirationSearcher::new` will spawn a separate thread to do the
/// computational heavy lifting.
pub struct AspirationSearcher {
    params: SearchParams,

    /// `true` if the current search has been terminated.
    search_is_terminated: bool,

    /// The number of positions analyzed during previous failed searches.
    previously_searched_nodes: NodeCount,

    /// The evaluation of the root position so far.
    value: Value,

    /// The aspiration window will be widened by this value if the
    /// search fails. (We use `isize` to avoid overflows.)
    delta: isize,

    /// The lower bound of the aspiration window.
    alpha: Value,

    /// The upper bound of the aspiration window.
    beta: Value,

    /// The real work will be handed over to `SimpleSearcher`.
    searcher: SimpleSearcher, // TODO: should be `MultipvSearcher`
}

impl AspirationSearcher {
    /// A helper method. It tells `self.searcher` to run a new search.
    fn start_aspirated_search(&mut self) {
        self.searcher.start_search(SearchParams {
            search_id: 0,
            lower_bound: self.alpha,
            upper_bound: self.beta,
            value: self.value,
            searchmoves: vec![], // TODO: should be `self.searchmoves.clone(),`
            variation_count: 1, // TODO: should be  `self.variation_count,`
            ..self.params.clone()
        });
    }

    /// A helper method. It multiplies `self.delta` by a constant.
    fn increase_delta(&mut self) {
        self.delta += 3 * self.delta / 8;
        if self.delta > 1500 {
            self.delta = 1_000_000;
        }
    }

    /// A helper method. It widens the aspiration window if necessary.
    fn widen_aspiration_window(&mut self) -> bool {
        let SearchParams { lower_bound, upper_bound, .. } = self.params;
        if lower_bound < self.alpha && lower_bound < self.value && self.value <= self.alpha {
            // Set smaller `self.alpha`.
            self.alpha = max(self.value as isize - self.delta, lower_bound as isize) as Value;
            self.increase_delta();
            return true;
        } else if self.beta < upper_bound && self.beta <= self.value && self.value < upper_bound {
            // Set bigger `self.beta`.
            self.beta = min(self.value as isize + self.delta, upper_bound as isize) as Value;
            self.increase_delta();
            return true;
        }
        false
    }
}

impl SearchExecutor for AspirationSearcher {
    fn new(tt: Arc<Tt>) -> AspirationSearcher {
        AspirationSearcher {
            params: SearchParams {
                search_id: 0,
                position: Position::from_fen(START_POSITION_FEN).ok().unwrap(),
                depth: 0,
                lower_bound: VALUE_MIN,
                upper_bound: VALUE_MAX,
                value: VALUE_UNKNOWN,
                searchmoves: vec![],
                variation_count: 1,
            },
            search_is_terminated: false,
            previously_searched_nodes: 0,
            value: VALUE_UNKNOWN,
            delta: 0,
            alpha: VALUE_MIN,
            beta: VALUE_MAX,
            searcher: SimpleSearcher::new(tt),
        }
    }

    fn start_search(&mut self, params: SearchParams) {
        debug_assert!(params.depth <= MAX_DEPTH);
        debug_assert!(params.lower_bound < params.upper_bound);
        debug_assert!(params.lower_bound != VALUE_UNKNOWN);
        self.params = params;
        self.search_is_terminated = false;
        self.previously_searched_nodes = 0;
        self.value = self.params.value;

        // The half-width of the initial aspiration window.
        self.delta = 17; // TODO: make this `16`?

        // Set the initial aspiration window (`self.alpha`, `self.beta`).
        let SearchParams { value, lower_bound, upper_bound, .. } = self.params;
        let (a, b) = if value == VALUE_UNKNOWN || value < lower_bound || value > upper_bound {
            (lower_bound, upper_bound)
        } else {
            let v = value as isize;
            (max(v - self.delta, lower_bound as isize) as Value,
             min(v + self.delta, upper_bound as isize) as Value)
        };
        self.alpha = a;
        self.beta = b;

        self.start_aspirated_search();
    }

    fn try_recv_report(&mut self) -> Result<Report, TryRecvError> {
        let Report { searched_nodes, depth, value, best_moves, done, .. } =
            try!(self.searcher.try_recv_report());
        self.value = value;
        let searched_nodes = self.previously_searched_nodes + searched_nodes;
        let depth = if done && !self.search_is_terminated {
            self.previously_searched_nodes = searched_nodes;
            if self.widen_aspiration_window() {
                // Start a re-search.
                self.start_aspirated_search();
                return Err(TryRecvError::Empty);
            }
            depth
        } else {
            0
        };

        return Ok(Report {
            search_id: self.params.search_id,
            searched_nodes: searched_nodes,
            depth: depth,
            value: self.value,
            best_moves: best_moves,
            done: done,
        });
    }

    fn wait_report(&self, duration: Duration) {
        self.searcher.wait_report(duration);
    }

    fn terminate_search(&mut self) {
        self.search_is_terminated = true;
        self.searcher.terminate_search();
    }
}

/// Executes multi-PV searches with aspiration windows and iterative
/// deepening.
///
/// `DeepeningSearcher::new` will spawn a separate thread to do the
/// computational heavy lifting.
pub struct DeepeningSearcher {
    params: SearchParams,

    /// `true` if the current search has been terminated.
    search_is_terminated: bool,

    /// The number of positions analyzed during previous (shallower)
    /// searches.
    previously_searched_nodes: NodeCount,

    /// The evaluation of the root position so far.
    value: Value,

    /// The depth of the currently executing search.
    depth: u8,

    /// The real work will be handed over to `AspirationSearcher`.
    searcher: AspirationSearcher,
}

impl DeepeningSearcher {
    /// A helper method. It tells `self.searcher` to run a new search.
    fn start_deeper_search(&mut self) {
        self.depth += 1;
        let value = if self.depth < 5 {
            VALUE_UNKNOWN
        } else {
            self.value
        };
        self.searcher.start_search(SearchParams {
            search_id: 0,
            depth: self.depth,
            value: value,
            ..self.params.clone()
        });
    }
}

impl SearchExecutor for DeepeningSearcher {
    fn new(tt: Arc<Tt>) -> DeepeningSearcher {
        DeepeningSearcher {
            params: SearchParams {
                search_id: 0,
                position: Position::from_fen(START_POSITION_FEN).ok().unwrap(),
                depth: 0,
                lower_bound: VALUE_MIN,
                upper_bound: VALUE_MAX,
                value: VALUE_UNKNOWN,
                searchmoves: vec![],
                variation_count: 1,
            },
            search_is_terminated: false,
            previously_searched_nodes: 0,
            value: VALUE_UNKNOWN,
            depth: 0,
            searcher: AspirationSearcher::new(tt),
        }
    }

    fn start_search(&mut self, params: SearchParams) {
        debug_assert!(params.depth <= MAX_DEPTH);
        debug_assert!(params.lower_bound < params.upper_bound);
        debug_assert!(params.lower_bound != VALUE_UNKNOWN);
        self.params = params;
        self.search_is_terminated = false;
        self.previously_searched_nodes = 0;
        self.value = self.params.value;
        self.depth = 0;

        self.start_deeper_search();
    }

    fn try_recv_report(&mut self) -> Result<Report, TryRecvError> {
        let Report { searched_nodes, depth, value, best_moves, done, .. } =
            try!(self.searcher.try_recv_report());
        if value != VALUE_UNKNOWN {
            self.value = value;
        }
        let searched_nodes = self.previously_searched_nodes + searched_nodes;
        let depth = if done && !self.search_is_terminated {
            debug_assert_eq!(depth, self.depth);
            self.previously_searched_nodes = searched_nodes;
            if self.depth < self.params.depth {
                self.start_deeper_search();
                return Err(TryRecvError::Empty);
            }
            self.depth
        } else {
            self.depth - 1
        };

        return Ok(Report {
            search_id: self.params.search_id,
            searched_nodes: searched_nodes,
            depth: depth,
            value: self.value,
            best_moves: best_moves,
            done: done,
        });
    }

    fn wait_report(&self, duration: Duration) {
        self.searcher.wait_report(duration);
    }

    fn terminate_search(&mut self) {
        self.search_is_terminated = true;
        self.searcher.terminate_search();
    }
}
<|endoftext|>


<commit_before>//! The SpaceAPI server struct.

use std::net::{SocketAddr, ToSocketAddrs};
use std::sync::{Arc, Mutex};
use std::time::Duration;
use std::fmt::Debug;

use r2d2;
use r2d2_redis::RedisConnectionManager;
use iron::Iron;
use router::Router;
use redis::IntoConnectionInfo;

mod handlers;

use ::api;

use ::sensors;
use ::modifiers;
use ::errors::SpaceapiServerError;
use ::types::RedisPool;

/// A Space API server instance.
///
/// You can create a new instance using the ``new`` constructor method by
/// passing it the host, the port, the ``Status`` object and a redis connection info object.
///
/// The ``SpaceapiServer`` includes a web server through
/// [Hyper](http://hyper.rs/hyper/hyper/server/index.html). Simply call the ``serve`` method.
pub struct SpaceapiServer {
    socket_addr: SocketAddr,
    status: api::Status,
    redis_pool: RedisPool,
    sensor_specs: sensors::SafeSensorSpecs,
    status_modifiers: Vec<Box<modifiers::StatusModifier>>,
}

impl SpaceapiServer {

    pub fn new<U, T>(socket_addr: U,
                     status: api::Status,
                     redis_connection_info: T,
                     status_modifiers: Vec<Box<modifiers::StatusModifier>>)
        -> Result<SpaceapiServer, SpaceapiServerError>
        where U: ToSocketAddrs, T: IntoConnectionInfo + Debug {
            // Get socket addr
            let mut socket_addr_iter = try!(socket_addr.to_socket_addrs());
            let socket_addr = try!(socket_addr_iter.next()
                                   .ok_or(SpaceapiServerError::Message("Invalid socket address".into())));

            // Log some useful debug information
            debug!("Redis connection info: {:?}", &redis_connection_info);

            // Create redis pool
            let redis_config = r2d2::Config::builder()
                // Provide up to 6 connections in connection pool
                .pool_size(6)
                // At least 1 connection must be active
                .min_idle(Some(2))
                // Initialize connection pool lazily. This allows the SpaceAPI
                // server to work even without a database connection.
                .initialization_fail_fast(false)
                // Try to get a connection for max 1 second
                .connection_timeout(Duration::from_secs(1))
                // Don't log errors directly.
                // They can get quite verbose, and we're already catching and
                // logging the corresponding results anyways.
                .error_handler(Box::new(r2d2::NopErrorHandler))
                .build();
            let redis_manager = try!(RedisConnectionManager::new(redis_connection_info));
            let pool = try!(r2d2::Pool::new(redis_config, redis_manager));

            Ok(SpaceapiServer {
                socket_addr: socket_addr,
                status: status,
                redis_pool: pool,
                sensor_specs: Arc::new(Mutex::new(vec![])),
                status_modifiers: status_modifiers,
            })
        }

    /// Create and return a Router instance.
    fn route(self) -> Router {
        let mut router = Router::new();

        router.get("/", handlers::ReadHandler::new(
            self.status.clone(), self.redis_pool.clone(),
            self.sensor_specs.clone(), self.status_modifiers), "root");

        router.put("/sensors/:sensor/", handlers::UpdateHandler::new(
            self.redis_pool.clone(), self.sensor_specs.clone()), "sensors");

        router
    }

    /// Start a HTTP server listening on ``self.host:self.port``.
    ///
    /// The call returns an `HttpResult<Listening>` object, see
    /// http://ironframework.io/doc/hyper/server/struct.Listening.html
    /// for more information.
    pub fn serve(self) -> ::HttpResult<::Listening> {
        // Launch server process
        let socket_addr = self.socket_addr;
        let router = self.route();
        println!("Starting HTTP server on http://{}...", socket_addr);
        Iron::new(router).http(socket_addr)
    }

    /// Register a new sensor.
    ///
    /// The first argument is a ``api::SensorTemplate`` instance containing all static data.
    /// The second argument specifies how to get the actual sensor value from Redis.
    /// And the third argument specifies the data type of the value.
    pub fn register_sensor(&mut self, template: Box<api::SensorTemplate>, data_key: String) {
        let sensor_specs_ref = self.sensor_specs.clone();
        sensor_specs_ref.lock().unwrap().push(
            sensors::SensorSpec { template: template, data_key: data_key}
        );
    }

}
<commit_msg>Remove documentation for non-existing parameter (#69)<commit_after>//! The SpaceAPI server struct.

use std::net::{SocketAddr, ToSocketAddrs};
use std::sync::{Arc, Mutex};
use std::time::Duration;
use std::fmt::Debug;

use r2d2;
use r2d2_redis::RedisConnectionManager;
use iron::Iron;
use router::Router;
use redis::IntoConnectionInfo;

mod handlers;

use ::api;

use ::sensors;
use ::modifiers;
use ::errors::SpaceapiServerError;
use ::types::RedisPool;

/// A Space API server instance.
///
/// You can create a new instance using the ``new`` constructor method by
/// passing it the host, the port, the ``Status`` object and a redis connection info object.
///
/// The ``SpaceapiServer`` includes a web server through
/// [Hyper](http://hyper.rs/hyper/hyper/server/index.html). Simply call the ``serve`` method.
pub struct SpaceapiServer {
    socket_addr: SocketAddr,
    status: api::Status,
    redis_pool: RedisPool,
    sensor_specs: sensors::SafeSensorSpecs,
    status_modifiers: Vec<Box<modifiers::StatusModifier>>,
}

impl SpaceapiServer {

    pub fn new<U, T>(socket_addr: U,
                     status: api::Status,
                     redis_connection_info: T,
                     status_modifiers: Vec<Box<modifiers::StatusModifier>>)
        -> Result<SpaceapiServer, SpaceapiServerError>
        where U: ToSocketAddrs, T: IntoConnectionInfo + Debug {
            // Get socket addr
            let mut socket_addr_iter = try!(socket_addr.to_socket_addrs());
            let socket_addr = try!(socket_addr_iter.next()
                                   .ok_or(SpaceapiServerError::Message("Invalid socket address".into())));

            // Log some useful debug information
            debug!("Redis connection info: {:?}", &redis_connection_info);

            // Create redis pool
            let redis_config = r2d2::Config::builder()
                // Provide up to 6 connections in connection pool
                .pool_size(6)
                // At least 1 connection must be active
                .min_idle(Some(2))
                // Initialize connection pool lazily. This allows the SpaceAPI
                // server to work even without a database connection.
                .initialization_fail_fast(false)
                // Try to get a connection for max 1 second
                .connection_timeout(Duration::from_secs(1))
                // Don't log errors directly.
                // They can get quite verbose, and we're already catching and
                // logging the corresponding results anyways.
                .error_handler(Box::new(r2d2::NopErrorHandler))
                .build();
            let redis_manager = try!(RedisConnectionManager::new(redis_connection_info));
            let pool = try!(r2d2::Pool::new(redis_config, redis_manager));

            Ok(SpaceapiServer {
                socket_addr: socket_addr,
                status: status,
                redis_pool: pool,
                sensor_specs: Arc::new(Mutex::new(vec![])),
                status_modifiers: status_modifiers,
            })
        }

    /// Create and return a Router instance.
    fn route(self) -> Router {
        let mut router = Router::new();

        router.get("/", handlers::ReadHandler::new(
            self.status.clone(), self.redis_pool.clone(),
            self.sensor_specs.clone(), self.status_modifiers), "root");

        router.put("/sensors/:sensor/", handlers::UpdateHandler::new(
            self.redis_pool.clone(), self.sensor_specs.clone()), "sensors");

        router
    }

    /// Start a HTTP server listening on ``self.host:self.port``.
    ///
    /// The call returns an `HttpResult<Listening>` object, see
    /// http://ironframework.io/doc/hyper/server/struct.Listening.html
    /// for more information.
    pub fn serve(self) -> ::HttpResult<::Listening> {
        // Launch server process
        let socket_addr = self.socket_addr;
        let router = self.route();
        println!("Starting HTTP server on http://{}...", socket_addr);
        Iron::new(router).http(socket_addr)
    }

    /// Register a new sensor.
    ///
    /// The first argument is a ``api::SensorTemplate`` instance containing all static data.
    /// The second argument specifies how to get the actual sensor value from Redis.
    pub fn register_sensor(&mut self, template: Box<api::SensorTemplate>, data_key: String) {
        let sensor_specs_ref = self.sensor_specs.clone();
        sensor_specs_ref.lock().unwrap().push(
            sensors::SensorSpec { template: template, data_key: data_key}
        );
    }

}
<|endoftext|>


<commit_before>//! Draw rectangle

use internal;
use triangulation;
use Graphics;
use Color;
use DrawState;
use math::Matrix2d;

pub use math::margin_rectangle as margin;

/// Use x, y, half-width, half-height
pub fn centered(rect: internal::Rectangle) -> internal::Rectangle {
    [rect[0] - rect[2], rect[1] - rect[3], 2.0 * rect[2], 2.0 * rect[3]]
}

/// Use centered square
pub fn centered_square(
    x: internal::Scalar,
    y: internal::Scalar,
    radius: internal::Scalar
) -> internal::Rectangle {
    [x - radius, y - radius, 2.0 * radius, 2.0 * radius]
}

/// Use square with x, y in upper left corner
pub fn square(
    x: internal::Scalar,
    y: internal::Scalar,
    size: internal::Scalar
) -> internal::Rectangle {
    [x, y, size, size]
}

/// The shape of the rectangle
#[derive(Copy, Clone)]
pub enum Shape {
    /// Square corners
    Square,
    /// Round corners
    Round(internal::Radius),
    /// Bevel corners
    Bevel(internal::Radius),
}

/// The border of the rectangle
#[derive(Copy, Clone)]
pub struct Border {
    /// The color of the border
    pub color: internal::Color,
    /// The radius of the border
    pub radius: internal::Radius,
}

/// Maybe border property
#[derive(Copy, Clone)]
pub struct MaybeBorder(pub Option<Border>);

/// A filled rectangle
#[derive(Copy, Clone)]
pub struct Rectangle {
    /// The rectangle color
    pub color: internal::Color,
    /// The roundness of the rectangle
    pub shape: Shape,
    /// The border
    pub border: Option<Border>,
}

impl Rectangle {
    /// Creates a new rectangle.
    pub fn new(color: internal::Color) -> Rectangle {
        Rectangle {
            color: color,
            shape: Shape::Square,
            border: None,
        }
    }

    /// Creates a new round rectangle.
    pub fn new_round(
        color: internal::Color,
        round_radius: internal::Radius
    ) -> Rectangle {
        Rectangle {
            color: color,
            shape: Shape::Round(round_radius),
            border: None
        }
    }

    /// Creates a new rectangle border.
    pub fn new_border(
        color: internal::Color,
        radius: internal::Radius
    ) -> Rectangle {
        Rectangle {
            color: [0.0; 4],
            shape: Shape::Square,
            border: Some(Border {
                    color: color,
                    radius: radius
                })
        }
    }

    /// Creates a new round rectangle border.
    pub fn new_round_border(
        color: internal::Color,
        round_radius: internal::Radius,
        border_radius: internal::Radius
    ) -> Rectangle {
        Rectangle {
            color: [0.0; 4],
            shape: Shape::Round(round_radius),
            border: Some(Border {
                    color: color,
                    radius: border_radius
                })
        }
    }

    /// Sets color.
    pub fn color(mut self, value: internal::Color) -> Self {
        self.color = value;
        self
    }

    /// Sets shape.
    pub fn shape(mut self, value: Shape) -> Self {
        self.shape = value;
        self
    }

    /// Sets border.
    pub fn border(mut self, value: Border) -> Self {
        self.border = Some(value);
        self
    }

    /// Sets optional border.
    pub fn maybe_border(mut self, value: Option<Border>) -> Self {
        self.border = value;
        self
    }

    /// Draws the rectangle
    pub fn draw<G>(
        &self,
        rectangle: internal::Rectangle,
        draw_state: &DrawState,
        transform: Matrix2d,
        g: &mut G
    )
        where G: Graphics
    {
        if self.color[3] != 0.0 {
            match self.shape {
                Shape::Square => {
                    g.tri_list(
                        draw_state,
                        &self.color,
                        |f|
                            f(&triangulation::rect_tri_list_xy(
                                transform,
                                rectangle
                            )),
                    );
                }
                Shape::Round(round_radius) => {
                    g.tri_list(
                        draw_state,
                        &self.color,
                        |f|
                    triangulation::with_round_rectangle_tri_list(
                        32,
                        transform,
                        rectangle,
                        round_radius,
                        |vertices| f(vertices)
                    ));
                }
                Shape::Bevel(bevel_radius) => {
                    g.tri_list(
                        draw_state,
                        &self.color,
                        |f|
                    triangulation::with_round_rectangle_tri_list(
                        2,
                        transform,
                        rectangle,
                        bevel_radius,
                        |vertices| f(vertices)
                    ));
                }
            }
        }

        if let Some(Border { color, radius: border_radius }) = self.border {
            if color[3] == 0.0 { return; }
            match self.shape {
                Shape::Square => {
                    g.tri_list(
                        draw_state,
                        &color,
                        |f| f(
                            &triangulation::rect_border_tri_list_xy(
                                transform, rectangle, border_radius),
                        )
                    );
                }
                Shape::Round(round_radius) => {
                    g.tri_list(
                        draw_state,
                        &color,
                        |f|
                    triangulation::with_round_rectangle_border_tri_list(
                        128,
                        transform,
                        rectangle,
                        round_radius,
                        border_radius,
                        |vertices| f(vertices)
                    ));
                }
                Shape::Bevel(bevel_radius) => {
                    g.tri_list(
                        draw_state,
                        &color,
                        |f|
                    triangulation::with_round_rectangle_border_tri_list(
                        2,
                        transform,
                        rectangle,
                        bevel_radius,
                        border_radius,
                        |vertices| f(vertices)
                    ));
                }
            }
        }
    }
}

#[cfg(test)]
mod test {
    use super::Rectangle;
    use super::Shape;
    use super::Border;
    use Color;

    #[test]
    fn test_rectangle() {
        let _rectangle = Rectangle::new([1.0; 4])
            .color([0.0; 4])
            .shape(Shape::Round(10.0))
            .border(Border { color: [0.0; 4], radius: 4.0 });
    }
}
<commit_msg>Removed `rectangle::MaybeBorder`<commit_after>//! Draw rectangle

use internal;
use triangulation;
use Graphics;
use Color;
use DrawState;
use math::Matrix2d;

pub use math::margin_rectangle as margin;

/// Use x, y, half-width, half-height
pub fn centered(rect: internal::Rectangle) -> internal::Rectangle {
    [rect[0] - rect[2], rect[1] - rect[3], 2.0 * rect[2], 2.0 * rect[3]]
}

/// Use centered square
pub fn centered_square(
    x: internal::Scalar,
    y: internal::Scalar,
    radius: internal::Scalar
) -> internal::Rectangle {
    [x - radius, y - radius, 2.0 * radius, 2.0 * radius]
}

/// Use square with x, y in upper left corner
pub fn square(
    x: internal::Scalar,
    y: internal::Scalar,
    size: internal::Scalar
) -> internal::Rectangle {
    [x, y, size, size]
}

/// The shape of the rectangle
#[derive(Copy, Clone)]
pub enum Shape {
    /// Square corners
    Square,
    /// Round corners
    Round(internal::Radius),
    /// Bevel corners
    Bevel(internal::Radius),
}

/// The border of the rectangle
#[derive(Copy, Clone)]
pub struct Border {
    /// The color of the border
    pub color: internal::Color,
    /// The radius of the border
    pub radius: internal::Radius,
}

/// A filled rectangle
#[derive(Copy, Clone)]
pub struct Rectangle {
    /// The rectangle color
    pub color: internal::Color,
    /// The roundness of the rectangle
    pub shape: Shape,
    /// The border
    pub border: Option<Border>,
}

impl Rectangle {
    /// Creates a new rectangle.
    pub fn new(color: internal::Color) -> Rectangle {
        Rectangle {
            color: color,
            shape: Shape::Square,
            border: None,
        }
    }

    /// Creates a new round rectangle.
    pub fn new_round(
        color: internal::Color,
        round_radius: internal::Radius
    ) -> Rectangle {
        Rectangle {
            color: color,
            shape: Shape::Round(round_radius),
            border: None
        }
    }

    /// Creates a new rectangle border.
    pub fn new_border(
        color: internal::Color,
        radius: internal::Radius
    ) -> Rectangle {
        Rectangle {
            color: [0.0; 4],
            shape: Shape::Square,
            border: Some(Border {
                    color: color,
                    radius: radius
                })
        }
    }

    /// Creates a new round rectangle border.
    pub fn new_round_border(
        color: internal::Color,
        round_radius: internal::Radius,
        border_radius: internal::Radius
    ) -> Rectangle {
        Rectangle {
            color: [0.0; 4],
            shape: Shape::Round(round_radius),
            border: Some(Border {
                    color: color,
                    radius: border_radius
                })
        }
    }

    /// Sets color.
    pub fn color(mut self, value: internal::Color) -> Self {
        self.color = value;
        self
    }

    /// Sets shape.
    pub fn shape(mut self, value: Shape) -> Self {
        self.shape = value;
        self
    }

    /// Sets border.
    pub fn border(mut self, value: Border) -> Self {
        self.border = Some(value);
        self
    }

    /// Sets optional border.
    pub fn maybe_border(mut self, value: Option<Border>) -> Self {
        self.border = value;
        self
    }

    /// Draws the rectangle
    pub fn draw<G>(
        &self,
        rectangle: internal::Rectangle,
        draw_state: &DrawState,
        transform: Matrix2d,
        g: &mut G
    )
        where G: Graphics
    {
        if self.color[3] != 0.0 {
            match self.shape {
                Shape::Square => {
                    g.tri_list(
                        draw_state,
                        &self.color,
                        |f|
                            f(&triangulation::rect_tri_list_xy(
                                transform,
                                rectangle
                            )),
                    );
                }
                Shape::Round(round_radius) => {
                    g.tri_list(
                        draw_state,
                        &self.color,
                        |f|
                    triangulation::with_round_rectangle_tri_list(
                        32,
                        transform,
                        rectangle,
                        round_radius,
                        |vertices| f(vertices)
                    ));
                }
                Shape::Bevel(bevel_radius) => {
                    g.tri_list(
                        draw_state,
                        &self.color,
                        |f|
                    triangulation::with_round_rectangle_tri_list(
                        2,
                        transform,
                        rectangle,
                        bevel_radius,
                        |vertices| f(vertices)
                    ));
                }
            }
        }

        if let Some(Border { color, radius: border_radius }) = self.border {
            if color[3] == 0.0 { return; }
            match self.shape {
                Shape::Square => {
                    g.tri_list(
                        draw_state,
                        &color,
                        |f| f(
                            &triangulation::rect_border_tri_list_xy(
                                transform, rectangle, border_radius),
                        )
                    );
                }
                Shape::Round(round_radius) => {
                    g.tri_list(
                        draw_state,
                        &color,
                        |f|
                    triangulation::with_round_rectangle_border_tri_list(
                        128,
                        transform,
                        rectangle,
                        round_radius,
                        border_radius,
                        |vertices| f(vertices)
                    ));
                }
                Shape::Bevel(bevel_radius) => {
                    g.tri_list(
                        draw_state,
                        &color,
                        |f|
                    triangulation::with_round_rectangle_border_tri_list(
                        2,
                        transform,
                        rectangle,
                        bevel_radius,
                        border_radius,
                        |vertices| f(vertices)
                    ));
                }
            }
        }
    }
}

#[cfg(test)]
mod test {
    use super::Rectangle;
    use super::Shape;
    use super::Border;
    use Color;

    #[test]
    fn test_rectangle() {
        let _rectangle = Rectangle::new([1.0; 4])
            .color([0.0; 4])
            .shape(Shape::Round(10.0))
            .border(Border { color: [0.0; 4], radius: 4.0 });
    }
}
<|endoftext|>


<commit_before>#[crate_id = "rlua#0.3.0"];
#[crate_type = "bin"];
#[license = "MIT"];

#[feature(globs)];

extern mod rlua;

fn main()
{
}
<commit_msg>- 'extern mod' -> 'extern crate'<commit_after>#[crate_id = "rlua#0.3.0"];
#[crate_type = "bin"];
#[license = "MIT"];

#[feature(globs)];

extern crate rlua;

fn main()
{
}
<|endoftext|>