<commit_before>//! Parser module for Textile language.

mod attributes;
mod block;
mod inline;
mod patterns;

use into_string::*;
use parser::block::parse_blocks;
use std::collections::HashMap;

/// Vector of Textile attributes, e.g. classes, ID's or CSS styles.
pub type Attributes = Vec<Attribute>;

/// Block element, e.g. heading, paragraph or code block.
#[derive(Debug, PartialEq)]
pub enum Block {
    /// Block quotation, e.g. `bq. Some quote`.
    BlockQuotation {
        attributes: Attributes,
        cite: String,
        elements: Vec<Block>,
    },
    /// Code block, e.g. `bc. print("Hello World")`.
    CodeBlock {
        attributes: Attributes,
        code: String,
    },
    /// Comment block.
    Comment(Vec<String>),
    /// Heading, e.g. `h3. Some text`.
    Heading {
        attributes: Attributes,
        elements: Vec<Inline>,
        level: u8,
    },
    /// Disable Textile formatting in a block of text.
    NoTextileBlock(Vec<String>),
    /// Paragraph, e.g. `p. Some text` or `Some text`.
    Paragraph {
        attributes: Attributes,
        elements: Vec<Inline>,
        starts_with_p: bool,
    },
    Pre {
        attributes: Attributes,
        lines: Vec<String>,
    },
}

/// Inline element, e.g. bold text, link or image.
#[derive(Debug, PartialEq)]
pub enum Inline {
    /// Abbreviation, e.g. `ABBR(Abbreviation)`.
    Abbreviation {
        abbr: String,
        transcript: String,
    },
    /// Bold text, e.g. `*Text*` or `**Text**`.
    Bold {
        attributes: Attributes,
        elements: Vec<Inline>,
        tag_type: BoldTagType,
    },
    /// Line break. Converts to `<br>` tag in HTML.
    Break,
    /// Citation, e.g. `??Some citation??`.
    Citation {
        attributes: Attributes,
        elements: Vec<Inline>,
    },
    /// Code, e.g. `@puts "Hello world!"@`.
    Code(String),
    /// Image, e.g. `!http://example.com/image.jpg(Image)!`.
    Image {
        attributes: Attributes,
        alt: String,
        href: String,
        src: String,
    },
    /// Italic text, e.g. `_Text_` or `__Text__`.
    Italic {
        attributes: Attributes,
        elements: Vec<Inline>,
        tag_type: ItalicTagType,
    },
    /// Link, e.g. `"Link":http://example.com`.
    Link {
        attributes: Attributes,
        elements: Vec<Inline>,
        href: String,
        title: String,
    },
    /// Span element, e.g. `%Span text%`.
    Span {
        attributes: Attributes,
        elements: Vec<Inline>,
    },
    /// Strikethrough text, e.g. `-Text-`.
    Strikethrough {
        attributes: Attributes,
        elements: Vec<Inline>,
    },
    /// Subscript text, e.g. `~Text~`.
    Subscript {
        attributes: Attributes,
        elements: Vec<Inline>,
    },
    /// Superscript text, e.g. `^Text^`.
    Superscript {
        attributes: Attributes,
        elements: Vec<Inline>,
    },
    /// String with text.
    Text(String),
    /// Underlined text, e.g. `+Text+`.
    Underlined {
        attributes: Attributes,
        elements: Vec<Inline>,
    },
}

/// Tag type for bold text.
#[derive(Debug, PartialEq)]
pub enum BoldTagType {
    /// Converts into HTML `<b>` tag.
    Bold,
    /// Converts into HTML `<strong>` tag.
    Strong,
}

/// Tag type for italic text.
#[derive(Debug, PartialEq)]
pub enum ItalicTagType {
    /// Converts into HTML `<em>` tag.
    Emphasis,
    /// Converts into HTML `<i>` tag.
    Italic,
}

/// Textile attribute.
#[derive(Debug, Clone, PartialEq)]
pub enum Attribute {
    /// Image align. Convertes into HTML `align` attribute.
    Align(String),
    /// Vector of HTML classes. Converts into HTML `class` attribute.
    Class(Vec<String>),
    /// Converts into HTML `id` attribute.
    Id(String),
    /// Converts into HTML `lang` attribute.
    Language(String),
    /// CSS styles. Converts into HTML `style` attribute.
    Style(HashMap<String, String>)
}

/// Splits text into tokens. Accepts `&str`, `String` or `Path` data type. Returns vector of block elements.
///
/// # Example
///
/// ```rust
/// use textile::parser::*;
///
/// let text = "h1. _String with text_.";
/// assert_eq!(parse(text), vec![
///     Block::Heading {
///         attributes: vec![],
///         elements: vec![
///             Inline::Italic {
///                 attributes: vec![],
///                 tag_type: ItalicTagType::Emphasis,
///                 elements: vec![
///                     Inline::Text("String with text".to_string())
///                 ]
///             },
///             Inline::Text(".".to_string())
///         ],
///         level: 1
///     }
/// ]);
/// ```
pub fn parse<S: IntoString>(text: S) -> Vec<Block> {
    parse_blocks(&text.into_string().lines().collect::<Vec<&str>>())
}
<commit_msg>Update documentation in 'Block' enum<commit_after>//! Parser module for Textile language.

mod attributes;
mod block;
mod inline;
mod patterns;

use into_string::*;
use parser::block::parse_blocks;
use std::collections::HashMap;

/// Vector of Textile attributes, e.g. classes, ID's or CSS styles.
pub type Attributes = Vec<Attribute>;

/// Block element, e.g. heading, paragraph or code block.
#[derive(Debug, PartialEq)]
pub enum Block {
    /// Block quotation, e.g. `bq. Some quote`.
    BlockQuotation {
        attributes: Attributes,
        cite: String,
        elements: Vec<Block>,
    },
    /// Code block, e.g. `bc. print("Hello World")`.
    CodeBlock {
        attributes: Attributes,
        code: String,
    },
    /// Comment block.
    Comment(Vec<String>),
    /// Heading, e.g. `h3. Some text`.
    Heading {
        attributes: Attributes,
        elements: Vec<Inline>,
        level: u8,
    },
    /// In this block the Textile formatting is disabled.
    NoTextileBlock(Vec<String>),
    /// Paragraph, e.g. `p. Some text` or `Some text`.
    Paragraph {
        attributes: Attributes,
        elements: Vec<Inline>,
        starts_with_p: bool,
    },
    /// Pre-formatted text, e.g. `pre. *Some text*`
    Pre {
        attributes: Attributes,
        lines: Vec<String>,
    },
}

/// Inline element, e.g. bold text, link or image.
#[derive(Debug, PartialEq)]
pub enum Inline {
    /// Abbreviation, e.g. `ABBR(Abbreviation)`.
    Abbreviation {
        abbr: String,
        transcript: String,
    },
    /// Bold text, e.g. `*Text*` or `**Text**`.
    Bold {
        attributes: Attributes,
        elements: Vec<Inline>,
        tag_type: BoldTagType,
    },
    /// Line break. Converts to `<br>` tag in HTML.
    Break,
    /// Citation, e.g. `??Some citation??`.
    Citation {
        attributes: Attributes,
        elements: Vec<Inline>,
    },
    /// Code, e.g. `@puts "Hello world!"@`.
    Code(String),
    /// Image, e.g. `!http://example.com/image.jpg(Image)!`.
    Image {
        attributes: Attributes,
        alt: String,
        href: String,
        src: String,
    },
    /// Italic text, e.g. `_Text_` or `__Text__`.
    Italic {
        attributes: Attributes,
        elements: Vec<Inline>,
        tag_type: ItalicTagType,
    },
    /// Link, e.g. `"Link":http://example.com`.
    Link {
        attributes: Attributes,
        elements: Vec<Inline>,
        href: String,
        title: String,
    },
    /// Span element, e.g. `%Span text%`.
    Span {
        attributes: Attributes,
        elements: Vec<Inline>,
    },
    /// Strikethrough text, e.g. `-Text-`.
    Strikethrough {
        attributes: Attributes,
        elements: Vec<Inline>,
    },
    /// Subscript text, e.g. `~Text~`.
    Subscript {
        attributes: Attributes,
        elements: Vec<Inline>,
    },
    /// Superscript text, e.g. `^Text^`.
    Superscript {
        attributes: Attributes,
        elements: Vec<Inline>,
    },
    /// String with text.
    Text(String),
    /// Underlined text, e.g. `+Text+`.
    Underlined {
        attributes: Attributes,
        elements: Vec<Inline>,
    },
}

/// Tag type for bold text.
#[derive(Debug, PartialEq)]
pub enum BoldTagType {
    /// Converts into HTML `<b>` tag.
    Bold,
    /// Converts into HTML `<strong>` tag.
    Strong,
}

/// Tag type for italic text.
#[derive(Debug, PartialEq)]
pub enum ItalicTagType {
    /// Converts into HTML `<em>` tag.
    Emphasis,
    /// Converts into HTML `<i>` tag.
    Italic,
}

/// Textile attribute.
#[derive(Debug, Clone, PartialEq)]
pub enum Attribute {
    /// Image align. Convertes into HTML `align` attribute.
    Align(String),
    /// Vector of HTML classes. Converts into HTML `class` attribute.
    Class(Vec<String>),
    /// Converts into HTML `id` attribute.
    Id(String),
    /// Converts into HTML `lang` attribute.
    Language(String),
    /// CSS styles. Converts into HTML `style` attribute.
    Style(HashMap<String, String>)
}

/// Splits text into tokens. Accepts `&str`, `String` or `Path` data type. Returns vector of block elements.
///
/// # Example
///
/// ```rust
/// use textile::parser::*;
///
/// let text = "h1. _String with text_.";
/// assert_eq!(parse(text), vec![
///     Block::Heading {
///         attributes: vec![],
///         elements: vec![
///             Inline::Italic {
///                 attributes: vec![],
///                 tag_type: ItalicTagType::Emphasis,
///                 elements: vec![
///                     Inline::Text("String with text".to_string())
///                 ]
///             },
///             Inline::Text(".".to_string())
///         ],
///         level: 1
///     }
/// ]);
/// ```
pub fn parse<S: IntoString>(text: S) -> Vec<Block> {
    parse_blocks(&text.into_string().lines().collect::<Vec<&str>>())
}
<|endoftext|>


<commit_before>use regex::Regex;
use http::method::Method;
use iron::{Middleware, Request, Response, Alloy};
use iron::middleware::{Status, Continue, Unwind};
use iron::mixin::{GetUrl};

pub mod params;
mod glob;

pub type Handler = fn(&mut Request, &mut Response, &mut Alloy) -> ();

#[deriving(Clone)]
pub struct Router {
    routes: Vec<Route>
}

struct Route {
    method: Method,
    glob: String,
    matches: Regex,
    handler: Handler,
    params: Vec<String>
}

impl Clone for Route {
    fn clone(&self) -> Route {
        Route {
            method: self.method.clone(),
            glob: self.glob.clone(),
            matches: self.matches.clone(),
            handler: self.handler,
            params: self.params.clone()
        }
    }
}

impl Router {
    pub fn new() -> Router { Router { routes: Vec::new() } }
    pub fn route(&mut self, method: Method, glob: String,
                 params: Vec<String>, handler: Handler) {
        self.routes.push(Route {
            method: method,
            glob: glob.clone(),
            matches: glob::deglob(glob),
            handler: handler,
            params: params
        });
    }
}

impl Middleware for Router {
    fn enter(&mut self, req: &mut Request, res: &mut Response, alloy: &mut Alloy) -> Status {
        let request_uri = match req.url() {
            Some(uri) => uri.clone(),
            // Not an AbsolutePath, not our domain.
            None => { return Continue; }
        };

        for route in self.routes.iter() {
            if route.matches.is_match(request_uri.as_slice()) {
                alloy.insert::<params::Params>(
                    params::Params::new(
                        request_uri.as_slice(),
                        route.matches.clone(),
                        route.params.clone().move_iter()
                    )
                );
                (route.handler)(req, res, alloy);
                return Unwind;
            }
        }
        Continue
    }
}

<commit_msg>(cleanup) Cleaned up some small issues.<commit_after>use regex::Regex;
use http::method::Method;
use iron::{Middleware, Request, Response, Alloy};
use iron::middleware::{Status, Continue, Unwind};
use iron::mixin::GetUrl;

pub mod params;
mod glob;

pub type Handler = fn(&mut Request, &mut Response, &mut Alloy) -> ();

#[deriving(Clone)]
pub struct Router {
    routes: Vec<Route>
}

struct Route {
    method: Method,
    glob: String,
    matches: Regex,
    handler: Handler,
    params: Vec<String>
}

impl Clone for Route {
    fn clone(&self) -> Route {
        Route {
            method: self.method.clone(),
            glob: self.glob.clone(),
            matches: self.matches.clone(),
            handler: self.handler,
            params: self.params.clone()
        }
    }
}

impl Router {
    pub fn new() -> Router { Router { routes: Vec::new() } }
    pub fn route(&mut self, method: Method, glob: String,
                 params: Vec<String>, handler: Handler) {
        self.routes.push(Route {
            method: method,
            glob: glob.clone(),
            matches: glob::deglob(glob),
            handler: handler,
            params: params
        });
    }
}

impl Middleware for Router {
    fn enter(&mut self, req: &mut Request, res: &mut Response, alloy: &mut Alloy) -> Status {
        let request_uri = match req.url() {
            Some(uri) => uri.clone(),
            // Not an AbsolutePath, not our problem.
            None => { return Continue; }
        };

        for route in self.routes.iter() {
            if route.matches.is_match(request_uri.as_slice()) {
                alloy.insert::<params::Params>(
                    params::Params::new(
                        request_uri.as_slice(),
                        route.matches.clone(),
                        route.params.clone().move_iter()
                    )
                );
                (route.handler)(req, res, alloy);
                return Unwind;
            }
        }
        Continue
    }
}

<|endoftext|>


<commit_before>//! Provides a high quality sampling scheme based on (0, 2)-sequences
//! See sec. 7.4.3 of Physically Based Rendering

use std::num::UnsignedInt;
use std::rand;
use std::rand::Rng;
use std::rand::distributions::{IndependentSample, Range};
use std::u32;
use std::f32;
use std::num::Float;

use sampler::{Sampler, Region};

/// Low discrepancy sampler that makes use of the (0, 2) sequence to generate
/// well distributed samples
pub struct LowDiscrepancy {
    region: Region,
    /// Number of samples to take per pixel
    spp: usize,
    scramble_range: Range<u32>,
}

impl LowDiscrepancy {
    /// Create a low discrepancy sampler to sample the image in `dim.0 * dim.1` sized blocks
    pub fn new(dim: (u32, u32), mut spp: usize) -> LowDiscrepancy {
        if !spp.is_power_of_two() {
            spp = spp.next_power_of_two();
            print!("Warning: LowDiscrepancy sampler requires power of two samples per pixel, ");
            println!("rounding up to {}", spp);
        }
        LowDiscrepancy { region: Region::new((0, 0), dim), spp: spp,
                         scramble_range: Range::new(0u32, u32::MAX) }
    }
}

impl Sampler for LowDiscrepancy {
    fn get_samples(&mut self, samples: &mut Vec<(f32, f32)>) {
        samples.clear();
        if !self.has_samples() {
            return;
        }
        if samples.len() < self.spp {
            samples.resize(self.spp, (0.0, 0.0));
        }
        let mut rng = rand::thread_rng();
        let scramble = (self.scramble_range.ind_sample(&mut rng),
                        self.scramble_range.ind_sample(&mut rng));
        sample_2d(&mut samples[], scramble);
        rng.shuffle(&mut samples[]);
        let frange = Range::new(0f32, 1f32);
        for s in samples.iter_mut() {
            s.0 = frange.ind_sample(&mut rng);
            s.1 = frange.ind_sample(&mut rng);
            s.0 += self.region.current.0 as f32;
            s.1 += self.region.current.1 as f32;
        }

        self.region.current.0 += 1;
        if self.region.current.0 == self.region.end.0 {
            self.region.current.0 = self.region.start.0;
            self.region.current.1 += 1;
        }
    }
    fn max_spp(&self) -> usize { self.spp }
    fn has_samples(&self) -> bool { self.region.current.1 != self.region.end.1 }
    fn dimensions(&self) -> (u32, u32) { self.region.dim }
    fn select_block(&mut self, start: (u32, u32)) {
        self.region.select_region(start);
    }
}

/// Generate a 2D pattern of low discrepancy samples to fill the slice
/// sample values will be normalized between [0, 1]
pub fn sample_2d(samples: &mut [(f32, f32)], scramble: (u32, u32)) {
    for s in samples.iter_mut().enumerate() {
        *s.1 = sample_02(s.0 as u32, scramble);
    }
}
/// Generate a sample from a scrambled (0, 2) sequence
pub fn sample_02(n: u32, scramble: (u32, u32)) -> (f32, f32) {
    (van_der_corput(n, scramble.0), sobol(n, scramble.1))
}
/// Generate a scrambled Van der Corput sequence value
/// as described by Kollig & Keller (2002) and in PBR
/// method is specialized for base 2
pub fn van_der_corput(mut n: u32, scramble: u32) -> f32 {
	n = (n << 16) | (n >> 16);
	n = ((n & 0x00ff00ff) << 8) | ((n & 0xff00ff00) >> 8);
	n = ((n & 0x0f0f0f0f) << 4) | ((n & 0xf0f0f0f0) >> 4);
	n = ((n & 0x33333333) << 2) | ((n & 0xcccccccc) >> 2);
	n = ((n & 0x55555555) << 1) | ((n & 0xaaaaaaaa) >> 1);
	n ^= scramble;
	Float::min(((n >> 8) & 0xffffff) as f32 / ((1 << 24) as f32), 1.0 - f32::EPSILON)
}
/// Generate a scrambled Sobol' sequence value
/// as described by Kollig & Keller (2002) and in PBR
/// method is specialized for base 2
pub fn sobol(mut n: u32, mut scramble: u32) -> f32 {
    let mut i = 1 << 31;
    while n != 0 {
        if n & 0x1 != 0 {
            scramble ^= i;
        }
        n >>= 1;
        i ^= i >> 1;
    }
    Float::min(((scramble >> 8) & 0xffffff) as f32 / ((1 << 24) as f32), 1.0 - f32::EPSILON)
}

<commit_msg>Accidently committed the random float sampler I was testing with<commit_after>//! Provides a high quality sampling scheme based on (0, 2)-sequences
//! See sec. 7.4.3 of Physically Based Rendering

use std::num::UnsignedInt;
use std::rand;
use std::rand::Rng;
use std::rand::distributions::{IndependentSample, Range};
use std::u32;
use std::f32;
use std::num::Float;

use sampler::{Sampler, Region};

/// Low discrepancy sampler that makes use of the (0, 2) sequence to generate
/// well distributed samples
pub struct LowDiscrepancy {
    region: Region,
    /// Number of samples to take per pixel
    spp: usize,
    scramble_range: Range<u32>,
}

impl LowDiscrepancy {
    /// Create a low discrepancy sampler to sample the image in `dim.0 * dim.1` sized blocks
    pub fn new(dim: (u32, u32), mut spp: usize) -> LowDiscrepancy {
        if !spp.is_power_of_two() {
            spp = spp.next_power_of_two();
            print!("Warning: LowDiscrepancy sampler requires power of two samples per pixel, ");
            println!("rounding up to {}", spp);
        }
        LowDiscrepancy { region: Region::new((0, 0), dim), spp: spp,
                         scramble_range: Range::new(0u32, u32::MAX) }
    }
}

impl Sampler for LowDiscrepancy {
    fn get_samples(&mut self, samples: &mut Vec<(f32, f32)>) {
        samples.clear();
        if !self.has_samples() {
            return;
        }
        if samples.len() < self.spp {
            samples.resize(self.spp, (0.0, 0.0));
        }
        let mut rng = rand::thread_rng();
        let scramble = (self.scramble_range.ind_sample(&mut rng),
                        self.scramble_range.ind_sample(&mut rng));
        sample_2d(&mut samples[], scramble);
        rng.shuffle(&mut samples[]);
        for s in samples.iter_mut() {
            s.0 += self.region.current.0 as f32;
            s.1 += self.region.current.1 as f32;
        }

        self.region.current.0 += 1;
        if self.region.current.0 == self.region.end.0 {
            self.region.current.0 = self.region.start.0;
            self.region.current.1 += 1;
        }
    }
    fn max_spp(&self) -> usize { self.spp }
    fn has_samples(&self) -> bool { self.region.current.1 != self.region.end.1 }
    fn dimensions(&self) -> (u32, u32) { self.region.dim }
    fn select_block(&mut self, start: (u32, u32)) {
        self.region.select_region(start);
    }
}

/// Generate a 2D pattern of low discrepancy samples to fill the slice
/// sample values will be normalized between [0, 1]
pub fn sample_2d(samples: &mut [(f32, f32)], scramble: (u32, u32)) {
    for s in samples.iter_mut().enumerate() {
        *s.1 = sample_02(s.0 as u32, scramble);
    }
}
/// Generate a sample from a scrambled (0, 2) sequence
pub fn sample_02(n: u32, scramble: (u32, u32)) -> (f32, f32) {
    (van_der_corput(n, scramble.0), sobol(n, scramble.1))
}
/// Generate a scrambled Van der Corput sequence value
/// as described by Kollig & Keller (2002) and in PBR
/// method is specialized for base 2
pub fn van_der_corput(mut n: u32, scramble: u32) -> f32 {
	n = (n << 16) | (n >> 16);
	n = ((n & 0x00ff00ff) << 8) | ((n & 0xff00ff00) >> 8);
	n = ((n & 0x0f0f0f0f) << 4) | ((n & 0xf0f0f0f0) >> 4);
	n = ((n & 0x33333333) << 2) | ((n & 0xcccccccc) >> 2);
	n = ((n & 0x55555555) << 1) | ((n & 0xaaaaaaaa) >> 1);
	n ^= scramble;
	Float::min(((n >> 8) & 0xffffff) as f32 / ((1 << 24) as f32), 1.0 - f32::EPSILON)
}
/// Generate a scrambled Sobol' sequence value
/// as described by Kollig & Keller (2002) and in PBR
/// method is specialized for base 2
pub fn sobol(mut n: u32, mut scramble: u32) -> f32 {
    let mut i = 1 << 31;
    while n != 0 {
        if n & 0x1 != 0 {
            scramble ^= i;
        }
        n >>= 1;
        i ^= i >> 1;
    }
    Float::min(((scramble >> 8) & 0xffffff) as f32 / ((1 << 24) as f32), 1.0 - f32::EPSILON)
}

<|endoftext|>


<commit_before>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

use std::option::Option;

use uuid::Uuid;

use kvproto::metapb;
use kvproto::eraftpb::{self, ConfChangeType};
use kvproto::raft_cmdpb::RaftCmdRequest;
use raftstore::{Result, Error};

pub fn find_peer(region: &metapb::Region, store_id: u64) -> Option<&metapb::Peer> {
    for peer in region.get_peers() {
        if peer.get_store_id() == store_id {
            return Some(peer);
        }
    }

    None
}

pub fn remove_peer(region: &mut metapb::Region, store_id: u64) -> Option<metapb::Peer> {
    region.get_peers()
        .iter()
        .position(|x| x.get_store_id() == store_id)
        .map(|i| region.mut_peers().remove(i))
}

// a helper function to create peer easily.
pub fn new_peer(store_id: u64, peer_id: u64) -> metapb::Peer {
    let mut peer = metapb::Peer::new();
    peer.set_store_id(store_id);
    peer.set_id(peer_id);
    peer
}

pub fn get_uuid_from_req(cmd: &RaftCmdRequest) -> Option<Uuid> {
    Uuid::from_bytes(cmd.get_header().get_uuid())
}

pub fn check_key_in_region(key: &[u8], region: &metapb::Region) -> Result<()> {
    let end_key = region.get_end_key();
    let start_key = region.get_start_key();
    if key >= start_key && (end_key.is_empty() || key < end_key) {
        Ok(())
    } else {
        Err(Error::KeyNotInRegion(key.to_vec(), region.clone()))
    }
}

pub fn conf_change_type_str(conf_type: &eraftpb::ConfChangeType) -> String {
    match *conf_type {
        ConfChangeType::AddNode => "AddNode".to_owned(),
        ConfChangeType::RemoveNode => "RemoveNode".to_owned(),
    }
}

// check whether epoch is staler than check_epoch.
pub fn is_epoch_stale(epoch: &metapb::RegionEpoch, check_epoch: &metapb::RegionEpoch) -> bool {
    epoch.get_version() < check_epoch.get_version() ||
    epoch.get_conf_ver() < check_epoch.get_conf_ver()
}

#[cfg(test)]
mod tests {
    use kvproto::metapb;

    use super::*;

    #[test]
    fn test_peer() {
        let mut region = metapb::Region::new();
        region.set_id(1);
        region.mut_peers().push(new_peer(1, 1));

        assert!(find_peer(&region, 1).is_some());
        assert!(find_peer(&region, 10).is_none());

        assert!(remove_peer(&mut region, 1).is_some());
        assert!(remove_peer(&mut region, 1).is_none());
        assert!(find_peer(&region, 1).is_none());

    }
}
<commit_msg>store: use &str for conf_change_type_str<commit_after>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

use std::option::Option;

use uuid::Uuid;

use kvproto::metapb;
use kvproto::eraftpb::{self, ConfChangeType};
use kvproto::raft_cmdpb::RaftCmdRequest;
use raftstore::{Result, Error};

pub fn find_peer(region: &metapb::Region, store_id: u64) -> Option<&metapb::Peer> {
    for peer in region.get_peers() {
        if peer.get_store_id() == store_id {
            return Some(peer);
        }
    }

    None
}

pub fn remove_peer(region: &mut metapb::Region, store_id: u64) -> Option<metapb::Peer> {
    region.get_peers()
        .iter()
        .position(|x| x.get_store_id() == store_id)
        .map(|i| region.mut_peers().remove(i))
}

// a helper function to create peer easily.
pub fn new_peer(store_id: u64, peer_id: u64) -> metapb::Peer {
    let mut peer = metapb::Peer::new();
    peer.set_store_id(store_id);
    peer.set_id(peer_id);
    peer
}

pub fn get_uuid_from_req(cmd: &RaftCmdRequest) -> Option<Uuid> {
    Uuid::from_bytes(cmd.get_header().get_uuid())
}

pub fn check_key_in_region(key: &[u8], region: &metapb::Region) -> Result<()> {
    let end_key = region.get_end_key();
    let start_key = region.get_start_key();
    if key >= start_key && (end_key.is_empty() || key < end_key) {
        Ok(())
    } else {
        Err(Error::KeyNotInRegion(key.to_vec(), region.clone()))
    }
}

const CONF_CHANGE_ADD_NODE_STR: &'static str = "AddNode";
const CONF_CHANGE_REMOVE_NODE_STR: &'static str = "RemoveNode";

pub fn conf_change_type_str(conf_type: &eraftpb::ConfChangeType) -> &'static str {
    match *conf_type {
        ConfChangeType::AddNode => CONF_CHANGE_ADD_NODE_STR,
        ConfChangeType::RemoveNode => CONF_CHANGE_REMOVE_NODE_STR,
    }
}

// check whether epoch is staler than check_epoch.
pub fn is_epoch_stale(epoch: &metapb::RegionEpoch, check_epoch: &metapb::RegionEpoch) -> bool {
    epoch.get_version() < check_epoch.get_version() ||
    epoch.get_conf_ver() < check_epoch.get_conf_ver()
}

#[cfg(test)]
mod tests {
    use kvproto::metapb;

    use super::*;

    #[test]
    fn test_peer() {
        let mut region = metapb::Region::new();
        region.set_id(1);
        region.mut_peers().push(new_peer(1, 1));

        assert!(find_peer(&region, 1).is_some());
        assert!(find_peer(&region, 10).is_none());

        assert!(remove_peer(&mut region, 1).is_some());
        assert!(remove_peer(&mut region, 1).is_none());
        assert!(find_peer(&region, 1).is_none());

    }
}
<|endoftext|>


<commit_before>use std::io::Read;
use error::{Result, Error, ErrorKind};
use reader::{FbxEvent, PropertyValue};
use super::CommonState;

#[derive(Debug, Clone)]
pub struct BinaryParser {
    version: u32,
    end_offset_stack: Vec<u32>,
}

impl BinaryParser {
    pub fn new(version: u32) -> Self {
        BinaryParser {
            version: version,
            end_offset_stack: vec![],
        }
    }

    pub fn next<R: Read>(&mut self, reader: &mut R, common: &mut CommonState) -> Result<FbxEvent> {
        // Check if the previously read node ends here.
        if let Some(&end_pos_top) = self.end_offset_stack.last() {
            if end_pos_top as u64 == common.pos {
                // Reached the end of previously read node.
                self.end_offset_stack.pop();
                return Ok(FbxEvent::EndNode);
            }
        }

        // Read a node record header.
        let node_record_header = try!(NodeRecordHeader::read(reader, &mut common.pos));
        if node_record_header.is_null_record() {
            // End of a node.
            return if let Some(expected_pos) = self.end_offset_stack.pop() {
                if common.pos == expected_pos as u64 {
                    Ok(FbxEvent::EndNode)
                } else {
                    // Data is collapsed (the node doesn't end at expected position).
                    Err(Error::new(
                            common.pos,
                            ErrorKind::DataError(format!("Node does not end at expected position (expected {}, now at {})", expected_pos, common.pos))))
                }
            } else {
                // Data is collapsed (an extra node end marker found).
                Err(Error::new(common.pos, ErrorKind::DataError("An extra node end marker found".to_string())))
            };
        } else {
            // Start of a node.
            self.end_offset_stack.push(node_record_header.end_offset);
        }

        // Read a node name.
        let name = try_read_fixstr!(common.pos, reader, node_record_header.name_len);

        // Read properties.
        let mut properties = Vec::<PropertyValue>::with_capacity(node_record_header.num_properties as usize);
        for _ in 0..node_record_header.num_properties {
            let prop = try!(self.read_property(reader, common));
            properties.push(prop);
        }

        Ok(FbxEvent::StartNode {
            name: name,
            properties: properties,
        })
    }

    fn read_property<R: Read>(&mut self, reader: &mut R, common: &mut CommonState) -> Result<PropertyValue> {
        let type_code = try_read_le_u8!(common.pos, reader);
        // type code must be ASCII.
        let type_code = if type_code > 0x80 {
            return Err(Error::new(common.pos-1, ErrorKind::DataError(format!("Expected property type code (ASCII) but got {:#x}", type_code))));
        } else {
            type_code as char
        };
        let value = match type_code {
            // 1 bit boolean (1: true, 0: false) encoded as the LSB of a 1 byte value.
            'C' => {
                let val = try_read_le_u8!(common.pos, reader);
                // It seems 'T' (0x54) is used as `false`, 'T' (0x59) is used as `true`.
                if (val != 'T' as u8) && (val != 'Y' as u8) {
                    // Should this treated as error?
                    // (I don't know whether other characters than 'T' and 'Y' are allowed...)
                    warn!("Expected 'T' or 'Y' for representaton of boolean property value, but got {:#x}", val);
                }
                // Check LSB.
                PropertyValue::Bool(val & 1 == 1)
            },
            // 2 byte signed integer.
            'Y' => {
                PropertyValue::I16(try_read_le_i16!(common.pos, reader))
            },
            // 4 byte signed integer.
            'I' => {
                PropertyValue::I32(try_read_le_i32!(common.pos, reader))
            },
            // 4 byte single-precision IEEE 754 floating-point number.
            'F' => {
                PropertyValue::F32(try_read_le_f32!(common.pos, reader))
            },
            // 8 byte double-precision IEEE 754 floating-point number.
            'D' => {
                PropertyValue::F64(try_read_le_f64!(common.pos, reader))
            },
            // 8 byte signed integer.
            'L' => {
                PropertyValue::I64(try_read_le_i64!(common.pos, reader))
            },
            // Array types
            'f'|'d'|'l'|'i'|'b' => {
                let array_header = try!(PropertyArrayHeader::read(reader, &mut common.pos));
                try!(self.read_property_value_array(reader, common, type_code, &array_header))
            },
            // String
            'S' => {
                let length = try_read_le_u32!(common.pos, reader);
                PropertyValue::String(try_read_fixstr!(common.pos, reader, length))
            },
            // Raw binary data
            'R' => {
                let length = try_read_le_u32!(common.pos, reader);
                PropertyValue::Binary(try_read_exact!(common.pos, reader, length))
            },
            _ => {
                return Err(Error::new(
                        common.pos,
                        ErrorKind::DataError(format!(
                                "Unsupported type code appears in node property: type_code={}({:#x})",
                                type_code, type_code as u8))));
            }
        };
        Ok(value)
    }

    /// Read property value of array type from given stream which maybe compressed.
    fn read_property_value_array<R: Read>(&mut self,
                                          reader: &mut R, common: &mut CommonState,
                                          type_code: char, array_header: &PropertyArrayHeader) -> Result<PropertyValue> {
        match array_header.encoding {
            // 0; raw
            0 => {
                self.read_property_value_array_from_plain_stream(reader, common, type_code, array_header)
            },
            // 1: zlib compressed data
            1 => {
                Err(Error::new(
                        common.pos,
                        ErrorKind::Unimplemented("Parser for zlib compressed property array is not implemented yet".to_string())))
            },
            // Unknown.
            e => {
                Err(Error::new(
                        common.pos,
                        ErrorKind::DataError(format!("Unsupported property array encoding, got {:#x}", e))))
            }
        }
    }

    fn read_property_value_array_from_plain_stream<R: Read>(&mut self, reader: &mut R, common: &mut CommonState, type_code: char,
                                                            array_header: &PropertyArrayHeader) -> Result<PropertyValue> {
        Err(Error::new(
                common.pos,
                ErrorKind::Unimplemented("Parser for array type of property value is not implemented yet".to_string())))
    }
}

#[derive(Debug, Copy, Clone)]
struct NodeRecordHeader {
    end_offset: u32,
    num_properties: u32,
    property_list_len: u32,
    name_len: u8,
}

impl NodeRecordHeader {
    pub fn read<R: Read>(reader: &mut R, pos: &mut u64) -> Result<Self> {
        let end_offset = try_read_le_u32!(*pos, reader);
        let num_properties = try_read_le_u32!(*pos, reader);
        let property_list_len = try_read_le_u32!(*pos, reader);
        let name_len = try_read_le_u8!(*pos, reader);
        Ok(NodeRecordHeader {
            end_offset: end_offset,
            num_properties: num_properties,
            property_list_len: property_list_len,
            name_len: name_len,
        })
    }

    /// Check whether the header indicates there are no more children.
    pub fn is_null_record(&self) -> bool {
        self.end_offset == 0
            && self.num_properties == 0
            && self.property_list_len == 0
            && self.name_len == 0
    }
}

#[derive(Debug, Copy, Clone)]
pub struct PropertyArrayHeader {
    array_length: u32,
    encoding: u32,
    compressed_length: u32,
}

impl PropertyArrayHeader {
    pub fn read<R: Read>(reader: &mut R, pos: &mut u64) -> Result<Self> {
        let array_length = try_read_le_u32!(*pos, reader);
        let encoding = try_read_le_u32!(*pos, reader);
        let compressed_length = try_read_le_u32!(*pos, reader);
        Ok(PropertyArrayHeader {
            array_length: array_length,
            encoding: encoding,
            compressed_length: compressed_length,
        })
    }
}
<commit_msg>Implement binary parser for node property<commit_after>extern crate byteorder;
extern crate flate2;

use std::io::Read;
use error::{Result, Error, ErrorKind};
use reader::{FbxEvent, PropertyValue};
use super::CommonState;

#[derive(Debug, Clone)]
pub struct BinaryParser {
    version: u32,
    end_offset_stack: Vec<u32>,
}

impl BinaryParser {
    pub fn new(version: u32) -> Self {
        BinaryParser {
            version: version,
            end_offset_stack: vec![],
        }
    }

    pub fn next<R: Read>(&mut self, reader: &mut R, common: &mut CommonState) -> Result<FbxEvent> {
        // Check if the previously read node ends here.
        if let Some(&end_pos_top) = self.end_offset_stack.last() {
            if end_pos_top as u64 == common.pos {
                // Reached the end of previously read node.
                self.end_offset_stack.pop();
                return Ok(FbxEvent::EndNode);
            }
        }

        // Read a node record header.
        let node_record_header = try!(NodeRecordHeader::read(reader, &mut common.pos));
        if node_record_header.is_null_record() {
            // End of a node.
            return if let Some(expected_pos) = self.end_offset_stack.pop() {
                if common.pos == expected_pos as u64 {
                    Ok(FbxEvent::EndNode)
                } else {
                    // Data is collapsed (the node doesn't end at expected position).
                    Err(Error::new(
                            common.pos,
                            ErrorKind::DataError(format!("Node does not end at expected position (expected {}, now at {})", expected_pos, common.pos))))
                }
            } else {
                // Data is collapsed (an extra node end marker found).
                Err(Error::new(common.pos, ErrorKind::DataError("An extra node end marker found".to_string())))
            };
        } else {
            // Start of a node.
            self.end_offset_stack.push(node_record_header.end_offset);
        }

        // Read a node name.
        let name = try_read_fixstr!(common.pos, reader, node_record_header.name_len);

        // Read properties.
        let mut properties = Vec::<PropertyValue>::with_capacity(node_record_header.num_properties as usize);
        for _ in 0..node_record_header.num_properties {
            let prop = try!(self.read_property(reader, common));
            properties.push(prop);
        }

        Ok(FbxEvent::StartNode {
            name: name,
            properties: properties,
        })
    }

    fn read_property<R: Read>(&mut self, reader: &mut R, common: &mut CommonState) -> Result<PropertyValue> {
        let type_code = try_read_le_u8!(common.pos, reader);
        // type code must be ASCII.
        let type_code = if type_code > 0x80 {
            return Err(Error::new(common.pos-1, ErrorKind::DataError(format!("Expected property type code (ASCII) but got {:#x}", type_code))));
        } else {
            type_code as char
        };
        let value = match type_code {
            // 1 bit boolean (1: true, 0: false) encoded as the LSB of a 1 byte value.
            'C' => {
                let val = try_read_le_u8!(common.pos, reader);
                // It seems 'T' (0x54) is used as `false`, 'T' (0x59) is used as `true`.
                if (val != 'T' as u8) && (val != 'Y' as u8) {
                    // Should this treated as error?
                    // (I don't know whether other characters than 'T' and 'Y' are allowed...)
                    warn!("Expected 'T' or 'Y' for representaton of boolean property value, but got {:#x}", val);
                }
                // Check LSB.
                PropertyValue::Bool(val & 1 == 1)
            },
            // 2 byte signed integer.
            'Y' => {
                PropertyValue::I16(try_read_le_i16!(common.pos, reader))
            },
            // 4 byte signed integer.
            'I' => {
                PropertyValue::I32(try_read_le_i32!(common.pos, reader))
            },
            // 4 byte single-precision IEEE 754 floating-point number.
            'F' => {
                PropertyValue::F32(try_read_le_f32!(common.pos, reader))
            },
            // 8 byte double-precision IEEE 754 floating-point number.
            'D' => {
                PropertyValue::F64(try_read_le_f64!(common.pos, reader))
            },
            // 8 byte signed integer.
            'L' => {
                PropertyValue::I64(try_read_le_i64!(common.pos, reader))
            },
            // Array types
            'f'|'d'|'l'|'i'|'b' => {
                let array_header = try!(PropertyArrayHeader::read(reader, &mut common.pos));
                try!(self.read_property_value_array(reader, common, type_code, &array_header))
            },
            // String
            'S' => {
                let length = try_read_le_u32!(common.pos, reader);
                PropertyValue::String(try_read_fixstr!(common.pos, reader, length))
            },
            // Raw binary data
            'R' => {
                let length = try_read_le_u32!(common.pos, reader);
                PropertyValue::Binary(try_read_exact!(common.pos, reader, length))
            },
            _ => {
                return Err(Error::new(
                        common.pos,
                        ErrorKind::DataError(format!(
                                "Unsupported type code appears in node property: type_code={}({:#x})",
                                type_code, type_code as u8))));
            }
        };
        Ok(value)
    }

    /// Read property value of array type from given stream which maybe compressed.
    fn read_property_value_array<R: Read>(&mut self,
                                          reader: &mut R, common: &mut CommonState,
                                          type_code: char, array_header: &PropertyArrayHeader) -> Result<PropertyValue> {
        match array_header.encoding {
            // 0; raw
            0 => {
                let (val, byte_size) = try!(self.read_property_value_array_from_plain_stream(reader, common.pos, type_code, array_header.array_length));
                common.pos += byte_size;
                Ok(val)
            },
            // 1: zlib compressed data
            1 => {
                let mut decoded_stream = flate2::read::ZlibDecoder::new(reader.by_ref().take(array_header.compressed_length as u64));
                let (val, _) = try!(self.read_property_value_array_from_plain_stream(&mut decoded_stream, common.pos, type_code, array_header.array_length));
                common.pos += array_header.compressed_length as u64;
                Ok(val)
            },
            // Unknown.
            e => {
                Err(Error::new(
                        common.pos,
                        ErrorKind::DataError(format!("Unsupported property array encoding, got {:#x}", e))))
            }
        }
    }

    fn read_property_value_array_from_plain_stream<R: Read>(&mut self, reader: &mut R, abs_pos: u64, type_code: char,
                                                            num_elements: u32) -> Result<(PropertyValue, u64)> {
        use self::byteorder::{ReadBytesExt, LittleEndian};
        Ok(match type_code {
            // Array of 4 byte single-precision IEEE 754 floating-point number.
            'f' => {
                let mut data = Vec::<f32>::with_capacity(num_elements as usize);
                for _ in 0..num_elements {
                    data.push(try_with_pos!(abs_pos, reader.read_f32::<LittleEndian>()));
                }
                (PropertyValue::VecF32(data), num_elements as u64 * 4)
            },
            // Array of 8 byte double-precision IEEE 754 floating-point number.
            'd' => {
                let mut data = Vec::<f64>::with_capacity(num_elements as usize);
                for _ in 0..num_elements {
                    data.push(try_with_pos!(abs_pos, reader.read_f64::<LittleEndian>()));
                }
                (PropertyValue::VecF64(data), num_elements as u64 * 8)
            },
            // Array of 8 byte signed integer.
            'l' => {
                let mut data = Vec::<i64>::with_capacity(num_elements as usize);
                for _ in 0..num_elements {
                    data.push(try_with_pos!(abs_pos, reader.read_i64::<LittleEndian>()));
                }
                (PropertyValue::VecI64(data), num_elements as u64 * 8)
            },
            // Array of 4 byte signed integer.
            'i' => {
                let mut data = Vec::<i32>::with_capacity(num_elements as usize);
                for _ in 0..num_elements {
                    data.push(try_with_pos!(abs_pos, reader.read_i32::<LittleEndian>()));
                }
                (PropertyValue::VecI32(data), num_elements as u64 * 4)
            },
            // Array of 1 byte booleans (always 0 or 1?).
            'b' => {
                let mut data = Vec::<bool>::with_capacity(num_elements as usize);
                for _ in 0..num_elements {
                    // Check LSB.
                    data.push(try_with_pos!(abs_pos, reader.read_u8()) & 1 == 1);
                }
                (PropertyValue::VecBool(data), num_elements as u64)
            },
            _ => {
                // Unreachable because `read_property()` gives only 'f' , 'd', 'l', 'i', or 'b' to
                // `read_property_value_array()`.
                unreachable!();
            }
        })
    }
}

#[derive(Debug, Copy, Clone)]
struct NodeRecordHeader {
    end_offset: u32,
    num_properties: u32,
    property_list_len: u32,
    name_len: u8,
}

impl NodeRecordHeader {
    pub fn read<R: Read>(reader: &mut R, pos: &mut u64) -> Result<Self> {
        let end_offset = try_read_le_u32!(*pos, reader);
        let num_properties = try_read_le_u32!(*pos, reader);
        let property_list_len = try_read_le_u32!(*pos, reader);
        let name_len = try_read_le_u8!(*pos, reader);
        Ok(NodeRecordHeader {
            end_offset: end_offset,
            num_properties: num_properties,
            property_list_len: property_list_len,
            name_len: name_len,
        })
    }

    /// Check whether the header indicates there are no more children.
    pub fn is_null_record(&self) -> bool {
        self.end_offset == 0
            && self.num_properties == 0
            && self.property_list_len == 0
            && self.name_len == 0
    }
}

#[derive(Debug, Copy, Clone)]
pub struct PropertyArrayHeader {
    array_length: u32,
    encoding: u32,
    compressed_length: u32,
}

impl PropertyArrayHeader {
    pub fn read<R: Read>(reader: &mut R, pos: &mut u64) -> Result<Self> {
        let array_length = try_read_le_u32!(*pos, reader);
        let encoding = try_read_le_u32!(*pos, reader);
        let compressed_length = try_read_le_u32!(*pos, reader);
        Ok(PropertyArrayHeader {
            array_length: array_length,
            encoding: encoding,
            compressed_length: compressed_length,
        })
    }
}
<|endoftext|>


<commit_before>//! Implements the principal game engine functionality.

pub mod tt;
pub mod alpha_beta;
pub mod threading;

use std::thread;
use std::cmp::min;
use std::sync::Arc;
use std::sync::mpsc::{channel, Sender, Receiver};
use std::time::SystemTime;
use basetypes::*;
use chess_move::*;
use position::Position;
use self::tt::*;
use self::threading::*;

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

/// The half-with of the initial aspiration window in centipawns.
pub const INITIAL_ASPIRATION_WINDOW: Value = 17; // 16;

/// The number of nodes that will be searched without reporting search
/// progress.
///
/// If this value is too small the engine may become slow, if this
/// value is too big the engine may become unresponsive.
pub const NODE_COUNT_REPORT_INTERVAL: NodeCount = 10000;

pub struct TimeManagement {
    move_time: u64, // milliseconds
}

impl TimeManagement {
    #[allow(unused_variables)]
    pub fn new(us: Color,
               pondering_is_allowed: bool,
               wtime: Option<u64>,
               btime: Option<u64>,
               winc: Option<u64>,
               binc: Option<u64>,
               movestogo: Option<u64>)
               -> TimeManagement {
        // TODO: We ignore "pondering_is_allowed".

        let (time, inc) = if us == WHITE {
            (wtime, winc.unwrap_or(0))
        } else {
            (btime, binc.unwrap_or(0))
        };
        let time = time.unwrap_or(0);
        let movestogo = movestogo.unwrap_or(40);
        let movetime = (time + inc * movestogo) / movestogo;
        TimeManagement { move_time: min(movetime, time / 2) }
    }

    pub fn must_play(&self, search_status: &SearchStatus) -> bool {
        // TODO: Implement smarter time management.
        search_status.searched_time >= self.move_time
    }
}

pub struct SearchStatus {
    pub started_at: Option<SystemTime>,
    pub done: bool,
    pub depth: u8,
    pub value: Value,
    pub bound: BoundType,
    pub pv: Vec<Move>,
    pub searched_nodes: NodeCount,
    pub searched_time: u64, // milliseconds
    pub nps: u64, // nodes per second
}

/// Implements `UciEngine` trait.
pub struct MultipvSearch {
    tt: Arc<TranspositionTable>,
    position: Position,
    status: SearchStatus,

    // A handle to the search thread.
    search_thread: Option<thread::JoinHandle<()>>,

    // A channel for sending commands to the search thread.
    commands: Sender<Command>,

    // A channel for receiving reports from the search thread.
    reports: Receiver<Report>,
}

impl MultipvSearch {
    /// Creates a new instance.
    pub fn new(tt: Arc<TranspositionTable>) -> MultipvSearch {

        // Spawn the search thread.
        let (commands_tx, commands_rx) = channel();
        let (reports_tx, reports_rx) = channel();
        let tt_clone = tt.clone();
        let search_thread = thread::spawn(move || {
            serve_deepening(tt_clone, commands_rx, reports_tx);
        });

        MultipvSearch {
            tt: tt,
            search_thread: Some(search_thread),
            position: Position::from_fen("k7/8/8/8/8/8/8/7K w - - 0 1").ok().unwrap(),
            commands: commands_tx,
            reports: reports_rx,
            status: SearchStatus {
                started_at: None,
                done: true,
                depth: 0,
                value: VALUE_UNKNOWN,
                bound: BOUND_NONE,
                pv: vec![],
                searched_nodes: 0,
                searched_time: 0,
                nps: 0,
            },
        }
    }

    /// Starts a new search.
    #[allow(unused_variables)]
    pub fn start(&mut self, p: &Position, searchmoves: Option<Vec<String>>, pv_count: usize) {
        // TODO: We ignore the "pv_count" parameter.
        assert_eq!(pv_count, 1);

        // TODO: We ignore the "searchmoves" parameter.

        // TODO: Add `self.legal_moves_count` filed.

        self.stop();
        self.position = p.clone();
        self.status = SearchStatus {
            started_at: Some(SystemTime::now()),
            done: false,
            depth: 0,
            value: VALUE_UNKNOWN, // TODO: Set good initial value (-19999).
            bound: BOUND_NONE, // TODO: Set good initial value (BOUND_LOWER).
            pv: vec![], // TODO: Set good initial value (vec![best_move]).
            searched_nodes: 0,
            searched_time: 0,
            ..self.status
        };
        self.commands
            .send(Command::Search {
                search_id: 0,
                position: p.clone(),
                depth: MAX_DEPTH,
                lower_bound: -29999,
                upper_bound: 29999,
            })
            .unwrap();
    }

    /// Stops the current search.
    pub fn stop(&mut self) {
        if !self.status.done {
            self.commands.send(Command::Stop).unwrap();
            loop {
                if let Ok(Report::Done { .. }) = self.reports.recv() {
                    break;
                }
            }
            self.status.done = true;
        }
    }

    /// Stops the current search and joins the search thread.
    ///
    /// After calling `exit`, no other methods on this instance should
    /// be called.
    pub fn exit(&mut self) {
        self.commands.send(Command::Exit).unwrap();
        self.search_thread.take().unwrap().join().unwrap();
    }

    #[inline(always)]
    pub fn status(&self) -> &SearchStatus {
        &self.status
    }

    pub fn update_status(&mut self) -> &SearchStatus {
        while let Ok(report) = self.reports.try_recv() {
            match report {
                Report::Progress { searched_depth, searched_nodes, value, .. } => {
                    self.register_progress(searched_depth, searched_nodes, value);
                }
                Report::Done { .. } => {
                    self.status.done = true;
                }
            }
        }
        &self.status
    }

    // A helper method. It updates the search status info and makes
    // sure that a new PV is sent to the GUI for each newly reached
    // depth.
    fn register_progress(&mut self, depth: u8, searched_nodes: NodeCount, value: Value) {
        let thinking_duration = self.status.started_at.unwrap().elapsed().unwrap();
        self.status.searched_time = 1000 * thinking_duration.as_secs() +
                                    (thinking_duration.subsec_nanos() / 1000000) as u64;
        self.status.searched_nodes = searched_nodes;
        self.status.nps = 1000 * (self.status.nps + self.status.searched_nodes) /
                          (1000 + self.status.searched_time);
        if self.status.depth < depth || self.status.value != value {
            self.status.depth = depth;
            self.status.value = value;
            self.extract_pv(depth);
        }
    }

    // A helper method. It extracts the primary variation (PV) from
    // the transposition table (TT) and updates `status.current_pv`.
    //
    // **Note:** Because the PV is a moving target (the search
    // continues to run in parallel), imperfections in the reported
    // PVs are unavoidable. To deal with this, we turn a blind eye if
    // the value at the root of the PV differs from the value at the
    // leaf by no more than `EPSILON`.
    fn extract_pv(&mut self, depth: u8) {
        if depth == 0 {
            return;
        }

        // First: Extract the PV, the leaf value, the root value, and
        // the bound type from the TT.
        let mut p = self.position.clone();
        let mut our_turn = true;
        let mut prev_move = None;
        let mut pv = Vec::new();
        let mut leaf_value = -19999;
        let mut root_value = leaf_value;
        let mut bound = BOUND_LOWER;
        while let Some(entry) = self.tt.peek(p.hash()) {
            if entry.bound() != BOUND_NONE {
                // Get the value and the bound type. In half of the
                // cases the value stored in `entry` is from other
                // side's perspective.
                if our_turn {
                    leaf_value = entry.value();
                    bound = entry.bound();
                } else {
                    leaf_value = -entry.value();
                    bound = match entry.bound() {
                        BOUND_UPPER => BOUND_LOWER,
                        BOUND_LOWER => BOUND_UPPER,
                        x => x,
                    };
                }

                // The values under -19999 and over 19999 carry
                // information about in how many moves is the
                // inevitable checkmate. However, do not show this to
                // the user, because it is sometimes incorrect.
                if leaf_value >= 20000 {
                    leaf_value = 19999;
                    if bound == BOUND_LOWER {
                        bound = BOUND_EXACT
                    }
                }
                if leaf_value <= -20000 {
                    leaf_value = -19999;
                    if bound == BOUND_UPPER {
                        bound = BOUND_EXACT
                    }
                }

                if let Some(m) = prev_move {
                    // Extend the PV with the previous move.
                    pv.push(m);
                } else {
                    // We are at the root -- set the root value.
                    root_value = leaf_value;
                }

                if pv.len() < depth as usize && (leaf_value - root_value).abs() <= EPSILON {
                    if let Some(m) = p.try_move_digest(entry.move16()) {
                        if p.do_move(m) {
                            if bound == BOUND_EXACT {
                                // Extend the PV with one more move.
                                prev_move = Some(m);
                                our_turn = !our_turn;
                                continue;
                            } else {
                                // This is the last move in the PV.
                                pv.push(m);
                            }
                        }
                    }
                }
            }
            break;
        }

        // Second: Change the bound type if the leaf value in the PV
        // differs too much from the root value.
        bound = match leaf_value - root_value {
            x if x > EPSILON && bound != BOUND_UPPER => BOUND_LOWER,
            x if x < -EPSILON && bound != BOUND_LOWER => BOUND_UPPER,
            _ => bound,
        };

        // Third: Update `status`.
        self.status.value = root_value;
        self.status.bound = bound;
        self.status.pv = pv;
    }
}

// A sufficiently small value (in centipawns).
const EPSILON: Value = 8;
<commit_msg>make started_at field private<commit_after>//! Implements the principal game engine functionality.

pub mod tt;
pub mod alpha_beta;
pub mod threading;

use std::thread;
use std::cmp::min;
use std::sync::Arc;
use std::sync::mpsc::{channel, Sender, Receiver};
use std::time::SystemTime;
use basetypes::*;
use chess_move::*;
use position::Position;
use self::tt::*;
use self::threading::*;

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

/// The half-with of the initial aspiration window in centipawns.
pub const INITIAL_ASPIRATION_WINDOW: Value = 17; // 16;

/// The number of nodes that will be searched without reporting search
/// progress.
///
/// If this value is too small the engine may become slow, if this
/// value is too big the engine may become unresponsive.
pub const NODE_COUNT_REPORT_INTERVAL: NodeCount = 10000;

pub struct TimeManagement {
    move_time: u64, // milliseconds
}

impl TimeManagement {
    #[allow(unused_variables)]
    pub fn new(us: Color,
               pondering_is_allowed: bool,
               wtime: Option<u64>,
               btime: Option<u64>,
               winc: Option<u64>,
               binc: Option<u64>,
               movestogo: Option<u64>)
               -> TimeManagement {
        // TODO: We ignore "pondering_is_allowed".

        let (time, inc) = if us == WHITE {
            (wtime, winc.unwrap_or(0))
        } else {
            (btime, binc.unwrap_or(0))
        };
        let time = time.unwrap_or(0);
        let movestogo = movestogo.unwrap_or(40);
        let movetime = (time + inc * movestogo) / movestogo;
        TimeManagement { move_time: min(movetime, time / 2) }
    }

    pub fn must_play(&self, search_status: &SearchStatus) -> bool {
        // TODO: Implement smarter time management.
        search_status.searched_time >= self.move_time
    }
}

pub struct SearchStatus {
    started_at: Option<SystemTime>,
    pub done: bool,
    pub depth: u8,
    pub value: Value,
    pub bound: BoundType,
    pub pv: Vec<Move>,
    pub searched_nodes: NodeCount,
    pub searched_time: u64, // milliseconds
    pub nps: u64, // nodes per second
}

/// Implements `UciEngine` trait.
pub struct MultipvSearch {
    tt: Arc<TranspositionTable>,
    position: Position,
    status: SearchStatus,

    // A handle to the search thread.
    search_thread: Option<thread::JoinHandle<()>>,

    // A channel for sending commands to the search thread.
    commands: Sender<Command>,

    // A channel for receiving reports from the search thread.
    reports: Receiver<Report>,
}

impl MultipvSearch {
    /// Creates a new instance.
    pub fn new(tt: Arc<TranspositionTable>) -> MultipvSearch {

        // Spawn the search thread.
        let (commands_tx, commands_rx) = channel();
        let (reports_tx, reports_rx) = channel();
        let tt_clone = tt.clone();
        let search_thread = thread::spawn(move || {
            serve_deepening(tt_clone, commands_rx, reports_tx);
        });

        MultipvSearch {
            tt: tt,
            search_thread: Some(search_thread),
            position: Position::from_fen("k7/8/8/8/8/8/8/7K w - - 0 1").ok().unwrap(),
            commands: commands_tx,
            reports: reports_rx,
            status: SearchStatus {
                started_at: None,
                done: true,
                depth: 0,
                value: VALUE_UNKNOWN,
                bound: BOUND_NONE,
                pv: vec![],
                searched_nodes: 0,
                searched_time: 0,
                nps: 0,
            },
        }
    }

    /// Starts a new search.
    #[allow(unused_variables)]
    pub fn start(&mut self, p: &Position, searchmoves: Option<Vec<String>>, pv_count: usize) {
        // TODO: We ignore the "pv_count" parameter.
        assert_eq!(pv_count, 1);

        // TODO: We ignore the "searchmoves" parameter.

        // TODO: Add `self.legal_moves_count` filed.

        self.stop();
        self.position = p.clone();
        self.status = SearchStatus {
            started_at: Some(SystemTime::now()),
            done: false,
            depth: 0,
            value: VALUE_UNKNOWN, // TODO: Set good initial value (-19999).
            bound: BOUND_NONE, // TODO: Set good initial value (BOUND_LOWER).
            pv: vec![], // TODO: Set good initial value (vec![best_move]).
            searched_nodes: 0,
            searched_time: 0,
            ..self.status
        };
        self.commands
            .send(Command::Search {
                search_id: 0,
                position: p.clone(),
                depth: MAX_DEPTH,
                lower_bound: -29999,
                upper_bound: 29999,
            })
            .unwrap();
    }

    /// Stops the current search.
    pub fn stop(&mut self) {
        if !self.status.done {
            self.commands.send(Command::Stop).unwrap();
            loop {
                if let Ok(Report::Done { .. }) = self.reports.recv() {
                    break;
                }
            }
            self.status.done = true;
        }
    }

    /// Stops the current search and joins the search thread.
    ///
    /// After calling `exit`, no other methods on this instance should
    /// be called.
    pub fn exit(&mut self) {
        self.commands.send(Command::Exit).unwrap();
        self.search_thread.take().unwrap().join().unwrap();
    }

    #[inline(always)]
    pub fn status(&self) -> &SearchStatus {
        &self.status
    }

    pub fn update_status(&mut self) -> &SearchStatus {
        while let Ok(report) = self.reports.try_recv() {
            match report {
                Report::Progress { searched_depth, searched_nodes, value, .. } => {
                    self.register_progress(searched_depth, searched_nodes, value);
                }
                Report::Done { .. } => {
                    self.status.done = true;
                }
            }
        }
        &self.status
    }

    // A helper method. It updates the search status info and makes
    // sure that a new PV is sent to the GUI for each newly reached
    // depth.
    fn register_progress(&mut self, depth: u8, searched_nodes: NodeCount, value: Value) {
        let thinking_duration = self.status.started_at.unwrap().elapsed().unwrap();
        self.status.searched_time = 1000 * thinking_duration.as_secs() +
                                    (thinking_duration.subsec_nanos() / 1000000) as u64;
        self.status.searched_nodes = searched_nodes;
        self.status.nps = 1000 * (self.status.nps + self.status.searched_nodes) /
                          (1000 + self.status.searched_time);
        if self.status.depth < depth || self.status.value != value {
            self.status.depth = depth;
            self.status.value = value;
            self.extract_pv(depth);
        }
    }

    // A helper method. It extracts the primary variation (PV) from
    // the transposition table (TT) and updates `status.current_pv`.
    //
    // **Note:** Because the PV is a moving target (the search
    // continues to run in parallel), imperfections in the reported
    // PVs are unavoidable. To deal with this, we turn a blind eye if
    // the value at the root of the PV differs from the value at the
    // leaf by no more than `EPSILON`.
    fn extract_pv(&mut self, depth: u8) {
        if depth == 0 {
            return;
        }

        // First: Extract the PV, the leaf value, the root value, and
        // the bound type from the TT.
        let mut p = self.position.clone();
        let mut our_turn = true;
        let mut prev_move = None;
        let mut pv = Vec::new();
        let mut leaf_value = -19999;
        let mut root_value = leaf_value;
        let mut bound = BOUND_LOWER;
        while let Some(entry) = self.tt.peek(p.hash()) {
            if entry.bound() != BOUND_NONE {
                // Get the value and the bound type. In half of the
                // cases the value stored in `entry` is from other
                // side's perspective.
                if our_turn {
                    leaf_value = entry.value();
                    bound = entry.bound();
                } else {
                    leaf_value = -entry.value();
                    bound = match entry.bound() {
                        BOUND_UPPER => BOUND_LOWER,
                        BOUND_LOWER => BOUND_UPPER,
                        x => x,
                    };
                }

                // The values under -19999 and over 19999 carry
                // information about in how many moves is the
                // inevitable checkmate. However, do not show this to
                // the user, because it is sometimes incorrect.
                if leaf_value >= 20000 {
                    leaf_value = 19999;
                    if bound == BOUND_LOWER {
                        bound = BOUND_EXACT
                    }
                }
                if leaf_value <= -20000 {
                    leaf_value = -19999;
                    if bound == BOUND_UPPER {
                        bound = BOUND_EXACT
                    }
                }

                if let Some(m) = prev_move {
                    // Extend the PV with the previous move.
                    pv.push(m);
                } else {
                    // We are at the root -- set the root value.
                    root_value = leaf_value;
                }

                if pv.len() < depth as usize && (leaf_value - root_value).abs() <= EPSILON {
                    if let Some(m) = p.try_move_digest(entry.move16()) {
                        if p.do_move(m) {
                            if bound == BOUND_EXACT {
                                // Extend the PV with one more move.
                                prev_move = Some(m);
                                our_turn = !our_turn;
                                continue;
                            } else {
                                // This is the last move in the PV.
                                pv.push(m);
                            }
                        }
                    }
                }
            }
            break;
        }

        // Second: Change the bound type if the leaf value in the PV
        // differs too much from the root value.
        bound = match leaf_value - root_value {
            x if x > EPSILON && bound != BOUND_UPPER => BOUND_LOWER,
            x if x < -EPSILON && bound != BOUND_LOWER => BOUND_UPPER,
            _ => bound,
        };

        // Third: Update `status`.
        self.status.value = root_value;
        self.status.bound = bound;
        self.status.pv = pv;
    }
}

// A sufficiently small value (in centipawns).
const EPSILON: Value = 8;
<|endoftext|>


<commit_before>use std::mem;
use std::marker::PhantomData;
use super::SessionType;
use protocol::{Protocol, Handler, Defer, DeferFunc};

/// This trait effectively posits that a protocol which handles `T` must
/// additionally handle other types. If `T` is an `Accept<P, Q>` the
/// protocol must handle `P` *and* be an `Acceptor` of `Q`. If `T` is
/// a `Finally<P>` it must handle `P`.
pub trait Acceptor<I, E, T>: Protocol + Sized {
	fn defer(u8) -> Defer<Self, I>;
}
impl<I, E: SessionType, H: Protocol + Handler<I, E, P> + Acceptor<I, E, Q>, P: SessionType, Q: SessionType> Acceptor<I, E, Accept<P, Q>> for H {
	fn defer(num: u8) -> Defer<H, I> {
		if num == 0 {
			let next_func: DeferFunc<I, Self, E, P> = <Self as Handler<I, E, P>>::with;

			Defer(unsafe { mem::transmute(next_func) }, PhantomData, true)
		} else {
			<Self as Acceptor<I, E, Q>>::defer(num - 1)
		}
	}
}
impl<I, E: SessionType, H: Protocol + Handler<I, E, P>,                     P: SessionType>                 Acceptor<I, E, Finally<P>>   for H {
	fn defer(num: u8) -> Defer<H, I> {
		// regardless of num we cannot proceed further than Finally
		let next_func: DeferFunc<I, Self, E, P> = <Self as Handler<I, E, P>>::with;

		Defer(unsafe { mem::transmute(next_func) }, PhantomData, true)
	}
}

/// Choose from `P` or something in `Q`.
pub struct Choose<P: SessionType, Q: SessionType>(PhantomData<(P, Q)>);

unsafe impl<P: SessionType, Q: SessionType> SessionType for Choose<P, Q> {
	type Dual = Accept<P::Dual, Q::Dual>;
}

trait NotSame { }
impl NotSame for .. { }
impl<A> !NotSame for (A, A) { }

pub trait Chooser<T> {
	fn num() -> u8;
}

impl<P: SessionType, Q: SessionType> Chooser<P> for Choose<P, Q> {
	fn num() -> u8 { 0 }
}

impl<P: SessionType> Chooser<P> for Finally<P> {
	fn num() -> u8 { 0 }
}

impl<P: SessionType, S: SessionType, Q: SessionType + Chooser<S>> Chooser<S> for Choose<P, Q>
	where (S, P): NotSame
{
	fn num() -> u8 { 1 + Q::num() }
}

/// Accept either `P` or something in `Q`.
pub struct Accept<P: SessionType, Q: SessionType>(PhantomData<(P, Q)>);

unsafe impl<P: SessionType, Q: SessionType> SessionType for Accept<P, Q> {
	type Dual = Choose<P::Dual, Q::Dual>;
}

/// Finally choose `P`.
pub struct Finally<P: SessionType>(PhantomData<P>);

unsafe impl<P: SessionType> SessionType for Finally<P> {
	type Dual = Finally<P::Dual>;
}

#[test]
fn check_choose_works() {
	use super::{Recv, Eps};

	type GetUsize = Recv<usize, Eps>;
	type GetU8 = Recv<u8, Eps>;
	type GetString = Recv<String, Eps>;
	type Getisize = Recv<isize, Eps>;

	type Proto = Choose<Getisize, Choose<GetString, Choose<GetU8, Finally<GetUsize>>>>;

	assert_eq!(<Proto as Chooser<Getisize>>::num(), 0);
	assert_eq!(<Proto as Chooser<GetString>>::num(), 1);
	assert_eq!(<Proto as Chooser<GetU8>>::num(), 2);
	assert_eq!(<Proto as Chooser<GetUsize>>::num(), 3);
}<commit_msg>Remove warning.<commit_after>use std::mem;
use std::marker::PhantomData;
use super::SessionType;
use protocol::{Protocol, Handler, Defer, DeferFunc};

/// This trait effectively posits that a protocol which handles `T` must
/// additionally handle other types. If `T` is an `Accept<P, Q>` the
/// protocol must handle `P` *and* be an `Acceptor` of `Q`. If `T` is
/// a `Finally<P>` it must handle `P`.
pub trait Acceptor<I, E, T>: Protocol + Sized {
	fn defer(u8) -> Defer<Self, I>;
}
impl<I, E: SessionType, H: Protocol + Handler<I, E, P> + Acceptor<I, E, Q>, P: SessionType, Q: SessionType> Acceptor<I, E, Accept<P, Q>> for H {
	fn defer(num: u8) -> Defer<H, I> {
		if num == 0 {
			let next_func: DeferFunc<I, Self, E, P> = <Self as Handler<I, E, P>>::with;

			Defer(unsafe { mem::transmute(next_func) }, PhantomData, true)
		} else {
			<Self as Acceptor<I, E, Q>>::defer(num - 1)
		}
	}
}
impl<I, E: SessionType, H: Protocol + Handler<I, E, P>,                     P: SessionType>                 Acceptor<I, E, Finally<P>>   for H {
	fn defer(_: u8) -> Defer<H, I> {
		// regardless of num we cannot proceed further than Finally
		let next_func: DeferFunc<I, Self, E, P> = <Self as Handler<I, E, P>>::with;

		Defer(unsafe { mem::transmute(next_func) }, PhantomData, true)
	}
}

/// Choose from `P` or something in `Q`.
pub struct Choose<P: SessionType, Q: SessionType>(PhantomData<(P, Q)>);

unsafe impl<P: SessionType, Q: SessionType> SessionType for Choose<P, Q> {
	type Dual = Accept<P::Dual, Q::Dual>;
}

trait NotSame { }
impl NotSame for .. { }
impl<A> !NotSame for (A, A) { }

pub trait Chooser<T> {
	fn num() -> u8;
}

impl<P: SessionType, Q: SessionType> Chooser<P> for Choose<P, Q> {
	fn num() -> u8 { 0 }
}

impl<P: SessionType> Chooser<P> for Finally<P> {
	fn num() -> u8 { 0 }
}

impl<P: SessionType, S: SessionType, Q: SessionType + Chooser<S>> Chooser<S> for Choose<P, Q>
	where (S, P): NotSame
{
	fn num() -> u8 { 1 + Q::num() }
}

/// Accept either `P` or something in `Q`.
pub struct Accept<P: SessionType, Q: SessionType>(PhantomData<(P, Q)>);

unsafe impl<P: SessionType, Q: SessionType> SessionType for Accept<P, Q> {
	type Dual = Choose<P::Dual, Q::Dual>;
}

/// Finally choose `P`.
pub struct Finally<P: SessionType>(PhantomData<P>);

unsafe impl<P: SessionType> SessionType for Finally<P> {
	type Dual = Finally<P::Dual>;
}

#[test]
fn check_choose_works() {
	use super::{Recv, Eps};

	type GetUsize = Recv<usize, Eps>;
	type GetU8 = Recv<u8, Eps>;
	type GetString = Recv<String, Eps>;
	type Getisize = Recv<isize, Eps>;

	type Proto = Choose<Getisize, Choose<GetString, Choose<GetU8, Finally<GetUsize>>>>;

	assert_eq!(<Proto as Chooser<Getisize>>::num(), 0);
	assert_eq!(<Proto as Chooser<GetString>>::num(), 1);
	assert_eq!(<Proto as Chooser<GetU8>>::num(), 2);
	assert_eq!(<Proto as Chooser<GetUsize>>::num(), 3);
}<|endoftext|>


<commit_before>use std::iter;

pub struct KMP<'a> {
    r: usize,
    dfa: Vec<Vec<usize>>,
    pat: &'a str
}

impl<'a> KMP<'a> {
    // create the DFA from a string pattern
    pub fn new<'b>(pat: &'b str) -> KMP<'b> {
        let r = 256;
        let m = pat.len();
        let dfa = iter::repeat(iter::repeat(0).take(m).collect::<Vec<usize>>())
            .take(r).collect();

        let mut ret = KMP {
            r: r,
            dfa: dfa,
            pat: pat
        };
        ret.build_dfa();
        ret
    }

    fn build_dfa(&mut self) {
        let m = self.pat.len();
        let r = self.r;
        self.dfa[self.pat.char_at(0) as usize][0] = 1;
        let mut x = 0;
        for j in 1 .. m {
            for c in 0 .. r {
                self.dfa[c][j] = self.dfa[c][x]; // copy mismatch cases
            }
            self.dfa[self.pat.char_at(j) as usize][j] = j+1; // set match case
            x = self.dfa[self.pat.char_at(j) as usize][x];
        }
    }

    pub fn search(&self, txt: &str) -> Option<usize> {
        let m = self.pat.len();
        let n = txt.len();
        let mut i = 0;
        let mut j = 0;
        while i < n && j < m {
            j = self.dfa[txt.char_at(i) as usize][j];
            i += 1;
        }
        if j == m {
            Some(i-m)
        } else {
            None
        }
    }
}

#[test]
fn test_kmp() {
    let pat = "abracadabra";
    let text = "abacadabrabracabracadabrabrabracad";
    let kmp = KMP::new(pat);
    assert!(kmp.search(text).map_or(false, |pos| text[pos..].starts_with(pat)));
}
<commit_msg>substring_search: implement BoyerMoore for string<commit_after>use std::iter;

// FIXME: only supports extended-ASCII
/// searches for the pattern in the input text using the
/// KMP algorithm.
pub struct KMP<'a> {
    r: usize,
    dfa: Vec<Vec<usize>>,
    pat: &'a str
}

impl<'a> KMP<'a> {
    // create the DFA from a string pattern
    pub fn new<'b>(pat: &'b str) -> KMP<'b> {
        let r = 256;
        let m = pat.len();
        let dfa = iter::repeat(iter::repeat(0).take(m).collect::<Vec<usize>>())
            .take(r).collect();

        let mut ret = KMP {
            r: r,
            dfa: dfa,
            pat: pat
        };
        ret.build_dfa();
        ret
    }

    fn build_dfa(&mut self) {
        let m = self.pat.len();
        let r = self.r;
        self.dfa[self.pat.char_at(0) as usize][0] = 1;
        let mut x = 0;
        for j in 1 .. m {
            for c in 0 .. r {
                self.dfa[c][j] = self.dfa[c][x]; // copy mismatch cases
            }
            self.dfa[self.pat.char_at(j) as usize][j] = j+1; // set match case
            x = self.dfa[self.pat.char_at(j) as usize][x];   // update restart state
        }
    }

    pub fn search(&self, txt: &str) -> Option<usize> {
        let m = self.pat.len();
        let n = txt.len();
        let mut i = 0;
        let mut j = 0;
        while i < n && j < m {
            j = self.dfa[txt.char_at(i) as usize][j];
            i += 1;
        }
        if j == m {
            Some(i-m)
        } else {
            None
        }
    }
}

#[test]
fn test_kmp() {
    let pat = "abracadabra";
    let text = "abacadabrabracabracadabrabrabracad";
    let kmp = KMP::new(pat);
    assert!(kmp.search(text).map_or(false, |pos| text[pos..].starts_with(pat)));
    assert_eq!(kmp.search("zzzzz"), None);
}

/// searches for the pattern in the input text using the
/// bad-character rule part of the Boyer-Moore algorithm.
pub struct BoyerMoore<'a> {
    r: usize,
    right: Vec<isize>,
    pat: &'a str
}

impl<'a> BoyerMoore<'a> {
     pub fn new<'b>(pat: &'b str) -> BoyerMoore<'b> {
         let r = 256;
         let mut ret = BoyerMoore {
             r: r,
             right: Vec::new(),
             pat: pat
         };
         ret.init();
         ret
     }

    fn init(&mut self) {
        let r = self.r;
        self.right = iter::repeat(-1).take(r).collect();
        for j in 0 .. self.pat.len() {
            self.right[self.pat.char_at(j) as usize] = j as isize;
        }
    }

    pub fn search(&self, txt: &str) -> Option<usize> {
        let m = self.pat.len();
        let n = txt.len();
        if n < m {
            return None;
        }
        let mut skip;
        let mut i = 0;
        while i <= n-m {
            skip = 0;
            for j in (0 .. m).rev() {
                if self.pat.char_at(j) != txt.char_at(i+j) {
                    skip = j as isize - self.right[txt.char_at(i+j) as usize];
                    if skip < 1 {
                        skip = 1;
                    }
                    break;
                }
            }
            if skip == 0 {
                return Some(i);
            }
            i += skip as usize;
        }
        return None;
    }
}

#[test]
fn test_boyer_moore() {
    let pat = "abracadabra";
    let text = "abacadabrabracabracadabrabrabracad";
    let bm = BoyerMoore::new(pat);
    assert!(bm.search(text).map_or(false, |pos| text[pos..].starts_with(pat)));
    assert_eq!(bm.search("zzzzz"), None);
}
<|endoftext|>


<commit_before>pub type Color = [u8; 4];

#[derive(Clone, Copy, Debug, Default)]
struct GradientPoint {
    pos: f64,
    color: Color,
}

#[derive(Clone, Copy, Debug, Default)]
struct GradientDomain {
    min: f64,
    max: f64,
}

impl GradientDomain {
    pub fn new(min: f64, max: f64) -> Self {
        Self { min, max }
    }

    pub fn set_min(&mut self, min: f64) {
        self.min = min;
    }

    pub fn set_max(&mut self, max: f64) {
        self.max = max;
    }
}

#[derive(Clone, Debug, Default)]
pub struct ColorGradient {
    gradient_points: Vec<GradientPoint>,
    domain: GradientDomain,
}

impl ColorGradient {
    pub fn new() -> Self {
        let gradient = Self {
            gradient_points: Vec::new(),
            domain: GradientDomain::new(0.0, 1.0),
        };

        gradient.build_grayscale_gradient()
    }

    pub fn add_gradient_point(mut self, pos: f64, color: Color) -> Self {
        let new_point = GradientPoint { pos, color };

        // first check to see if the position is within the domain of the gradient. if the position
        // is not within the domain, expand the domain and add the GradientPoint
        if self.domain.min > pos {
            self.domain.set_min(pos);
            // since the new position is the smallest value, insert it at the beginning of the
            // gradient
            self.gradient_points.insert(0, new_point);
        } else if self.domain.max < pos {
            self.domain.set_max(pos);

            // since the new position is at the largest value, insert it at the end of the gradient
            self.gradient_points.push(new_point)
        } else if !self // new point must be somewhere inside the existing domain. Check to see if
            // it doesn't exist already
            .gradient_points
            .iter()
            .any(|&x| (x.pos - pos).abs() < f64::EPSILON)
        {
            // it doesn't, so find the correct position to insert the new
            // control point.
            let insertion_point = self.find_insertion_point(pos);

            // add the new control point at the correct position.
            self.gradient_points.insert(insertion_point, new_point);
        }

        self
    }

    fn find_insertion_point(&self, pos: f64) -> usize {
        self.gradient_points
            .iter()
            .position(|x| x.pos >= pos)
            .unwrap_or_else(|| self.gradient_points.len())
    }

    pub fn clear_gradient(mut self) -> Self {
        self.gradient_points.clear();

        self
    }

    pub fn build_grayscale_gradient(self) -> Self {
        self.clear_gradient()
            .add_gradient_point(-1.0, [0, 0, 0, 255])
            .add_gradient_point(1.0, [255, 255, 255, 255])
    }

    #[rustfmt::skip]
    pub fn build_terrain_gradient(self) -> Self {
        self.clear_gradient()
            .add_gradient_point(-1.00,              [  0,   0,   0, 255])
            .add_gradient_point(-256.0 / 16384.0,   [  6,  58, 127, 255])
            .add_gradient_point(-1.0 / 16384.0,     [ 14, 112, 192, 255])
            .add_gradient_point(0.0,                [ 70, 120,  60, 255])
            .add_gradient_point(1024.0 / 16384.0,   [110, 140,  75, 255])
            .add_gradient_point(2048.0 / 16384.0,   [160, 140, 111, 255])
            .add_gradient_point(3072.0 / 16384.0,   [184, 163, 141, 255])
            .add_gradient_point(4096.0 / 16384.0,   [128, 128, 128, 255])
            .add_gradient_point(5632.0 / 16384.0,   [128, 128, 128, 255])
            .add_gradient_point(6144.0 / 16384.0,   [250, 250, 250, 255])
            .add_gradient_point(1.0,                [255, 255, 255, 255])
    }

    pub fn build_rainbow_gradient(self) -> Self {
        self.clear_gradient()
            .add_gradient_point(-1.0, [255, 0, 0, 255])
            .add_gradient_point(-0.7, [255, 255, 0, 255])
            .add_gradient_point(-0.4, [0, 255, 0, 255])
            .add_gradient_point(0.0, [0, 255, 255, 255])
            .add_gradient_point(0.3, [0, 0, 255, 255])
            .add_gradient_point(0.6, [255, 0, 255, 255])
            .add_gradient_point(1.0, [255, 0, 0, 255])
    }

    pub fn get_color(&self, pos: f64) -> Color {
        let mut color = [0; 4];

        if pos < self.domain.min {
            color = self.gradient_points.first().unwrap().color
        } else if pos > self.domain.max {
            color = self.gradient_points.last().unwrap().color
        } else {
            for points in self.gradient_points.windows(2) {
                if (points[0].pos <= pos) && (points[1].pos > pos) {
                    // Compute the alpha value used for linear interpolation
                    let alpha = (pos - points[0].pos) / (points[1].pos - points[0].pos);

                    // Now perform the linear interpolation and return.
                    color = linerp_color(points[0].color, points[1].color, alpha)
                }
            }
        };

        color
    }
}

fn blend_channels(channel0: u8, channel1: u8, alpha: f64) -> u8 {
    let c0 = (f64::from(channel0)) / 255.0;
    let c1 = (f64::from(channel1)) / 255.0;

    (((c1 * alpha) + (c0 * (1.0 - alpha))) * 255.0) as u8
}

fn linerp_color(color0: Color, color1: Color, alpha: f64) -> Color {
    let r = blend_channels(color0[0], color1[0], alpha);
    let g = blend_channels(color0[1], color1[1], alpha);
    let b = blend_channels(color0[2], color1[2], alpha);
    let a = blend_channels(color0[3], color1[3], alpha);

    [r, g, b, a]
}

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

    #[test]
    fn blend_channels_min() {
        let result = blend_channels(0, 255, 0.0);
        assert_eq!(
            0, result,
            "blend_channels should've created 0, produced `{}` instead",
            result
        );
    }

    #[test]
    fn blend_channels_mid() {
        let result = blend_channels(0, 255, 0.5);
        assert_eq!(
            127, result,
            "blend_channels should've created 127, produced `{}` instead",
            result
        );
    }

    #[test]
    fn blend_channels_max() {
        let result = blend_channels(0, 255, 1.0);
        assert_eq!(
            255, result,
            "blend_channels should've created 255, produced `{}` instead",
            result
        );
    }

    #[test]
    fn linerp_color_1() {
        assert_eq!(
            [0, 127, 255, 0],
            linerp_color([0, 0, 255, 0], [0, 255, 255, 0], 0.5)
        );
    }

    #[test]
    fn color_gradient_1() {
        let gradient = ColorGradient::new();

        let gradient = gradient
            .clear_gradient()
            .add_gradient_point(0.0, [0, 0, 0, 0])
            .add_gradient_point(1.0, [255, 255, 255, 255]);

        assert_eq!([127, 127, 127, 127], gradient.get_color(0.5));
    }
}
<commit_msg>Some more cleanup and reworking<commit_after>pub type Color = [u8; 4];

#[derive(Clone, Copy, Debug, Default)]
struct GradientPoint {
    pos: f64,
    color: Color,
}

#[derive(Clone, Copy, Debug, Default)]
struct GradientDomain {
    min: f64,
    max: f64,
}

impl GradientDomain {
    pub fn new(min: f64, max: f64) -> Self {
        Self { min, max }
    }

    pub fn set_min(&mut self, min: f64) {
        self.min = min;
    }

    pub fn set_max(&mut self, max: f64) {
        self.max = max;
    }
}

#[derive(Clone, Debug, Default)]
pub struct ColorGradient {
    gradient_points: Vec<GradientPoint>,
    domain: GradientDomain,
}

impl ColorGradient {
    pub fn new() -> Self {
        let gradient = Self {
            gradient_points: Vec::new(),
            domain: GradientDomain::new(0.0, 1.0),
        };

        gradient.build_grayscale_gradient()
    }

    pub fn add_gradient_point(mut self, pos: f64, color: Color) -> Self {
        let new_point = GradientPoint { pos, color };

        // first check to see if the position is within the domain of the gradient. if the position
        // is not within the domain, expand the domain and add the GradientPoint
        if self.domain.min > pos {
            self.domain.set_min(pos);
            // since the new position is the smallest value, insert it at the beginning of the
            // gradient
            self.gradient_points.insert(0, new_point);
        } else if self.domain.max < pos {
            self.domain.set_max(pos);

            // since the new position is at the largest value, insert it at the end of the gradient
            self.gradient_points.push(new_point)
        } else if !self // new point must be somewhere inside the existing domain. Check to see if
            // it doesn't exist already
            .gradient_points
            .iter()
            .any(|&x| (x.pos - pos).abs() < f64::EPSILON)
        {
            // it doesn't, so find the correct position to insert the new
            // control point.
            let insertion_point = self.find_insertion_point(pos);

            // add the new control point at the correct position.
            self.gradient_points.insert(insertion_point, new_point);
        }

        self
    }

    fn find_insertion_point(&self, pos: f64) -> usize {
        self.gradient_points
            .iter()
            .position(|x| x.pos >= pos)
            .unwrap_or_else(|| self.gradient_points.len())
    }

    pub fn clear_gradient(mut self) -> Self {
        self.gradient_points.clear();
        self.domain = GradientDomain::new(0.0, 0.0);

        self
    }

    pub fn build_grayscale_gradient(self) -> Self {
        self.clear_gradient()
            .add_gradient_point(-1.0, [0, 0, 0, 255])
            .add_gradient_point(1.0, [255, 255, 255, 255])
    }

    #[rustfmt::skip]
    pub fn build_terrain_gradient(self) -> Self {
        self.clear_gradient()
            .add_gradient_point(-1.00,              [  0,   0,   0, 255])
            .add_gradient_point(-256.0 / 16384.0,   [  6,  58, 127, 255])
            .add_gradient_point(-1.0 / 16384.0,     [ 14, 112, 192, 255])
            .add_gradient_point(0.0,                [ 70, 120,  60, 255])
            .add_gradient_point(1024.0 / 16384.0,   [110, 140,  75, 255])
            .add_gradient_point(2048.0 / 16384.0,   [160, 140, 111, 255])
            .add_gradient_point(3072.0 / 16384.0,   [184, 163, 141, 255])
            .add_gradient_point(4096.0 / 16384.0,   [128, 128, 128, 255])
            .add_gradient_point(5632.0 / 16384.0,   [128, 128, 128, 255])
            .add_gradient_point(6144.0 / 16384.0,   [250, 250, 250, 255])
            .add_gradient_point(1.0,                [255, 255, 255, 255])
    }

    #[rustfmt::skip]
    pub fn build_rainbow_gradient(self) -> Self {
        self.clear_gradient()
            .add_gradient_point(-1.0, [255,   0,   0, 255])
            .add_gradient_point(-0.7, [255, 255,   0, 255])
            .add_gradient_point(-0.4, [  0, 255,   0, 255])
            .add_gradient_point( 0.0, [  0, 255, 255, 255])
            .add_gradient_point( 0.3, [  0,   0, 255, 255])
            .add_gradient_point( 0.6, [255,   0, 255, 255])
            .add_gradient_point( 1.0, [255,   0,   0, 255])
    }

    pub fn get_color(&self, pos: f64) -> Color {
        let mut color = Color::default();

        // If there are no colors in the gradient, return black
        return if self.gradient_points.is_empty() {
            color
        } else {
            match () {
                _ if pos < self.domain.min => color = self.gradient_points.first().unwrap().color,
                _ if pos > self.domain.max => color = self.gradient_points.last().unwrap().color,
                _ => {
                    for points in self.gradient_points.windows(2) {
                        if (points[0].pos <= pos) && (points[1].pos > pos) {
                            // Compute the alpha value used for linear interpolation
                            let alpha = (pos - points[0].pos) / (points[1].pos - points[0].pos);

                            // Now perform the interpolation and return.
                            color = interpolate_color(points[0].color, points[1].color, alpha)
                        }
                    }
                }
            };

            color
        };
    }
}

fn interpolate_color(color0: Color, color1: Color, alpha: f64) -> Color {
    fn blend_channel(channel0: u8, channel1: u8, alpha: f64) -> u8 {
        let c0 = (f64::from(channel0)) / 255.0;
        let c1 = (f64::from(channel1)) / 255.0;

        ((c1 - c0).mul_add(alpha, c0) * 255.0) as u8
    }

    let mut color = Color::default();

    for i in 0..color.len() {
        color[i] = blend_channel(color0[i], color1[i], alpha);
    }

    color
}

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

    #[test]
    fn linerp_color_1() {
        assert_eq!(
            [0, 127, 255, 0],
            interpolate_color([0, 0, 255, 0], [0, 255, 255, 0], 0.5)
        );
    }

    #[test]
    fn color_gradient_1() {
        let gradient = ColorGradient::new();

        let gradient = gradient
            .clear_gradient()
            .add_gradient_point(0.0, [0, 0, 0, 0])
            .add_gradient_point(1.0, [255, 255, 255, 255]);

        assert_eq!([127, 127, 127, 127], gradient.get_color(0.5));
    }
}
<|endoftext|>