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

pub mod alpha_beta;
pub mod threading;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        self.start_aspirated_search();
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

        self.start_deeper_search();
    }

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

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

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

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

pub mod alpha_beta;
pub mod threading;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        self.start_aspirated_search();
    }

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

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

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

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

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

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

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

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

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

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

impl DeepeningSearcher {
    /// A helper method. It tells `self.searcher` to run a new search.
    fn start_deeper_search(&mut self) {
        self.depth += 1;
        let value = if self.depth < 5 {
            // During the first few iterations the evaluation is
            // unreliable, and therefore we should not pass it to the
            // aspiration searcher.
            VALUE_UNKNOWN
        } else {
            self.value
        };
        self.searcher.start_search(SearchParams {
            search_id: 0,
            depth: self.depth,
            value: value,
            ..self.params.clone()
        });
    }
}

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

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

        self.start_deeper_search();
    }

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

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

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

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


<commit_before>use rustc::lint::*;
use syntax::codemap::mk_sp;
use syntax::ast;
use utils::{differing_macro_contexts, in_macro, snippet_opt, span_note_and_lint};
use syntax::ptr::P;

/// **What it does:** Checks for use of the non-existent `=*`, `=!` and `=-` operators.
///
/// **Why is this bad?** This is either a typo of `*=`, `!=` or `-=` or confusing.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust,ignore
/// a =- 42; // confusing, should it be `a -= 42` or `a = -42`?
/// ```
declare_lint! {
    pub SUSPICIOUS_ASSIGNMENT_FORMATTING,
    Warn,
    "suspicious formatting of `*=`, `-=` or `!=`"
}

/// **What it does:** Checks for formatting of `else if`. It lints if the `else`
/// and `if` are not on the same line or the `else` seems to be missing.
///
/// **Why is this bad?** This is probably some refactoring remnant, even if the
/// code is correct, it might look confusing.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust,ignore
/// if foo {
/// } if bar { // looks like an `else` is missing here
/// }
///
/// if foo {
/// } else
///
/// if bar { // this is the `else` block of the previous `if`, but should it be?
/// }
/// ```
declare_lint! {
    pub SUSPICIOUS_ELSE_FORMATTING,
    Warn,
    "suspicious formatting of `else if`"
}

/// **What it does:** Checks for possible missing comma in an array. It lints if
/// an array element is a binary operator expression and it lies on two lines.
///
/// **Why is this bad?** This could lead to unexpected results.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust,ignore
/// let a = &[
///     -1, -2, -3 // <= no coma here
///     -4, -5, -6
/// ];
/// ```
declare_lint! {
    pub POSSIBLE_MISSING_COMMA,
    Warn,
    "possible missing comma in array"
}

#[derive(Copy,Clone)]
pub struct Formatting;

impl LintPass for Formatting {
    fn get_lints(&self) -> LintArray {
        lint_array![SUSPICIOUS_ASSIGNMENT_FORMATTING, SUSPICIOUS_ELSE_FORMATTING, POSSIBLE_MISSING_COMMA]
    }
}

impl EarlyLintPass for Formatting {
    fn check_block(&mut self, cx: &EarlyContext, block: &ast::Block) {
        for w in block.stmts.windows(2) {
            match (&w[0].node, &w[1].node) {
                (&ast::StmtKind::Expr(ref first), &ast::StmtKind::Expr(ref second)) |
                (&ast::StmtKind::Expr(ref first), &ast::StmtKind::Semi(ref second)) => {
                    check_consecutive_ifs(cx, first, second);
                },
                _ => (),
            }
        }
    }

    fn check_expr(&mut self, cx: &EarlyContext, expr: &ast::Expr) {
        check_assign(cx, expr);
        check_else_if(cx, expr);
        check_array(cx, expr);
    }
}

/// Implementation of the `SUSPICIOUS_ASSIGNMENT_FORMATTING` lint.
fn check_assign(cx: &EarlyContext, expr: &ast::Expr) {
    if let ast::ExprKind::Assign(ref lhs, ref rhs) = expr.node {
        if !differing_macro_contexts(lhs.span, rhs.span) && !in_macro(cx, lhs.span) {
            let eq_span = mk_sp(lhs.span.hi, rhs.span.lo);

            if let ast::ExprKind::Unary(op, ref sub_rhs) = rhs.node {
                if let Some(eq_snippet) = snippet_opt(cx, eq_span) {
                    let op = ast::UnOp::to_string(op);
                    let eqop_span = mk_sp(lhs.span.hi, sub_rhs.span.lo);
                    if eq_snippet.ends_with('=') {
                        span_note_and_lint(cx,
                                           SUSPICIOUS_ASSIGNMENT_FORMATTING,
                                           eqop_span,
                                           &format!("this looks like you are trying to use `.. {op}= ..`, but you \
                                                     really are doing `.. = ({op} ..)`",
                                                    op = op),
                                           eqop_span,
                                           &format!("to remove this lint, use either `{op}=` or `= {op}`", op = op));
                    }
                }
            }
        }
    }
}

/// Implementation of the `SUSPICIOUS_ELSE_FORMATTING` lint for weird `else if`.
fn check_else_if(cx: &EarlyContext, expr: &ast::Expr) {
    if let Some((then, &Some(ref else_))) = unsugar_if(expr) {
        if unsugar_if(else_).is_some() && !differing_macro_contexts(then.span, else_.span) && !in_macro(cx, then.span) {
            // this will be a span from the closing ‘}’ of the “then” block (excluding) to the
            // “if” of the “else if” block (excluding)
            let else_span = mk_sp(then.span.hi, else_.span.lo);

            // the snippet should look like " else \n    " with maybe comments anywhere
            // it’s bad when there is a ‘\n’ after the “else”
            if let Some(else_snippet) = snippet_opt(cx, else_span) {
                let else_pos = else_snippet.find("else").expect("there must be a `else` here");

                if else_snippet[else_pos..].contains('\n') {
                    span_note_and_lint(cx,
                                       SUSPICIOUS_ELSE_FORMATTING,
                                       else_span,
                                       "this is an `else if` but the formatting might hide it",
                                       else_span,
                                       "to remove this lint, remove the `else` or remove the new line between `else` \
                                        and `if`");
                }
            }
        }
    }
}

/// Implementation of the `POSSIBLE_MISSING_COMMA_IN_ARRAY_FORMATTING` lint for array
fn check_array(cx: &EarlyContext, expr: &ast::Expr) {
    if let ast::ExprKind::Array(ref array) = expr.node {
        for element in array {
            if let ast::ExprKind::Binary(ref op, ref lhs, _) = element.node {
                if !differing_macro_contexts(lhs.span, op.span) {
                    let space_span = mk_sp(lhs.span.hi, op.span.lo);
                    if let Some(space_snippet) = snippet_opt(cx, space_span) {
                        let lint_span = mk_sp(lhs.span.hi, lhs.span.hi);
                        if space_snippet.contains('\n') {
                            span_note_and_lint(cx,
                                               POSSIBLE_MISSING_COMMA,
                                               lint_span,
                                               "possibly missing a comma here",
                                               lint_span,
                                               "to remove this lint, add a comma or write the expr in a single line");
                        }
                    }
                }
            }
        }
    }
}

/// Implementation of the `SUSPICIOUS_ELSE_FORMATTING` lint for consecutive ifs.
fn check_consecutive_ifs(cx: &EarlyContext, first: &ast::Expr, second: &ast::Expr) {
    if !differing_macro_contexts(first.span, second.span) && !in_macro(cx, first.span) &&
       unsugar_if(first).is_some() && unsugar_if(second).is_some() {
        // where the else would be
        let else_span = mk_sp(first.span.hi, second.span.lo);

        if let Some(else_snippet) = snippet_opt(cx, else_span) {
            if !else_snippet.contains('\n') {
                span_note_and_lint(cx,
                                   SUSPICIOUS_ELSE_FORMATTING,
                                   else_span,
                                   "this looks like an `else if` but the `else` is missing",
                                   else_span,
                                   "to remove this lint, add the missing `else` or add a new line before the second \
                                    `if`");
            }
        }
    }
}

/// Match `if` or `if let` expressions and return the `then` and `else` block.
fn unsugar_if(expr: &ast::Expr) -> Option<(&P<ast::Block>, &Option<P<ast::Expr>>)> {
    match expr.node {
        ast::ExprKind::If(_, ref then, ref else_) |
        ast::ExprKind::IfLet(_, _, ref then, ref else_) => Some((then, else_)),
        _ => None,
    }
}
<commit_msg>Fix lint name in comment too<commit_after>use rustc::lint::*;
use syntax::codemap::mk_sp;
use syntax::ast;
use utils::{differing_macro_contexts, in_macro, snippet_opt, span_note_and_lint};
use syntax::ptr::P;

/// **What it does:** Checks for use of the non-existent `=*`, `=!` and `=-` operators.
///
/// **Why is this bad?** This is either a typo of `*=`, `!=` or `-=` or confusing.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust,ignore
/// a =- 42; // confusing, should it be `a -= 42` or `a = -42`?
/// ```
declare_lint! {
    pub SUSPICIOUS_ASSIGNMENT_FORMATTING,
    Warn,
    "suspicious formatting of `*=`, `-=` or `!=`"
}

/// **What it does:** Checks for formatting of `else if`. It lints if the `else`
/// and `if` are not on the same line or the `else` seems to be missing.
///
/// **Why is this bad?** This is probably some refactoring remnant, even if the
/// code is correct, it might look confusing.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust,ignore
/// if foo {
/// } if bar { // looks like an `else` is missing here
/// }
///
/// if foo {
/// } else
///
/// if bar { // this is the `else` block of the previous `if`, but should it be?
/// }
/// ```
declare_lint! {
    pub SUSPICIOUS_ELSE_FORMATTING,
    Warn,
    "suspicious formatting of `else if`"
}

/// **What it does:** Checks for possible missing comma in an array. It lints if
/// an array element is a binary operator expression and it lies on two lines.
///
/// **Why is this bad?** This could lead to unexpected results.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust,ignore
/// let a = &[
///     -1, -2, -3 // <= no coma here
///     -4, -5, -6
/// ];
/// ```
declare_lint! {
    pub POSSIBLE_MISSING_COMMA,
    Warn,
    "possible missing comma in array"
}

#[derive(Copy,Clone)]
pub struct Formatting;

impl LintPass for Formatting {
    fn get_lints(&self) -> LintArray {
        lint_array![SUSPICIOUS_ASSIGNMENT_FORMATTING, SUSPICIOUS_ELSE_FORMATTING, POSSIBLE_MISSING_COMMA]
    }
}

impl EarlyLintPass for Formatting {
    fn check_block(&mut self, cx: &EarlyContext, block: &ast::Block) {
        for w in block.stmts.windows(2) {
            match (&w[0].node, &w[1].node) {
                (&ast::StmtKind::Expr(ref first), &ast::StmtKind::Expr(ref second)) |
                (&ast::StmtKind::Expr(ref first), &ast::StmtKind::Semi(ref second)) => {
                    check_consecutive_ifs(cx, first, second);
                },
                _ => (),
            }
        }
    }

    fn check_expr(&mut self, cx: &EarlyContext, expr: &ast::Expr) {
        check_assign(cx, expr);
        check_else_if(cx, expr);
        check_array(cx, expr);
    }
}

/// Implementation of the `SUSPICIOUS_ASSIGNMENT_FORMATTING` lint.
fn check_assign(cx: &EarlyContext, expr: &ast::Expr) {
    if let ast::ExprKind::Assign(ref lhs, ref rhs) = expr.node {
        if !differing_macro_contexts(lhs.span, rhs.span) && !in_macro(cx, lhs.span) {
            let eq_span = mk_sp(lhs.span.hi, rhs.span.lo);

            if let ast::ExprKind::Unary(op, ref sub_rhs) = rhs.node {
                if let Some(eq_snippet) = snippet_opt(cx, eq_span) {
                    let op = ast::UnOp::to_string(op);
                    let eqop_span = mk_sp(lhs.span.hi, sub_rhs.span.lo);
                    if eq_snippet.ends_with('=') {
                        span_note_and_lint(cx,
                                           SUSPICIOUS_ASSIGNMENT_FORMATTING,
                                           eqop_span,
                                           &format!("this looks like you are trying to use `.. {op}= ..`, but you \
                                                     really are doing `.. = ({op} ..)`",
                                                    op = op),
                                           eqop_span,
                                           &format!("to remove this lint, use either `{op}=` or `= {op}`", op = op));
                    }
                }
            }
        }
    }
}

/// Implementation of the `SUSPICIOUS_ELSE_FORMATTING` lint for weird `else if`.
fn check_else_if(cx: &EarlyContext, expr: &ast::Expr) {
    if let Some((then, &Some(ref else_))) = unsugar_if(expr) {
        if unsugar_if(else_).is_some() && !differing_macro_contexts(then.span, else_.span) && !in_macro(cx, then.span) {
            // this will be a span from the closing ‘}’ of the “then” block (excluding) to the
            // “if” of the “else if” block (excluding)
            let else_span = mk_sp(then.span.hi, else_.span.lo);

            // the snippet should look like " else \n    " with maybe comments anywhere
            // it’s bad when there is a ‘\n’ after the “else”
            if let Some(else_snippet) = snippet_opt(cx, else_span) {
                let else_pos = else_snippet.find("else").expect("there must be a `else` here");

                if else_snippet[else_pos..].contains('\n') {
                    span_note_and_lint(cx,
                                       SUSPICIOUS_ELSE_FORMATTING,
                                       else_span,
                                       "this is an `else if` but the formatting might hide it",
                                       else_span,
                                       "to remove this lint, remove the `else` or remove the new line between `else` \
                                        and `if`");
                }
            }
        }
    }
}

/// Implementation of the `POSSIBLE_MISSING_COMMA` lint for array
fn check_array(cx: &EarlyContext, expr: &ast::Expr) {
    if let ast::ExprKind::Array(ref array) = expr.node {
        for element in array {
            if let ast::ExprKind::Binary(ref op, ref lhs, _) = element.node {
                if !differing_macro_contexts(lhs.span, op.span) {
                    let space_span = mk_sp(lhs.span.hi, op.span.lo);
                    if let Some(space_snippet) = snippet_opt(cx, space_span) {
                        let lint_span = mk_sp(lhs.span.hi, lhs.span.hi);
                        if space_snippet.contains('\n') {
                            span_note_and_lint(cx,
                                               POSSIBLE_MISSING_COMMA,
                                               lint_span,
                                               "possibly missing a comma here",
                                               lint_span,
                                               "to remove this lint, add a comma or write the expr in a single line");
                        }
                    }
                }
            }
        }
    }
}

/// Implementation of the `SUSPICIOUS_ELSE_FORMATTING` lint for consecutive ifs.
fn check_consecutive_ifs(cx: &EarlyContext, first: &ast::Expr, second: &ast::Expr) {
    if !differing_macro_contexts(first.span, second.span) && !in_macro(cx, first.span) &&
       unsugar_if(first).is_some() && unsugar_if(second).is_some() {
        // where the else would be
        let else_span = mk_sp(first.span.hi, second.span.lo);

        if let Some(else_snippet) = snippet_opt(cx, else_span) {
            if !else_snippet.contains('\n') {
                span_note_and_lint(cx,
                                   SUSPICIOUS_ELSE_FORMATTING,
                                   else_span,
                                   "this looks like an `else if` but the `else` is missing",
                                   else_span,
                                   "to remove this lint, add the missing `else` or add a new line before the second \
                                    `if`");
            }
        }
    }
}

/// Match `if` or `if let` expressions and return the `then` and `else` block.
fn unsugar_if(expr: &ast::Expr) -> Option<(&P<ast::Block>, &Option<P<ast::Expr>>)> {
    match expr.node {
        ast::ExprKind::If(_, ref then, ref else_) |
        ast::ExprKind::IfLet(_, _, ref then, ref else_) => Some((then, else_)),
        _ => None,
    }
}
<|endoftext|>


<commit_before>extern crate bytes;
extern crate httpbis;
extern crate futures;
extern crate regex;

use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering;

use std::thread;
use std::time::Duration;

use regex::Regex;

use bytes::Bytes;

use futures::future::Future;
use futures::stream::Stream;
use futures::stream;
use futures::sink::Sink;
use futures::sync::mpsc;

use httpbis::*;

fn new_server() -> Server {
    let mut server = ServerBuilder::new_plain();
    server.service.set_service_fn("/200", |_, _| {
        Response::headers(Headers::ok_200())
    });
    server.service.set_service_fn("/inf", |headers, _| {
        let re = Regex::new("/inf/(\\d+)").expect("regex");
        let captures = re.captures(headers.path()).expect("captures");
        let size: u32 = captures.get(1).expect("1").as_str().parse().expect("parse");

        Response::headers_and_bytes_stream(
            Headers::ok_200(),
            stream::repeat(Bytes::from(vec![17; size as usize])))
    });
    server.service.set_service_fn("/bq", |headers, _| {
        let re = Regex::new("/bq/(\\d+)").expect("regex");
        let captures = re.captures(headers.path()).expect("captures");
        let size: u32 = captures.get(1).expect("1").as_str().parse().expect("parse");

        let (tx, rx) = mpsc::channel(1);

        thread::spawn(move || {
            let mut tx = tx;

            let b = Bytes::from(vec![17; size as usize]);
            loop {
                tx = tx.send(b.clone()).wait().expect("send");
            }
        });

        Response::headers_and_bytes_stream(
            Headers::ok_200(),
            rx.map_err(|_| unreachable!()))
    });
    server.set_port(0);
    server.build().expect("server")
}

fn spawn<F : FnOnce(Client, Arc<AtomicBool>) + Send + 'static>(port: u16, f: F) -> Arc<AtomicBool> {
    let still_alive = Arc::new(AtomicBool::new(false));
    let still_alive_copy = still_alive.clone();
    thread::spawn(move || {
        let client = Client::new_plain("::1", port, ClientConf::new()).expect("client");

        f(client, still_alive_copy)
    });
    still_alive
}

fn get_200(client: Client, still_alive: Arc<AtomicBool>) {
    loop {
        still_alive.store(true, Ordering::SeqCst);
        let r = client.start_get("/200", "localhost").collect().wait().expect("get");
        assert_eq!(200, r.headers.status());
    }
}

fn inf_impl(client: Client, still_alive: Arc<AtomicBool>, path: &str, size: usize) {
    let (headers, resp) = client.start_get(path, "localhost").0.wait().expect("get");

    assert_eq!(200, headers.status());

    let mut resp = resp.filter_data().wait();

    let exp = vec![17; size as usize];

    loop {
        still_alive.store(true, Ordering::SeqCst);

        let mut v = Vec::new();
        while v.len() < size as usize {
            still_alive.store(true, Ordering::SeqCst);
            v.extend(resp.next().unwrap().unwrap());
        }
        assert_eq!(&exp[..], &v[..size]);
        v.drain(..size);
    }
}

fn inf_100(client: Client, still_alive: Arc<AtomicBool>) {
    inf_impl(client, still_alive, "/inf/100", 100);
}

fn inf_10m(client: Client, still_alive: Arc<AtomicBool>) {
    inf_impl(client, still_alive, "/inf/10000000", 10000000);
}

fn bq_100(client: Client, still_alive: Arc<AtomicBool>) {
    inf_impl(client, still_alive, "/bq/100", 100);
}

fn bq_10m(client: Client, still_alive: Arc<AtomicBool>) {
    inf_impl(client, still_alive, "/bq/10000000", 10000000);
}

fn main() {
    let server = new_server();

    let get_200 = spawn(server.local_addr().port(), get_200);
    let inf_100 = spawn(server.local_addr().port(), inf_100);
    let inf_10m = spawn(server.local_addr().port(), inf_10m);
    let bq_100 = spawn(server.local_addr().port(), bq_100);
    let bq_10m = spawn(server.local_addr().port(), bq_10m);

    let all = vec![
        ("get_200", get_200),
        ("inf_100", inf_100),
        ("inf_10m", inf_10m),
        ("bq_100", bq_100),
        ("bq_10m", bq_10m),
    ];

    loop {
        thread::sleep(Duration::from_secs(1));

        let mut any_dead = false;
        for &(n, ref a) in &all {
            if !a.load(Ordering::SeqCst) {
                println!("{} is probably dead", n);
                any_dead = true;
            }
            a.store(false, Ordering::SeqCst);
        }

        if !any_dead {
            println!("all alive");
        }
    }
}
<commit_msg>Complicate stress test<commit_after>extern crate bytes;
extern crate httpbis;
extern crate futures;
extern crate regex;

use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering;

use std::thread;
use std::time::Duration;

use regex::Regex;

use bytes::Bytes;

use futures::future::Future;
use futures::stream::Stream;
use futures::stream;
use futures::sink::Sink;
use futures::sync::mpsc;

use httpbis::*;

fn new_server() -> Server {
    let mut server = ServerBuilder::new_plain();
    server.service.set_service_fn("/200", |_, _| {
        Response::headers(Headers::ok_200())
    });
    server.service.set_service_fn("/inf", |headers, _| {
        let re = Regex::new("/inf/(\\d+)").expect("regex");
        let captures = re.captures(headers.path()).expect("captures");
        let size: u32 = captures.get(1).expect("1").as_str().parse().expect("parse");

        Response::headers_and_bytes_stream(
            Headers::ok_200(),
            stream::repeat(Bytes::from(vec![17; size as usize])))
    });
    server.service.set_service_fn("/bq", |headers, _| {
        let re = Regex::new("/bq/(\\d+)").expect("regex");
        let captures = re.captures(headers.path()).expect("captures");
        let size: u32 = captures.get(1).expect("1").as_str().parse().expect("parse");

        let (tx, rx) = mpsc::channel(1);

        thread::spawn(move || {
            let mut tx = tx;

            let b = Bytes::from(vec![17; size as usize]);
            loop {
                tx = tx.send(b.clone()).wait().expect("send");
            }
        });

        Response::headers_and_bytes_stream(
            Headers::ok_200(),
            rx.map_err(|_| unreachable!()))
    });
    server.set_port(0);
    server.build().expect("server")
}

fn spawn<F : FnOnce(Client, Arc<AtomicBool>) + Send + 'static>(port: u16, f: F) -> Arc<AtomicBool> {
    let still_alive = Arc::new(AtomicBool::new(false));
    let still_alive_copy = still_alive.clone();
    thread::spawn(move || {
        let client = Client::new_plain("::1", port, ClientConf::new()).expect("client");

        f(client, still_alive_copy)
    });
    still_alive
}

fn get_200(client: Client, still_alive: Arc<AtomicBool>) {
    loop {
        still_alive.store(true, Ordering::SeqCst);
        let r = client.start_get("/200", "localhost").collect().wait().expect("get");
        assert_eq!(200, r.headers.status());
    }
}

fn inf_impl(client: Client, still_alive: Arc<AtomicBool>, path: &str, size: usize) {
    loop {
        let (headers, resp) = client.start_get(path, "localhost").0.wait().expect("get");

        assert_eq!(200, headers.status());

        let mut resp = resp.filter_data().wait();

        let exp = vec![17; size as usize];

        let iterations = 1_000_000_000 / size;

        for _ in 0..iterations {
            still_alive.store(true, Ordering::SeqCst);

            let mut v = Vec::new();
            while v.len() < size as usize {
                still_alive.store(true, Ordering::SeqCst);
                v.extend(resp.next().unwrap().unwrap());
            }
            assert_eq!(&exp[..], &v[..size]);
            v.drain(..size);
        }
    }
}

fn inf_100(client: Client, still_alive: Arc<AtomicBool>) {
    inf_impl(client, still_alive, "/inf/100", 100);
}

fn inf_10m(client: Client, still_alive: Arc<AtomicBool>) {
    inf_impl(client, still_alive, "/inf/10000000", 10000000);
}

fn bq_100(client: Client, still_alive: Arc<AtomicBool>) {
    inf_impl(client, still_alive, "/bq/100", 100);
}

fn bq_10m(client: Client, still_alive: Arc<AtomicBool>) {
    inf_impl(client, still_alive, "/bq/10000000", 10000000);
}

fn main() {
    let server = new_server();

    let get_200 = spawn(server.local_addr().port(), get_200);
    let inf_100 = spawn(server.local_addr().port(), inf_100);
    let inf_10m = spawn(server.local_addr().port(), inf_10m);
    let bq_100 = spawn(server.local_addr().port(), bq_100);
    let bq_10m = spawn(server.local_addr().port(), bq_10m);

    let all = vec![
        ("get_200", get_200),
        ("inf_100", inf_100),
        ("inf_10m", inf_10m),
        ("bq_100", bq_100),
        ("bq_10m", bq_10m),
    ];

    loop {
        thread::sleep(Duration::from_secs(1));

        let mut any_dead = false;
        for &(n, ref a) in &all {
            if !a.load(Ordering::SeqCst) {
                println!("{} is probably dead", n);
                any_dead = true;
            }
            a.store(false, Ordering::SeqCst);
        }

        if !any_dead {
            println!("all alive");
        }
    }
}
<|endoftext|>


<commit_before>//! Compile time optimized maps
#![crate_id="github.com/sfackler/rust-phf/phf"]
#![doc(html_root_url="http://www.rust-ci.org/sfackler/rust-phf/doc")]
#![crate_type="rlib"]
#![crate_type="dylib"]
#![warn(missing_doc)]

use std::fmt;
use std::hash::Hasher;
use std::hash::sip::SipHasher;
use std::slice;

/// An immutable map constructed at compile time.
///
/// `PhfMap`s may be created with the `phf_map` macro:
///
/// ```rust
/// # #[feature(phase)];
/// extern crate phf;
/// #[phase(syntax)]
/// extern crate phf_mac;
///
/// use phf::PhfMap;
///
/// static my_map: PhfMap<int> = phf_map!(
///    "hello" => 10,
///    "world" => 11,
/// );
///
/// # fn main() {}
/// ```
///
/// # Note
///
/// The fields of this struct are public so that they may be initialized by the
/// `phf_map` macro. They are subject to change at any time and should never
/// be accessed directly.
pub struct PhfMap<T> {
    #[doc(hidden)]
    pub k1: u64,
    #[doc(hidden)]
    pub k2: u64,
    #[doc(hidden)]
    pub disps: &'static [(uint, uint)],
    #[doc(hidden)]
    pub entries: &'static [(&'static str, T)],
}

static LOG_MAX_SIZE: uint = 21;

#[doc(hidden)]
pub static MAX_SIZE: uint = 1 << LOG_MAX_SIZE;

#[doc(hidden)]
#[inline]
pub fn hash(s: &str, k1: u64, k2: u64) -> (uint, uint, uint) {
    let hash = SipHasher::new_with_keys(k1, k2).hash(&s);
    let mask = (MAX_SIZE - 1) as u64;

    ((hash & mask) as uint,
     ((hash >> LOG_MAX_SIZE) & mask) as uint,
     ((hash >> (2 * LOG_MAX_SIZE)) & mask) as uint)
}

#[doc(hidden)]
#[inline]
pub fn displace(f1: uint, f2: uint, d1: uint, d2: uint) -> uint {
    d2 + f1 * d1 + f2
}

impl<T> Container for PhfMap<T> {
    fn len(&self) -> uint {
        self.entries.len()
    }
}

impl<'a, T> Map<&'a str, T> for PhfMap<T> {
    fn find<'a>(&'a self, key: & &str) -> Option<&'a T> {
        let (g, f1, f2) = hash(*key, self.k1, self.k2);
        let (d1, d2) = self.disps[g % self.disps.len()];
        let (s, ref value) = self.entries[displace(f1, f2, d1, d2) %
                                          self.entries.len()];
        if s == *key {
            Some(value)
        } else {
            None
        }
    }
}

impl<T: fmt::Show> fmt::Show for PhfMap<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!(fmt.buf.write_char('{'));
        let mut first = true;
        for (k, v) in self.entries() {
            if !first {
                try!(fmt.buf.write_str(", "));
            }
            try!(write!(fmt.buf, "{}: {}", k, v))
            first = false;
        }
        fmt.buf.write_char('}')
    }
}

impl<T> PhfMap<T> {
    /// Returns an iterator over the key/value pairs in the map.
    ///
    /// Entries are retuned in an arbitrary order.
    pub fn entries<'a>(&'a self) -> PhfMapEntries<'a, T> {
        PhfMapEntries { iter: self.entries.iter() }
    }

    /// Returns an iterator over the keys in the map.
    ///
    /// Keys are returned in an arbitrary order.
    pub fn keys<'a>(&'a self) -> PhfMapKeys<'a, T> {
        PhfMapKeys { iter: self.entries() }
    }

    /// Returns an iterator over the values in the map.
    ///
    /// Values are returned in an arbitrary order.
    pub fn values<'a>(&'a self) -> PhfMapValues<'a, T> {
        PhfMapValues { iter: self.entries() }
    }
}

/// An iterator over the key/value pairs in a `PhfMap`.
pub struct PhfMapEntries<'a, T> {
    iter: slice::Items<'a, (&'static str, T)>,
}

impl<'a, T> Iterator<(&'static str, &'a T)> for PhfMapEntries<'a, T> {
    fn next(&mut self) -> Option<(&'static str, &'a T)> {
        self.iter.next().map(|&(key, ref value)| (key, value))
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        self.iter.size_hint()
    }
}

/// An iterator over the keys in a `PhfMap`.
pub struct PhfMapKeys<'a, T> {
    iter: PhfMapEntries<'a, T>,
}

impl<'a, T> Iterator<&'static str> for PhfMapKeys<'a, T> {
    fn next(&mut self) -> Option<&'static str> {
        self.iter.next().map(|(key, _)| key)
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        self.iter.size_hint()
    }
}

/// An iterator over the values in a `PhfMap`.
pub struct PhfMapValues<'a, T> {
    iter: PhfMapEntries<'a, T>,
}

impl<'a, T> Iterator<&'a T> for PhfMapValues<'a, T> {
    fn next(&mut self) -> Option<&'a T> {
        self.iter.next().map(|(_, value)| value)
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        self.iter.size_hint()
    }
}
<commit_msg>Minor clarification in iterator docs<commit_after>//! Compile time optimized maps
#![crate_id="github.com/sfackler/rust-phf/phf"]
#![doc(html_root_url="http://www.rust-ci.org/sfackler/rust-phf/doc")]
#![crate_type="rlib"]
#![crate_type="dylib"]
#![warn(missing_doc)]

use std::fmt;
use std::hash::Hasher;
use std::hash::sip::SipHasher;
use std::slice;

/// An immutable map constructed at compile time.
///
/// `PhfMap`s may be created with the `phf_map` macro:
///
/// ```rust
/// # #[feature(phase)];
/// extern crate phf;
/// #[phase(syntax)]
/// extern crate phf_mac;
///
/// use phf::PhfMap;
///
/// static my_map: PhfMap<int> = phf_map!(
///    "hello" => 10,
///    "world" => 11,
/// );
///
/// # fn main() {}
/// ```
///
/// # Note
///
/// The fields of this struct are public so that they may be initialized by the
/// `phf_map` macro. They are subject to change at any time and should never
/// be accessed directly.
pub struct PhfMap<T> {
    #[doc(hidden)]
    pub k1: u64,
    #[doc(hidden)]
    pub k2: u64,
    #[doc(hidden)]
    pub disps: &'static [(uint, uint)],
    #[doc(hidden)]
    pub entries: &'static [(&'static str, T)],
}

static LOG_MAX_SIZE: uint = 21;

#[doc(hidden)]
pub static MAX_SIZE: uint = 1 << LOG_MAX_SIZE;

#[doc(hidden)]
#[inline]
pub fn hash(s: &str, k1: u64, k2: u64) -> (uint, uint, uint) {
    let hash = SipHasher::new_with_keys(k1, k2).hash(&s);
    let mask = (MAX_SIZE - 1) as u64;

    ((hash & mask) as uint,
     ((hash >> LOG_MAX_SIZE) & mask) as uint,
     ((hash >> (2 * LOG_MAX_SIZE)) & mask) as uint)
}

#[doc(hidden)]
#[inline]
pub fn displace(f1: uint, f2: uint, d1: uint, d2: uint) -> uint {
    d2 + f1 * d1 + f2
}

impl<T> Container for PhfMap<T> {
    fn len(&self) -> uint {
        self.entries.len()
    }
}

impl<'a, T> Map<&'a str, T> for PhfMap<T> {
    fn find<'a>(&'a self, key: & &str) -> Option<&'a T> {
        let (g, f1, f2) = hash(*key, self.k1, self.k2);
        let (d1, d2) = self.disps[g % self.disps.len()];
        let (s, ref value) = self.entries[displace(f1, f2, d1, d2) %
                                          self.entries.len()];
        if s == *key {
            Some(value)
        } else {
            None
        }
    }
}

impl<T: fmt::Show> fmt::Show for PhfMap<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!(fmt.buf.write_char('{'));
        let mut first = true;
        for (k, v) in self.entries() {
            if !first {
                try!(fmt.buf.write_str(", "));
            }
            try!(write!(fmt.buf, "{}: {}", k, v))
            first = false;
        }
        fmt.buf.write_char('}')
    }
}

impl<T> PhfMap<T> {
    /// Returns an iterator over the key/value pairs in the map.
    ///
    /// Entries are retuned in an arbitrary but fixed order.
    pub fn entries<'a>(&'a self) -> PhfMapEntries<'a, T> {
        PhfMapEntries { iter: self.entries.iter() }
    }

    /// Returns an iterator over the keys in the map.
    ///
    /// Keys are returned in an arbitrary but fixed order.
    pub fn keys<'a>(&'a self) -> PhfMapKeys<'a, T> {
        PhfMapKeys { iter: self.entries() }
    }

    /// Returns an iterator over the values in the map.
    ///
    /// Values are returned in an arbitrary but fixed order.
    pub fn values<'a>(&'a self) -> PhfMapValues<'a, T> {
        PhfMapValues { iter: self.entries() }
    }
}

/// An iterator over the key/value pairs in a `PhfMap`.
pub struct PhfMapEntries<'a, T> {
    iter: slice::Items<'a, (&'static str, T)>,
}

impl<'a, T> Iterator<(&'static str, &'a T)> for PhfMapEntries<'a, T> {
    fn next(&mut self) -> Option<(&'static str, &'a T)> {
        self.iter.next().map(|&(key, ref value)| (key, value))
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        self.iter.size_hint()
    }
}

/// An iterator over the keys in a `PhfMap`.
pub struct PhfMapKeys<'a, T> {
    iter: PhfMapEntries<'a, T>,
}

impl<'a, T> Iterator<&'static str> for PhfMapKeys<'a, T> {
    fn next(&mut self) -> Option<&'static str> {
        self.iter.next().map(|(key, _)| key)
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        self.iter.size_hint()
    }
}

/// An iterator over the values in a `PhfMap`.
pub struct PhfMapValues<'a, T> {
    iter: PhfMapEntries<'a, T>,
}

impl<'a, T> Iterator<&'a T> for PhfMapValues<'a, T> {
    fn next(&mut self) -> Option<&'a T> {
        self.iter.next().map(|(_, value)| value)
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        self.iter.size_hint()
    }
}
<|endoftext|>


<commit_before>//! Decoding and Encoding of PNG Images
//!
//! PNG (Portable Network Graphics) is an image format that supports lossless compression.
//!
//! # Related Links
//! * <http://www.w3.org/TR/PNG/> - The PNG Specification
//!

extern crate png;

use std::io::{self, Read, Write};

use color::ColorType;
use image::{ImageDecoder, ImageError, ImageResult};

/// PNG Reader
///
/// This reader will try to read the png one row at a time,
/// however for interlaced png files this is not posible and
/// these are therefore readed at once.
pub struct PNGReader<R: Read> {
    reader: png::Reader<R>,
    buffer: Vec<u8>,
    index: usize,
}

impl<R: Read> PNGReader<R> {
    fn new(mut reader: png::Reader<R>) -> ImageResult<PNGReader<R>> {
        let len = reader.output_buffer_size();
        // Since interlaced images do not come in
        // scanline order it is almost impossible to
        // read them in a streaming fashion, however
        // this shouldn't be a too big of a problem
        // as most interlaced images should fit in memory.
        let buffer = if reader.info().interlaced {
            let mut buffer = vec![0; len];
            reader.next_frame(&mut buffer)?;
            buffer
        } else {
            Vec::new()
        };

        Ok(PNGReader {
            reader,
            buffer,
            index: 0,
        })
    }
}

impl<R: Read> Read for PNGReader<R> {
    fn read(&mut self, mut buf: &mut [u8]) -> io::Result<usize> {
        // io::Write::write for slice cannot fail
        let readed = buf.write(&self.buffer[self.index..]).unwrap();

        let mut bytes = readed;
        self.index += readed;

        while self.index >= self.buffer.len() {
            match self.reader.next_row()? {
                Some(row) => {
                    // Faster to copy directly to external buffer
                    let readed  = buf.write(row).unwrap();
                    bytes += readed;

                    self.buffer = (&row[readed..]).to_owned();
                    self.index = 0;
                }
                None => return Ok(bytes)
            }
        }

        Ok(bytes)
    }

    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
        let mut bytes = self.buffer.len();
        buf.extend_from_slice(&self.buffer);
        self.buffer = Vec::new();
        self.index = 0;

        while let Some(row) = self.reader.next_row()? {
            buf.extend_from_slice(row);
            bytes += row.len();
        }

        Ok(bytes)
    }
}

/// PNG decoder
pub struct PNGDecoder<R: Read> {
    colortype: ColorType,
    reader: png::Reader<R>,
}

impl<R: Read> PNGDecoder<R> {
    /// Creates a new decoder that decodes from the stream ```r```
    pub fn new(r: R) -> ImageResult<PNGDecoder<R>> {
        let limits = png::Limits {
            bytes: usize::max_value(),
        };
        let decoder = png::Decoder::new_with_limits(r, limits);
        let (_, mut reader) = decoder.read_info()?;
        let colortype = reader.output_color_type().into();

        Ok(PNGDecoder { colortype, reader })
    }
}

impl<'a, R: 'a + Read> ImageDecoder<'a> for PNGDecoder<R> {
    type Reader = PNGReader<R>;

    fn dimensions(&self) -> (u64, u64) {
        let (w, h) = self.reader.info().size();
        (u64::from(w), u64::from(h))
    }

    fn colortype(&self) -> ColorType {
        self.colortype
    }

    fn into_reader(self) -> ImageResult<Self::Reader> {
        PNGReader::new(self.reader)
    }

    fn read_image(mut self) -> ImageResult<Vec<u8>> {
        // This should be slightly faster than the default implementation
        let mut data = vec![0; self.reader.output_buffer_size()];
        self.reader.next_frame(&mut data)?;
        Ok(data)
    }

    fn scanline_bytes(&self) -> u64 {
        let width = self.reader.info().width;
        self.reader.output_line_size(width) as u64
    }
}

/// PNG encoder
pub struct PNGEncoder<W: Write> {
    w: W,
}

impl<W: Write> PNGEncoder<W> {
    /// Create a new encoder that writes its output to ```w```
    pub fn new(w: W) -> PNGEncoder<W> {
        PNGEncoder { w }
    }

    /// Encodes the image ```image```
    /// that has dimensions ```width``` and ```height```
    /// and ```ColorType``` ```c```
    pub fn encode(self, data: &[u8], width: u32, height: u32, color: ColorType) -> io::Result<()> {
        let (ct, bits) = color.into();
        let mut encoder = png::Encoder::new(self.w, width, height);
        encoder.set_color(ct);
        encoder.set_depth(bits);
        let mut writer = encoder.write_header()?;
        writer.write_image_data(data).map_err(|e| e.into())
    }
}

impl From<(png::ColorType, png::BitDepth)> for ColorType {
    fn from((ct, bits): (png::ColorType, png::BitDepth)) -> ColorType {
        use self::png::ColorType::*;
        let bits = bits as u8;
        match ct {
            Grayscale => ColorType::Gray(bits),
            RGB => ColorType::RGB(bits),
            Indexed => ColorType::Palette(bits),
            GrayscaleAlpha => ColorType::GrayA(bits),
            RGBA => ColorType::RGBA(bits),
        }
    }
}

impl From<ColorType> for (png::ColorType, png::BitDepth) {
    fn from(ct: ColorType) -> (png::ColorType, png::BitDepth) {
        use self::png::ColorType::*;
        let (ct, bits) = match ct {
            ColorType::Gray(bits) => (Grayscale, bits),
            ColorType::RGB(bits) => (RGB, bits),
            ColorType::Palette(bits) => (Indexed, bits),
            ColorType::GrayA(bits) => (GrayscaleAlpha, bits),
            ColorType::RGBA(bits) => (RGBA, bits),
            ColorType::BGRA(bits) => (RGBA, bits),
            ColorType::BGR(bits) => (RGB, bits),
        };
        (ct, png::BitDepth::from_u8(bits).unwrap())
    }
}

impl From<png::DecodingError> for ImageError {
    fn from(err: png::DecodingError) -> ImageError {
        use self::png::DecodingError::*;
        match err {
            IoError(err) => ImageError::IoError(err),
            Format(desc) => ImageError::FormatError(desc.into_owned()),
            InvalidSignature => ImageError::FormatError("invalid signature".into()),
            CrcMismatch { .. } => ImageError::FormatError("CRC error".into()),
            Other(desc) => ImageError::FormatError(desc.into_owned()),
            CorruptFlateStream => {
                ImageError::FormatError("compressed data stream corrupted".into())
            }
            LimitsExceeded => ImageError::InsufficientMemory,
        }
    }
}

#[cfg(test)]
mod tests {
    use image::ImageDecoder;
    use std::io::Read;
    use super::*;

    #[test]
    fn ensure_no_decoder_off_by_one() {
        let dec = PNGDecoder::new(std::fs::File::open("tests/images/png/bugfixes/debug_triangle_corners_widescreen.png").unwrap())
            .expect("Unable to read PNG file (does it exist?)");

        assert_eq![(2000, 1000), dec.dimensions()];

        assert_eq![
            ColorType::RGB(8),
            dec.colortype(),
            "Image MUST have the RGB(8) format"
        ];

        let correct_bytes = dec
            .into_reader()
            .expect("Unable to read file")
            .bytes()
            .map(|x| x.expect("Unable to read byte"))
            .collect::<Vec<u8>>();

        assert_eq![6_000_000, correct_bytes.len()];
    }
}
<commit_msg>PNG encoding should return error on unsupported color type<commit_after>//! Decoding and Encoding of PNG Images
//!
//! PNG (Portable Network Graphics) is an image format that supports lossless compression.
//!
//! # Related Links
//! * <http://www.w3.org/TR/PNG/> - The PNG Specification
//!

extern crate png;

use std::io::{self, Read, Write};

use color::ColorType;
use image::{ImageDecoder, ImageError, ImageResult};

/// PNG Reader
///
/// This reader will try to read the png one row at a time,
/// however for interlaced png files this is not posible and
/// these are therefore readed at once.
pub struct PNGReader<R: Read> {
    reader: png::Reader<R>,
    buffer: Vec<u8>,
    index: usize,
}

impl<R: Read> PNGReader<R> {
    fn new(mut reader: png::Reader<R>) -> ImageResult<PNGReader<R>> {
        let len = reader.output_buffer_size();
        // Since interlaced images do not come in
        // scanline order it is almost impossible to
        // read them in a streaming fashion, however
        // this shouldn't be a too big of a problem
        // as most interlaced images should fit in memory.
        let buffer = if reader.info().interlaced {
            let mut buffer = vec![0; len];
            reader.next_frame(&mut buffer)?;
            buffer
        } else {
            Vec::new()
        };

        Ok(PNGReader {
            reader,
            buffer,
            index: 0,
        })
    }
}

impl<R: Read> Read for PNGReader<R> {
    fn read(&mut self, mut buf: &mut [u8]) -> io::Result<usize> {
        // io::Write::write for slice cannot fail
        let readed = buf.write(&self.buffer[self.index..]).unwrap();

        let mut bytes = readed;
        self.index += readed;

        while self.index >= self.buffer.len() {
            match self.reader.next_row()? {
                Some(row) => {
                    // Faster to copy directly to external buffer
                    let readed  = buf.write(row).unwrap();
                    bytes += readed;

                    self.buffer = (&row[readed..]).to_owned();
                    self.index = 0;
                }
                None => return Ok(bytes)
            }
        }

        Ok(bytes)
    }

    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
        let mut bytes = self.buffer.len();
        buf.extend_from_slice(&self.buffer);
        self.buffer = Vec::new();
        self.index = 0;

        while let Some(row) = self.reader.next_row()? {
            buf.extend_from_slice(row);
            bytes += row.len();
        }

        Ok(bytes)
    }
}

/// PNG decoder
pub struct PNGDecoder<R: Read> {
    colortype: ColorType,
    reader: png::Reader<R>,
}

impl<R: Read> PNGDecoder<R> {
    /// Creates a new decoder that decodes from the stream ```r```
    pub fn new(r: R) -> ImageResult<PNGDecoder<R>> {
        let limits = png::Limits {
            bytes: usize::max_value(),
        };
        let decoder = png::Decoder::new_with_limits(r, limits);
        let (_, mut reader) = decoder.read_info()?;
        let colortype = reader.output_color_type().into();

        Ok(PNGDecoder { colortype, reader })
    }
}

impl<'a, R: 'a + Read> ImageDecoder<'a> for PNGDecoder<R> {
    type Reader = PNGReader<R>;

    fn dimensions(&self) -> (u64, u64) {
        let (w, h) = self.reader.info().size();
        (u64::from(w), u64::from(h))
    }

    fn colortype(&self) -> ColorType {
        self.colortype
    }

    fn into_reader(self) -> ImageResult<Self::Reader> {
        PNGReader::new(self.reader)
    }

    fn read_image(mut self) -> ImageResult<Vec<u8>> {
        // This should be slightly faster than the default implementation
        let mut data = vec![0; self.reader.output_buffer_size()];
        self.reader.next_frame(&mut data)?;
        Ok(data)
    }

    fn scanline_bytes(&self) -> u64 {
        let width = self.reader.info().width;
        self.reader.output_line_size(width) as u64
    }
}

/// PNG encoder
pub struct PNGEncoder<W: Write> {
    w: W,
}

impl<W: Write> PNGEncoder<W> {
    /// Create a new encoder that writes its output to ```w```
    pub fn new(w: W) -> PNGEncoder<W> {
        PNGEncoder { w }
    }

    /// Encodes the image ```image```
    /// that has dimensions ```width``` and ```height```
    /// and ```ColorType``` ```c```
    pub fn encode(self, data: &[u8], width: u32, height: u32, color: ColorType) -> io::Result<()> {
        let (ct, bits) = match color {
            ColorType::Gray(bits) => Some((png::ColorType::Grayscale, bits)),
            ColorType::RGB(bits) => Some((png::ColorType::RGB, bits)),
            ColorType::Palette(bits) => Some((png::ColorType::Indexed, bits)),
            ColorType::GrayA(bits) => Some((png::ColorType::GrayscaleAlpha, bits)),
            ColorType::RGBA(bits) => Some((png::ColorType::RGBA, bits)),
            _ => None,
        }
        .and_then(|(ct, bits)| Some((ct, png::BitDepth::from_u8(bits)?)))
        .ok_or(io::Error::new(io::ErrorKind::InvalidInput, ImageError::UnsupportedColor(color)))?;

        let mut encoder = png::Encoder::new(self.w, width, height);
        encoder.set_color(ct);
        encoder.set_depth(bits);
        let mut writer = encoder.write_header()?;
        writer.write_image_data(data).map_err(|e| e.into())
    }
}

impl From<(png::ColorType, png::BitDepth)> for ColorType {
    fn from((ct, bits): (png::ColorType, png::BitDepth)) -> ColorType {
        use self::png::ColorType::*;
        let bits = bits as u8;
        match ct {
            Grayscale => ColorType::Gray(bits),
            RGB => ColorType::RGB(bits),
            Indexed => ColorType::Palette(bits),
            GrayscaleAlpha => ColorType::GrayA(bits),
            RGBA => ColorType::RGBA(bits),
        }
    }
}

impl From<ColorType> for (png::ColorType, png::BitDepth) {
    fn from(ct: ColorType) -> (png::ColorType, png::BitDepth) {
        use self::png::ColorType::*;
        let (ct, bits) = match ct {
            ColorType::Gray(bits) => (Grayscale, bits),
            ColorType::RGB(bits) => (RGB, bits),
            ColorType::Palette(bits) => (Indexed, bits),
            ColorType::GrayA(bits) => (GrayscaleAlpha, bits),
            ColorType::RGBA(bits) => (RGBA, bits),
            ColorType::BGRA(bits) => (RGBA, bits),
            ColorType::BGR(bits) => (RGB, bits),
        };
        (ct, png::BitDepth::from_u8(bits).unwrap())
    }
}

impl From<png::DecodingError> for ImageError {
    fn from(err: png::DecodingError) -> ImageError {
        use self::png::DecodingError::*;
        match err {
            IoError(err) => ImageError::IoError(err),
            Format(desc) => ImageError::FormatError(desc.into_owned()),
            InvalidSignature => ImageError::FormatError("invalid signature".into()),
            CrcMismatch { .. } => ImageError::FormatError("CRC error".into()),
            Other(desc) => ImageError::FormatError(desc.into_owned()),
            CorruptFlateStream => {
                ImageError::FormatError("compressed data stream corrupted".into())
            }
            LimitsExceeded => ImageError::InsufficientMemory,
        }
    }
}

#[cfg(test)]
mod tests {
    use image::ImageDecoder;
    use std::io::Read;
    use super::*;

    #[test]
    fn ensure_no_decoder_off_by_one() {
        let dec = PNGDecoder::new(std::fs::File::open("tests/images/png/bugfixes/debug_triangle_corners_widescreen.png").unwrap())
            .expect("Unable to read PNG file (does it exist?)");

        assert_eq![(2000, 1000), dec.dimensions()];

        assert_eq![
            ColorType::RGB(8),
            dec.colortype(),
            "Image MUST have the RGB(8) format"
        ];

        let correct_bytes = dec
            .into_reader()
            .expect("Unable to read file")
            .bytes()
            .map(|x| x.expect("Unable to read byte"))
            .collect::<Vec<u8>>();

        assert_eq![6_000_000, correct_bytes.len()];
    }
}
<|endoftext|>


<commit_before>use core::ops::Mul;
use core::num::Wrapping;
use {One, CheckedMul};

/// Binary operator for raising a value to a power.
pub trait Pow<RHS> {
    /// The result after applying the operator.
    type Output;

    /// Returns `self` to the power `rhs`.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::Pow;
    /// assert_eq!(Pow::pow(10u32, 2u32), 100);
    /// ```
    fn pow(self, rhs: RHS) -> Self::Output;
}

macro_rules! pow_impl {
    ($t:ty) => {
        pow_impl!($t, u8);
        pow_impl!($t, u16);
        pow_impl!($t, u32);
        pow_impl!($t, usize);
    };
    ($t:ty, $rhs:ty) => {
        pow_impl!($t, $rhs, |x, p| pow(x, p as usize));
    };
    ($t:ty, $rhs:ty, $method:expr) => {
        impl Pow<$rhs> for $t {
            type Output = $t;
            #[inline]
            fn pow(self, rhs: $rhs) -> $t {
                ($method)(self, rhs)
            }
        }

        impl<'a> Pow<&'a $rhs> for $t {
            type Output = $t;
            #[inline]
            fn pow(self, rhs: &'a $rhs) -> $t {
                ($method)(self, *rhs)
            }
        }

        impl<'a> Pow<$rhs> for &'a $t {
            type Output = $t;
            #[inline]
            fn pow(self, rhs: $rhs) -> $t {
                ($method)(*self, rhs)
            }
        }

        impl<'a, 'b> Pow<&'a $rhs> for &'b $t {
            type Output = $t;
            #[inline]
            fn pow(self, rhs: &'a $rhs) -> $t {
                ($method)(*self, *rhs)
            }
        }
    };
}

pow_impl!(u8, u8, |x: u8, p| x.pow(p as u32));
pow_impl!(u8, u16, |x: u8, p| x.pow(p as u32));
pow_impl!(u8, u32, u8::pow);
pow_impl!(u8, usize);
pow_impl!(i8, u8, |x: i8, p| x.pow(p as u32));
pow_impl!(i8, u16, |x: i8, p| x.pow(p as u32));
pow_impl!(i8, u32, i8::pow);
pow_impl!(i8, usize);
pow_impl!(u16, u8, |x: u16, p| x.pow(p as u32));
pow_impl!(u16, u16, |x: u16, p| x.pow(p as u32));
pow_impl!(u16, u32, u16::pow);
pow_impl!(u16, usize);
pow_impl!(i16, u8, |x: i16, p| x.pow(p as u32));
pow_impl!(i16, u16, |x: i16, p| x.pow(p as u32));
pow_impl!(i16, u32, i16::pow);
pow_impl!(i16, usize);
pow_impl!(u32, u8, |x: u32, p| x.pow(p as u32));
pow_impl!(u32, u16, |x: u32, p| x.pow(p as u32));
pow_impl!(u32, u32, u32::pow);
pow_impl!(u32, usize);
pow_impl!(i32, u8, |x: i32, p| x.pow(p as u32));
pow_impl!(i32, u16, |x: i32, p| x.pow(p as u32));
pow_impl!(i32, u32, i32::pow);
pow_impl!(i32, usize);
pow_impl!(u64, u8, |x: u64, p| x.pow(p as u32));
pow_impl!(u64, u16, |x: u64, p| x.pow(p as u32));
pow_impl!(u64, u32, u64::pow);
pow_impl!(u64, usize);
pow_impl!(i64, u8, |x: i64, p| x.pow(p as u32));
pow_impl!(i64, u16, |x: i64, p| x.pow(p as u32));
pow_impl!(i64, u32, i64::pow);
pow_impl!(i64, usize);
pow_impl!(usize, u8, |x: usize, p| x.pow(p as u32));
pow_impl!(usize, u16, |x: usize, p| x.pow(p as u32));
pow_impl!(usize, u32, usize::pow);
pow_impl!(usize, usize);
pow_impl!(isize, u8, |x: isize, p| x.pow(p as u32));
pow_impl!(isize, u16, |x: isize, p| x.pow(p as u32));
pow_impl!(isize, u32, isize::pow);
pow_impl!(isize, usize);
pow_impl!(Wrapping<u8>);
pow_impl!(Wrapping<i8>);
pow_impl!(Wrapping<u16>);
pow_impl!(Wrapping<i16>);
pow_impl!(Wrapping<u32>);
pow_impl!(Wrapping<i32>);
pow_impl!(Wrapping<u64>);
pow_impl!(Wrapping<i64>);
pow_impl!(Wrapping<usize>);
pow_impl!(Wrapping<isize>);

#[cfg(feature = "std")]
mod float_impls {
    use super::Pow;

    pow_impl!(f32, i8, |x: f32, p| x.powi(p as i32));
    pow_impl!(f32, u8, |x: f32, p| x.powi(p as i32));
    pow_impl!(f32, i16, |x: f32, p| x.powi(p as i32));
    pow_impl!(f32, u16, |x: f32, p| x.powi(p as i32));
    pow_impl!(f32, i32, f32::powi);
    pow_impl!(f64, i8, |x: f64, p| x.powi(p as i32));
    pow_impl!(f64, u8, |x: f64, p| x.powi(p as i32));
    pow_impl!(f64, i16, |x: f64, p| x.powi(p as i32));
    pow_impl!(f64, u16, |x: f64, p| x.powi(p as i32));
    pow_impl!(f64, i32, f64::powi);
    pow_impl!(f32, f32, f32::powf);
    pow_impl!(f64, f32, |x: f64, p| x.powf(p as f64));
    pow_impl!(f64, f64, f64::powf);
}

/// Raises a value to the power of exp, using exponentiation by squaring.
///
/// # Example
///
/// ```rust
/// use num_traits::pow;
///
/// assert_eq!(pow(2i8, 4), 16);
/// assert_eq!(pow(6u8, 3), 216);
/// ```
#[inline]
pub fn pow<T: Clone + One + Mul<T, Output = T>>(mut base: T, mut exp: usize) -> T {
    if exp == 0 { return T::one() }

    while exp & 1 == 0 {
        base = base.clone() * base;
        exp >>= 1;
    }
    if exp == 1 { return base }

    let mut acc = base.clone();
    while exp > 1 {
        exp >>= 1;
        base = base.clone() * base;
        if exp & 1 == 1 {
            acc = acc * base.clone();
        }
    }
    acc
}

/// Raises a value to the power of exp, returning `None` if an overflow occurred.
///
/// Otherwise same as the `pow` function.
///
/// # Example
///
/// ```rust
/// use num_traits::checked_pow;
///
/// assert_eq!(checked_pow(2i8, 4), Some(16));
/// assert_eq!(checked_pow(7i8, 8), None);
/// assert_eq!(checked_pow(7u32, 8), Some(5_764_801));
/// ```
#[inline]
pub fn checked_pow<T: Clone + One + CheckedMul>(mut base: T, mut exp: usize) -> Option<T> {
    if exp == 0 { return Some(T::one()) }

    macro_rules! optry {
        ( $ expr : expr ) => {
            if let Some(val) = $expr { val } else { return None }
        }
    }

    while exp & 1 == 0 {
        base = optry!(base.checked_mul(&base));
        exp >>= 1;
    }
    if exp == 1 { return Some(base) }

    let mut acc = base.clone();
    while exp > 1 {
        exp >>= 1;
        base = optry!(base.checked_mul(&base));
        if exp & 1 == 1 {
            acc = optry!(acc.checked_mul(&base));
        }
    }
    Some(acc)
}
<commit_msg>Ensure infalliability of conversions, avoid closures.<commit_after>use core::ops::Mul;
use core::num::Wrapping;
use {One, CheckedMul};

/// Binary operator for raising a value to a power.
pub trait Pow<RHS> {
    /// The result after applying the operator.
    type Output;

    /// Returns `self` to the power `rhs`.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::Pow;
    /// assert_eq!(Pow::pow(10u32, 2u32), 100);
    /// ```
    fn pow(self, rhs: RHS) -> Self::Output;
}

macro_rules! pow_impl {
    ($t:ty) => {
        pow_impl!($t, u8);
        pow_impl!($t, usize);

        // FIXME: these should be possible
        // pow_impl!($t, u16);
        // pow_impl!($t, u32);
        // pow_impl!($t, u64);
    };
    ($t:ty, $rhs:ty) => {
        pow_impl!($t, $rhs, usize, pow);
    };
    ($t:ty, $rhs:ty, $desired_rhs:ty, $method:expr) => {
        impl Pow<$rhs> for $t {
            type Output = $t;
            #[inline]
            fn pow(self, rhs: $rhs) -> $t {
                ($method)(self, <$desired_rhs>::from(rhs))
            }
        }

        impl<'a> Pow<&'a $rhs> for $t {
            type Output = $t;
            #[inline]
            fn pow(self, rhs: &'a $rhs) -> $t {
                ($method)(self, <$desired_rhs>::from(*rhs))
            }
        }

        impl<'a> Pow<$rhs> for &'a $t {
            type Output = $t;
            #[inline]
            fn pow(self, rhs: $rhs) -> $t {
                ($method)(*self, <$desired_rhs>::from(rhs))
            }
        }

        impl<'a, 'b> Pow<&'a $rhs> for &'b $t {
            type Output = $t;
            #[inline]
            fn pow(self, rhs: &'a $rhs) -> $t {
                ($method)(*self, <$desired_rhs>::from(*rhs))
            }
        }
    };
}

pow_impl!(u8, u8, u32, u8::pow);
pow_impl!(u8, u16, u32, u8::pow);
pow_impl!(u8, u32, u32, u8::pow);
pow_impl!(u8, usize);
pow_impl!(i8, u8, u32, i8::pow);
pow_impl!(i8, u16, u32, i8::pow);
pow_impl!(i8, u32, u32, i8::pow);
pow_impl!(i8, usize);
pow_impl!(u16, u8, u32, u16::pow);
pow_impl!(u16, u16, u32, u16::pow);
pow_impl!(u16, u32, u32, u16::pow);
pow_impl!(u16, usize);
pow_impl!(i16, u8, u32, i16::pow);
pow_impl!(i16, u16, u32, i16::pow);
pow_impl!(i16, u32, u32, i16::pow);
pow_impl!(i16, usize);
pow_impl!(u32, u8, u32, u32::pow);
pow_impl!(u32, u16, u32, u32::pow);
pow_impl!(u32, u32, u32, u32::pow);
pow_impl!(u32, usize);
pow_impl!(i32, u8, u32, i32::pow);
pow_impl!(i32, u16, u32, i32::pow);
pow_impl!(i32, u32, u32, i32::pow);
pow_impl!(i32, usize);
pow_impl!(u64, u8, u32, u64::pow);
pow_impl!(u64, u16, u32, u64::pow);
pow_impl!(u64, u32, u32, u64::pow);
pow_impl!(u64, usize);
pow_impl!(i64, u8, u32, i64::pow);
pow_impl!(i64, u16, u32, i64::pow);
pow_impl!(i64, u32, u32, i64::pow);
pow_impl!(i64, usize);
pow_impl!(usize, u8, u32, usize::pow);
pow_impl!(usize, u16, u32, usize::pow);
pow_impl!(usize, u32, u32, usize::pow);
pow_impl!(usize, usize);
pow_impl!(isize, u8, u32, isize::pow);
pow_impl!(isize, u16, u32, isize::pow);
pow_impl!(isize, u32, u32, isize::pow);
pow_impl!(isize, usize);
pow_impl!(Wrapping<u8>);
pow_impl!(Wrapping<i8>);
pow_impl!(Wrapping<u16>);
pow_impl!(Wrapping<i16>);
pow_impl!(Wrapping<u32>);
pow_impl!(Wrapping<i32>);
pow_impl!(Wrapping<u64>);
pow_impl!(Wrapping<i64>);
pow_impl!(Wrapping<usize>);
pow_impl!(Wrapping<isize>);

// FIXME: these should be possible
// pow_impl!(u8, u64);
// pow_impl!(i16, u64);
// pow_impl!(i8, u64);
// pow_impl!(u16, u64);
// pow_impl!(u32, u64);
// pow_impl!(i32, u64);
// pow_impl!(u64, u64);
// pow_impl!(i64, u64);
// pow_impl!(usize, u64);
// pow_impl!(isize, u64);

#[cfg(feature = "std")]
mod float_impls {
    use super::Pow;

    pow_impl!(f32, i8, i32, f32::powi);
    pow_impl!(f32, u8, i32, f32::powi);
    pow_impl!(f32, i16, i32, f32::powi);
    pow_impl!(f32, u16, i32, f32::powi);
    pow_impl!(f32, i32, i32, f32::powi);
    pow_impl!(f64, i8, i32, f64::powi);
    pow_impl!(f64, u8, i32, f64::powi);
    pow_impl!(f64, i16, i32, f64::powi);
    pow_impl!(f64, u16, i32, f64::powi);
    pow_impl!(f64, i32, i32, f64::powi);
    pow_impl!(f32, f32, f32, f32::powf);
    pow_impl!(f64, f32, f64, f64::powf);
    pow_impl!(f64, f64, f64, f64::powf);
}

/// Raises a value to the power of exp, using exponentiation by squaring.
///
/// # Example
///
/// ```rust
/// use num_traits::pow;
///
/// assert_eq!(pow(2i8, 4), 16);
/// assert_eq!(pow(6u8, 3), 216);
/// ```
#[inline]
pub fn pow<T: Clone + One + Mul<T, Output = T>>(mut base: T, mut exp: usize) -> T {
    if exp == 0 { return T::one() }

    while exp & 1 == 0 {
        base = base.clone() * base;
        exp >>= 1;
    }
    if exp == 1 { return base }

    let mut acc = base.clone();
    while exp > 1 {
        exp >>= 1;
        base = base.clone() * base;
        if exp & 1 == 1 {
            acc = acc * base.clone();
        }
    }
    acc
}

/// Raises a value to the power of exp, returning `None` if an overflow occurred.
///
/// Otherwise same as the `pow` function.
///
/// # Example
///
/// ```rust
/// use num_traits::checked_pow;
///
/// assert_eq!(checked_pow(2i8, 4), Some(16));
/// assert_eq!(checked_pow(7i8, 8), None);
/// assert_eq!(checked_pow(7u32, 8), Some(5_764_801));
/// ```
#[inline]
pub fn checked_pow<T: Clone + One + CheckedMul>(mut base: T, mut exp: usize) -> Option<T> {
    if exp == 0 { return Some(T::one()) }

    macro_rules! optry {
        ( $ expr : expr ) => {
            if let Some(val) = $expr { val } else { return None }
        }
    }

    while exp & 1 == 0 {
        base = optry!(base.checked_mul(&base));
        exp >>= 1;
    }
    if exp == 1 { return Some(base) }

    let mut acc = base.clone();
    while exp > 1 {
        exp >>= 1;
        base = optry!(base.checked_mul(&base));
        if exp & 1 == 1 {
            acc = optry!(acc.checked_mul(&base));
        }
    }
    Some(acc)
}
<|endoftext|>


<commit_before>use math::{Point, Vector};

use cgmath::prelude::*;
use cgmath::{ApproxEq, dot};

/// A ray of light traveling through our scene.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Ray {
    pub origin: Point,
    pub direction: Vector,
}

impl Ray {
    pub fn new(origin: Point, direction: Vector) -> Ray {
        debug_assert!(direction.magnitude().approx_eq(&1.0),
                      "Ray direction is not normalized. (|{:?}| == {:?} != 1.0)",
                      direction,
                      direction.magnitude());

        Ray {
            origin: origin,
            direction: direction,
        }
    }

    /// Get the position of traveling `distance` along the ray.
    pub fn evaluate(&self, distance: f32) -> Point {
        self.origin + self.direction * distance
    }

    /// Calculates the ray we get by reflecting it from `intersection` with the
    /// specified normal.
    pub fn reflect(&self, normal: Vector, intersection: Point) -> Ray {
        let new_direction =
            self.direction - 2f32 * dot(self.direction, normal) * normal;

        Ray {
            origin: intersection,
            direction: new_direction,
        }
    }
}

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

    #[test]
    fn test_reflect() {
        let ray = Ray::new(vec3(-1.0, 1.0, 0.0), vec3(1.0, -1.0, 0.0).normalize());
        let normal = vec3(0.0, 1.0, 0.0);
        let intersection = vec3(0.0, 0.0, 0.0);

        let result = Ray::new(vec3(0.0, 0.0, 0.0), vec3(1.0, 1.0, 0.0).normalize());
        assert_eq!(ray.reflect(normal, intersection), result);
    }
}
<commit_msg>Add `Ray::refract()`<commit_after>use math::{Point, Vector};

use cgmath::prelude::*;
use cgmath::{ApproxEq, dot};

/// A ray of light traveling through our scene.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Ray {
    pub origin: Point,
    pub direction: Vector,
}

impl Ray {
    pub fn new(origin: Point, direction: Vector) -> Ray {
        debug_assert!(direction.magnitude().approx_eq(&1.0),
                      "Ray direction is not normalized. (|{:?}| == {:?} != 1.0)",
                      direction,
                      direction.magnitude());

        Ray {
            origin: origin,
            direction: direction,
        }
    }

    /// Get the position of traveling `distance` along the ray.
    pub fn evaluate(&self, distance: f32) -> Point {
        self.origin + self.direction * distance
    }

    /// Calculates the ray we get by reflecting it from `intersection` with the
    /// specified normal.
    pub fn reflect(&self, normal: Vector, intersection: Point) -> Ray {
        let new_direction =
            self.direction - 2f32 * dot(self.direction, normal) * normal;

        Ray {
            origin: intersection,
            direction: new_direction,
        }
    }

    pub fn refract(&self, normal: Vector, intersection: Point, ior_from: f32, ior_to: f32)
        -> Option<Ray> {
        let ratio = ior_from / ior_to;
        let cos_in = self.direction.dot(normal);
        let k = 1.0 - ratio.powi(2) - (1.0 - cos_in.powi(2));

        if k < 0.0 {
            return None;
        }

        let new_direction = ratio * self.direction + normal * (ratio * cos_in * k.sqrt());

        Some(Ray {
            origin: intersection,
            direction: new_direction,
        })
    }
}

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

    #[test]
    fn test_reflect() {
        let ray = Ray::new(vec3(-1.0, 1.0, 0.0), vec3(1.0, -1.0, 0.0).normalize());
        let normal = vec3(0.0, 1.0, 0.0);
        let intersection = vec3(0.0, 0.0, 0.0);

        let result = Ray::new(vec3(0.0, 0.0, 0.0), vec3(1.0, 1.0, 0.0).normalize());
        assert_eq!(ray.reflect(normal, intersection), result);
    }
}
<|endoftext|>