<commit_before>use basetypes::*;
use position::castling_rights::*;

// "Move" represents a move on the chessboard. It contains 3 types of
// information:
//
// 1. Information about the played move itself.
//
// 2. Information needed so as to be able to undo the move and restore
// the board into the exact same state as before.
//
// 3. The move score -- moves with higher score are tried
// first. Ideally the best move should have the highest score.
//
// "Move" is a 32-bit unsigned number. The lowest 16 bits contain the
// whole needed information about the move itself (type 1). And is
// laid out the following way:
//
//   15                                                           0
//  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
//  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
//  | Move  |    Origin square      |   Destination square  | Aux   |
//  | type  |       6 bits          |        6 bits         | data  |
//  | 2 bits|   |   |   |   |   |   |   |   |   |   |   |   | 2 bits|
//  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |       |
//  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
//
// There are 4 "move type"s: 0) normal move; 1) en-passant capture; 2)
// pawn promotion; 3) castling. "Aux data" encodes the type of the
// promoted piece if the move type is pawn promotion, otherwise it
// encodes castling rights (see below).
//
// The highest 16 bits contain the rest ot the info:
//
//   31                                                          16
//  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
//  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
//  |  Move score   |  Captured |  Played   | Cast- |   En-passant  |
//  |    4 bits     |  piece    |  piece    | ling  |      file     |
//  |   |   |   |   |  3 bits   |  3 bits   | 2 bits|     4 bits    |
//  |   |   |   |   |   |   |   |   |   |   |       |   |   |   |   |
//  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
//
// "En-passant file" tells on what vertical line (if any) on the board
// there was a passing pawn before the move was played.
//
// Castling rights are a bit complex. The castling rights for the side
// that makes the move, before the move was made, are stored in the
// "Aux data" field. This is OK, because promoting a pawn never
// changes the moving player's castling rights. The castling rights
// for the opposite side are stored in "Castling" field. (A move can
// change the castling rights for the other side when a rook in the
// corner is captured.)
//
// When "Captured piece" is stored, its bits are inverted, so that
// MVV-LVA (Most valuable victim -- least valuable aggressor) ordering
// of the moves is preserved, even when the "Move score" field stays
// the same.

const M_SHIFT_SCORE: u32 = 28;
const M_SHIFT_CAPTURED_PIECE: u32 = 25;
const M_SHIFT_PIECE: u32 = 22;
const M_SHIFT_CASTLING_DATA: u32 = 20;
const M_SHIFT_ENPASSANT_FILE: u32 = 16;
const M_SHIFT_MOVE_TYPE: u32 = 14;
const M_SHIFT_ORIG_SQUARE: u32 = 8;
const M_SHIFT_DEST_SQUARE: u32 = 2;
const M_SHIFT_AUX_DATA: u32 = 0;

const M_MASK_SCORE: u32 = 0b1111 << M_SHIFT_SCORE;
const M_MASK_CAPTURED_PIECE: u32 = 0b111 << M_SHIFT_CAPTURED_PIECE;
const M_MASK_PIECE: u32 = 0b111 << M_SHIFT_PIECE;
const M_MASK_CASTLING_DATA: u32 = 0b11 << M_SHIFT_CASTLING_DATA;
const M_MASK_ENPASSANT_FILE: u32 = 0b1111 << M_SHIFT_ENPASSANT_FILE;
const M_MASK_MOVE_TYPE: u32 = 0b11 << M_SHIFT_MOVE_TYPE;
const M_MASK_ORIG_SQUARE: u32 = 0b111111 << M_SHIFT_ORIG_SQUARE;
const M_MASK_DEST_SQUARE: u32 = 0b111111 << M_SHIFT_DEST_SQUARE;
const M_MASK_AUX_DATA: u32 = 0b11 << M_SHIFT_AUX_DATA;

pub const NO_ENPASSANT_FILE: Rank = 8;

#[derive(Debug)]
#[derive(Clone, Copy)]
#[derive(PartialOrd, Ord, PartialEq, Eq)]
pub struct Move(u32);

impl Move {
    #[inline(always)]
    pub fn new(us: Color,
               score: usize,
               move_type: MoveType,
               piece: PieceType,
               orig_square: Square,
               dest_square: Square,
               captured_piece: PieceType,
               en_passant_file: File,
               castling: CastlingRights,
               promoted_piece_code: usize)
               -> Move {
        assert!(us <= 1);
        assert!(score <= 0b1111);
        assert!(move_type <= 0x11);
        assert!(piece < NO_PIECE);
        assert!(orig_square <= 63);
        assert!(dest_square <= 63);
        assert!(captured_piece != KING && captured_piece <= NO_PIECE);
        assert!(en_passant_file <= 0b1000);
        assert!(promoted_piece_code <= 0b11);
        let aux_data = match move_type {
            MOVE_PROMOTION => promoted_piece_code,
            _ => castling.get_for(us),
        };
        Move((score << M_SHIFT_SCORE | (!captured_piece & 0b111) << M_SHIFT_CAPTURED_PIECE |
              piece << M_SHIFT_PIECE |
              castling.get_for(1 ^ us) << M_SHIFT_CASTLING_DATA |
              en_passant_file << M_SHIFT_ENPASSANT_FILE |
              move_type << M_SHIFT_MOVE_TYPE | orig_square << M_SHIFT_ORIG_SQUARE |
              dest_square << M_SHIFT_DEST_SQUARE |
              aux_data << M_SHIFT_AUX_DATA) as u32)
    }

    #[inline(always)]
    pub fn set_score(&mut self, score: usize) {
        assert!(score <= 0b1111);
        self.0 &= !M_MASK_SCORE;
        self.0 |= (score << M_SHIFT_SCORE) as u32;
    }

    #[inline(always)]
    pub fn set_score_bit(&mut self, b: usize) {
        assert!(b <= 3);
        self.0 |= 1 << b << M_SHIFT_SCORE;
    }

    #[inline(always)]
    pub fn clear_score_bit(&mut self, b: usize) {
        assert!(b <= 3);
        self.0 &= !(1 << b << M_SHIFT_SCORE);
    }

    #[inline(always)]
    pub fn score(&self) -> usize {
        ((self.0 & M_MASK_SCORE) >> M_SHIFT_SCORE) as usize
    }

    #[inline(always)]
    pub fn move_type(&self) -> MoveType {
        ((self.0 & M_MASK_MOVE_TYPE) >> M_SHIFT_MOVE_TYPE) as MoveType
    }

    #[inline(always)]
    pub fn piece(&self) -> PieceType {
        ((self.0 & M_MASK_PIECE) >> M_SHIFT_PIECE) as PieceType
    }

    #[inline(always)]
    pub fn orig_square(&self) -> Square {
        ((self.0 & M_MASK_ORIG_SQUARE) >> M_SHIFT_ORIG_SQUARE) as Square
    }

    #[inline(always)]
    pub fn dest_square(&self) -> Square {
        ((self.0 & M_MASK_DEST_SQUARE) >> M_SHIFT_DEST_SQUARE) as Square
    }

    #[inline(always)]
    pub fn captured_piece(&self) -> PieceType {
        ((!self.0 & M_MASK_CAPTURED_PIECE) >> M_SHIFT_CAPTURED_PIECE) as PieceType
    }

    #[inline(always)]
    pub fn en_passant_file(&self) -> File {
        ((self.0 & M_MASK_ENPASSANT_FILE) >> M_SHIFT_ENPASSANT_FILE) as File
    }

    #[inline(always)]
    pub fn castling_data(&self) -> usize {
        ((self.0 & M_MASK_CASTLING_DATA) >> M_SHIFT_CASTLING_DATA) as usize
    }

    #[inline(always)]
    pub fn aux_data(&self) -> usize {
        ((self.0 & M_MASK_AUX_DATA) >> M_SHIFT_AUX_DATA) as usize
    }

    #[inline(always)]
    pub fn piece_from_aux_data(pp_code: usize) -> PieceType {
        match pp_code {
            0 => QUEEN,
            1 => ROOK,
            2 => BISHOP,
            3 => KNIGHT,
            _ => panic!("invalid promoted piece code"),
        }
    }
}

pub struct MoveStack {
    stack: [Move; MOVE_STACK_SIZE],
    next_index: usize,
}

impl MoveStack {
    pub fn new() -> MoveStack {
        use std::mem::uninitialized;
        unsafe {
            MoveStack {
                stack: uninitialized(),
                next_index: 0,
            }
        }
    }

    #[inline(always)]
    pub fn push(&mut self, m: Move) {
        self.stack[self.next_index] = m;
        self.next_index += 1;
    }

    #[inline(always)]
    pub fn pop(&mut self) -> Option<Move> {
        if self.next_index == 0 {
            None
        } else {
            self.next_index -= 1;
            Some(self.stack[self.next_index])
        }
    }

    #[inline(always)]
    pub fn remove_all(&mut self) -> usize {
        let count = self.count();
        self.next_index = 0;
        count
    }

    #[inline(always)]
    pub fn count(&self) -> usize {
        self.next_index
    }

}

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

    #[test]
    fn test_move() {
        use basetypes::*;

        let mut cr = CastlingRights::new();
        cr.set_for(WHITE, 0b10);
        cr.set_for(BLACK, 0b11);
        let mut m = Move::new(WHITE,
                              12,
                              MOVE_NORMAL,
                              PAWN,
                              E2,
                              E4,
                              NO_PIECE,
                              NO_ENPASSANT_FILE,
                              cr,
                              0);
        let n1 = Move::new(WHITE,
                           12,
                           MOVE_NORMAL,
                           PAWN,
                           F3,
                           E4,
                           KNIGHT,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           0);
        let n2 = Move::new(WHITE,
                           12,
                           MOVE_NORMAL,
                           KING,
                           F3,
                           E4,
                           NO_PIECE,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           0);
        let n3 = Move::new(BLACK,
                           0,
                           MOVE_PROMOTION,
                           PAWN,
                           F2,
                           F1,
                           NO_PIECE,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           1);
        assert!(n1 > m);
        assert!(n2 < m);
        assert_eq!(m.score(), 12);
        assert_eq!(m.piece(), PAWN);
        assert_eq!(m.captured_piece(), NO_PIECE);
        assert_eq!(m.orig_square(), E2);
        assert_eq!(m.dest_square(), E4);
        assert_eq!(m.en_passant_file(), 8);
        assert_eq!(m.aux_data(), 0b10);
        assert_eq!(m.castling_data(), 0b11);
        let m2 = m;
        assert_eq!(m, m2);
        m.set_score(13);
        assert_eq!(m.score(), 13);
        assert!(m > m2);
        m.clear_score_bit(0);
        assert_eq!(m, m2);
        m.set_score_bit(0);
        assert_eq!(m.score(), 13);
        m.set_score(0);
        assert_eq!(m.score(), 0);
        assert_eq!(n3.aux_data(), 1);
    }
}
<commit_msg>shufling code<commit_after>use basetypes::*;
use position::castling_rights::*;

// "Move" represents a move on the chessboard. It contains 3 types of
// information:
//
// 1. Information about the played move itself.
//
// 2. Information needed so as to be able to undo the move and restore
// the board into the exact same state as before.
//
// 3. The move score -- moves with higher score are tried
// first. Ideally the best move should have the highest score.
//
// "Move" is a 32-bit unsigned number. The lowest 16 bits contain the
// whole needed information about the move itself (type 1). And is
// laid out the following way:
//
//   15                                                           0
//  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
//  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
//  | Move  |    Origin square      |   Destination square  | Aux   |
//  | type  |       6 bits          |        6 bits         | data  |
//  | 2 bits|   |   |   |   |   |   |   |   |   |   |   |   | 2 bits|
//  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |       |
//  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
//
// There are 4 "move type"s: 0) normal move; 1) en-passant capture; 2)
// pawn promotion; 3) castling. "Aux data" encodes the type of the
// promoted piece if the move type is pawn promotion, otherwise it
// encodes castling rights (see below).
//
// The highest 16 bits contain the rest ot the info:
//
//   31                                                          16
//  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
//  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
//  |  Move score   |  Captured |  Played   | Cast- |   En-passant  |
//  |    4 bits     |  piece    |  piece    | ling  |      file     |
//  |   |   |   |   |  3 bits   |  3 bits   | 2 bits|     4 bits    |
//  |   |   |   |   |   |   |   |   |   |   |       |   |   |   |   |
//  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
//
// "En-passant file" tells on what vertical line (if any) on the board
// there was a passing pawn before the move was played.
//
// Castling rights are a bit complex. The castling rights for the side
// that makes the move, before the move was made, are stored in the
// "Aux data" field. This is OK, because promoting a pawn never
// changes the moving player's castling rights. The castling rights
// for the opposite side are stored in "Castling" field. (A move can
// change the castling rights for the other side when a rook in the
// corner is captured.)
//
// When "Captured piece" is stored, its bits are inverted, so that
// MVV-LVA (Most valuable victim -- least valuable aggressor) ordering
// of the moves is preserved, even when the "Move score" field stays
// the same.
#[derive(Debug)]
#[derive(Clone, Copy)]
#[derive(PartialOrd, Ord, PartialEq, Eq)]
pub struct Move(u32);

impl Move {
    #[inline(always)]
    pub fn new(us: Color,
               score: usize,
               move_type: MoveType,
               piece: PieceType,
               orig_square: Square,
               dest_square: Square,
               captured_piece: PieceType,
               en_passant_file: File,
               castling: CastlingRights,
               promoted_piece_code: usize)
               -> Move {
        assert!(us <= 1);
        assert!(score <= 0b1111);
        assert!(move_type <= 0x11);
        assert!(piece < NO_PIECE);
        assert!(orig_square <= 63);
        assert!(dest_square <= 63);
        assert!(captured_piece != KING && captured_piece <= NO_PIECE);
        assert!(en_passant_file <= 0b1000);
        assert!(promoted_piece_code <= 0b11);
        let aux_data = match move_type {
            MOVE_PROMOTION => promoted_piece_code,
            _ => castling.get_for(us),
        };
        Move((score << M_SHIFT_SCORE | (!captured_piece & 0b111) << M_SHIFT_CAPTURED_PIECE |
              piece << M_SHIFT_PIECE |
              castling.get_for(1 ^ us) << M_SHIFT_CASTLING_DATA |
              en_passant_file << M_SHIFT_ENPASSANT_FILE |
              move_type << M_SHIFT_MOVE_TYPE | orig_square << M_SHIFT_ORIG_SQUARE |
              dest_square << M_SHIFT_DEST_SQUARE |
              aux_data << M_SHIFT_AUX_DATA) as u32)
    }

    #[inline(always)]
    pub fn set_score(&mut self, score: usize) {
        assert!(score <= 0b1111);
        self.0 &= !M_MASK_SCORE;
        self.0 |= (score << M_SHIFT_SCORE) as u32;
    }

    #[inline(always)]
    pub fn set_score_bit(&mut self, b: usize) {
        assert!(b <= 3);
        self.0 |= 1 << b << M_SHIFT_SCORE;
    }

    #[inline(always)]
    pub fn clear_score_bit(&mut self, b: usize) {
        assert!(b <= 3);
        self.0 &= !(1 << b << M_SHIFT_SCORE);
    }

    #[inline(always)]
    pub fn score(&self) -> usize {
        ((self.0 & M_MASK_SCORE) >> M_SHIFT_SCORE) as usize
    }

    #[inline(always)]
    pub fn move_type(&self) -> MoveType {
        ((self.0 & M_MASK_MOVE_TYPE) >> M_SHIFT_MOVE_TYPE) as MoveType
    }

    #[inline(always)]
    pub fn piece(&self) -> PieceType {
        ((self.0 & M_MASK_PIECE) >> M_SHIFT_PIECE) as PieceType
    }

    #[inline(always)]
    pub fn orig_square(&self) -> Square {
        ((self.0 & M_MASK_ORIG_SQUARE) >> M_SHIFT_ORIG_SQUARE) as Square
    }

    #[inline(always)]
    pub fn dest_square(&self) -> Square {
        ((self.0 & M_MASK_DEST_SQUARE) >> M_SHIFT_DEST_SQUARE) as Square
    }

    #[inline(always)]
    pub fn captured_piece(&self) -> PieceType {
        ((!self.0 & M_MASK_CAPTURED_PIECE) >> M_SHIFT_CAPTURED_PIECE) as PieceType
    }

    #[inline(always)]
    pub fn en_passant_file(&self) -> File {
        ((self.0 & M_MASK_ENPASSANT_FILE) >> M_SHIFT_ENPASSANT_FILE) as File
    }

    #[inline(always)]
    pub fn castling_data(&self) -> usize {
        ((self.0 & M_MASK_CASTLING_DATA) >> M_SHIFT_CASTLING_DATA) as usize
    }

    #[inline(always)]
    pub fn aux_data(&self) -> usize {
        ((self.0 & M_MASK_AUX_DATA) >> M_SHIFT_AUX_DATA) as usize
    }

    #[inline(always)]
    pub fn piece_from_aux_data(pp_code: usize) -> PieceType {
        match pp_code {
            0 => QUEEN,
            1 => ROOK,
            2 => BISHOP,
            3 => KNIGHT,
            _ => panic!("invalid promoted piece code"),
        }
    }
}

// Represents no en-passant file.
pub const NO_ENPASSANT_FILE: Rank = 8;

const M_SHIFT_SCORE: u32 = 28;
const M_SHIFT_CAPTURED_PIECE: u32 = 25;
const M_SHIFT_PIECE: u32 = 22;
const M_SHIFT_CASTLING_DATA: u32 = 20;
const M_SHIFT_ENPASSANT_FILE: u32 = 16;
const M_SHIFT_MOVE_TYPE: u32 = 14;
const M_SHIFT_ORIG_SQUARE: u32 = 8;
const M_SHIFT_DEST_SQUARE: u32 = 2;
const M_SHIFT_AUX_DATA: u32 = 0;

const M_MASK_SCORE: u32 = 0b1111 << M_SHIFT_SCORE;
const M_MASK_CAPTURED_PIECE: u32 = 0b111 << M_SHIFT_CAPTURED_PIECE;
const M_MASK_PIECE: u32 = 0b111 << M_SHIFT_PIECE;
const M_MASK_CASTLING_DATA: u32 = 0b11 << M_SHIFT_CASTLING_DATA;
const M_MASK_ENPASSANT_FILE: u32 = 0b1111 << M_SHIFT_ENPASSANT_FILE;
const M_MASK_MOVE_TYPE: u32 = 0b11 << M_SHIFT_MOVE_TYPE;
const M_MASK_ORIG_SQUARE: u32 = 0b111111 << M_SHIFT_ORIG_SQUARE;
const M_MASK_DEST_SQUARE: u32 = 0b111111 << M_SHIFT_DEST_SQUARE;
const M_MASK_AUX_DATA: u32 = 0b11 << M_SHIFT_AUX_DATA;

pub struct MoveStack {
    stack: [Move; MOVE_STACK_SIZE],
    next_index: usize,
}

impl MoveStack {
    pub fn new() -> MoveStack {
        use std::mem::uninitialized;
        unsafe {
            MoveStack {
                stack: uninitialized(),
                next_index: 0,
            }
        }
    }

    #[inline(always)]
    pub fn push(&mut self, m: Move) {
        self.stack[self.next_index] = m;
        self.next_index += 1;
    }

    #[inline(always)]
    pub fn pop(&mut self) -> Option<Move> {
        if self.next_index == 0 {
            None
        } else {
            self.next_index -= 1;
            Some(self.stack[self.next_index])
        }
    }

    #[inline(always)]
    pub fn remove_all(&mut self) -> usize {
        let count = self.count();
        self.next_index = 0;
        count
    }

    #[inline(always)]
    pub fn count(&self) -> usize {
        self.next_index
    }

}

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

    #[test]
    fn test_move() {
        use basetypes::*;

        let mut cr = CastlingRights::new();
        cr.set_for(WHITE, 0b10);
        cr.set_for(BLACK, 0b11);
        let mut m = Move::new(WHITE,
                              12,
                              MOVE_NORMAL,
                              PAWN,
                              E2,
                              E4,
                              NO_PIECE,
                              NO_ENPASSANT_FILE,
                              cr,
                              0);
        let n1 = Move::new(WHITE,
                           12,
                           MOVE_NORMAL,
                           PAWN,
                           F3,
                           E4,
                           KNIGHT,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           0);
        let n2 = Move::new(WHITE,
                           12,
                           MOVE_NORMAL,
                           KING,
                           F3,
                           E4,
                           NO_PIECE,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           0);
        let n3 = Move::new(BLACK,
                           0,
                           MOVE_PROMOTION,
                           PAWN,
                           F2,
                           F1,
                           NO_PIECE,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           1);
        assert!(n1 > m);
        assert!(n2 < m);
        assert_eq!(m.score(), 12);
        assert_eq!(m.piece(), PAWN);
        assert_eq!(m.captured_piece(), NO_PIECE);
        assert_eq!(m.orig_square(), E2);
        assert_eq!(m.dest_square(), E4);
        assert_eq!(m.en_passant_file(), 8);
        assert_eq!(m.aux_data(), 0b10);
        assert_eq!(m.castling_data(), 0b11);
        let m2 = m;
        assert_eq!(m, m2);
        m.set_score(13);
        assert_eq!(m.score(), 13);
        assert!(m > m2);
        m.clear_score_bit(0);
        assert_eq!(m, m2);
        m.set_score_bit(0);
        assert_eq!(m.score(), 13);
        m.set_score(0);
        assert_eq!(m.score(), 0);
        assert_eq!(n3.aux_data(), 1);
    }
}
<|endoftext|>


<commit_before>//! 2D grid with neighbors iter and custom internal coordinate.

mod iter;
mod coord;
mod test;

use std::cmp;
use std::mem;
use std::ops::{Deref, DerefMut};

use scoped_threadpool::Pool;

use traits::Grid;
use traits::Cell;
use traits::EvolutionState;
use traits::Nhood;
use traits::Coord;

use self::iter::Iter;
pub use self::coord::GridCoord;

/// 2D grid. Implemented with two buffers.
/// They are swapped on every evolution step.
/// Old buffer is used for read-only neighbors data.
/// New buffer is writable and mutated through update process.
/// Grid uses one-dimensional `Vec` to store cells.
pub struct TwodimGrid<C, N, Es>
    where C: Cell<State = Es> + Clone,
          N: Nhood<Coord = GridCoord>,
          Es: EvolutionState,
{
    cells: Vec<C>,
    old_cells: Vec<C>,
    evolution_state: Es,
    nhood: N,
    neighbors: Vec<Vec<Option<usize>>>,
    dimensions: GridCoord,
    rows: u32,
    cols: u32,
    pool: Pool,
    parts: Vec<(usize, usize)>,
}

impl<C, N, Es> TwodimGrid<C, N, Es>
    where C: Cell<State = Es> + Clone,
          N: Nhood<Coord = GridCoord>,
          Es: EvolutionState,
{
    /// Constructs TwodimGrid with given ROWSxCOLS, neighborhood
    /// strategy, initial evolution state, threads count.
    pub fn new(rows: u32, cols: u32, nhood: N, state: C::State, threads: u32) -> Self {

        let len = (rows * cols) as usize;

        let cells = Vec::with_capacity(len);
        let old_cells = Vec::with_capacity(len);
        let neighbors = Vec::with_capacity(len);

        let pool = Pool::new(threads);

        let mut grid = TwodimGrid {
            cells: cells,
            old_cells: old_cells,
            evolution_state: state,
            nhood: nhood,
            neighbors: neighbors,
            rows: rows,
            cols: cols,
            dimensions: GridCoord::from_2d(cols as i32, rows as i32),
            pool: pool,
            parts: Vec::new(),
        };

        grid.init();

        grid
    }

    fn init(&mut self) {

        let cells_count = self.rows * self.cols;

        for offset in 0..cells_count {

            let coord = GridCoord::from_offset(offset, self.rows, self.cols);

            // init neighbors
            let neighbors = self.get_neighbors(&coord);
            self.neighbors.push(neighbors);

            // init cells
            let cell = C::with_coord(coord);
            self.cells.push(cell.clone());
            self.old_cells.push(cell.clone());
        }

        // Init split border indices.
        // Used later in `update` to split `cells` between threads.
        let cells_on_thread = cells_count / self.pool.thread_count();
        println!("{:?}", cells_on_thread);
        let mut start = 0;
        let mut end = cells_on_thread;
        // Emulating `do-while` loop.
        while {
            self.parts.push((start as usize, end as usize));
            start = end + 1;
            end = cmp::min(start + cells_on_thread, cells_count);
            end < cells_count
        } {}
        println!("{:?}", self.parts);
    }

    fn get_neighbors(&self, coord: &GridCoord) -> Vec<Option<usize>> {

        let neighbors_count = self.nhood.neighbors_count();
        let mut neighbors = Vec::with_capacity(neighbors_count);

        let cols = self.cols as i32;
        let rows = self.rows as i32;

        for coord in &self.nhood.neighbors(coord) {

            if coord.x() >= 0 && coord.x() < cols && coord.y() >= 0 && coord.y() < rows {
                neighbors.push(Some(self.offset(coord)));
            } else {
                neighbors.push(None);
            }
        }

        neighbors
    }

    #[inline]
    fn offset<Crd: Coord>(&self, coord: &Crd) -> usize {
        (coord.y() * self.cols as i32 + coord.x()) as usize
    }
}

/// Helper struct to enable sendable mutable pointers.
struct MutPtr<T: ?Sized>(*mut T);

unsafe impl<T: ?Sized> Send for MutPtr<T> {}
unsafe impl<T: ?Sized> Sync for MutPtr<T> {}

impl<T: ?Sized> Deref for MutPtr<T> {
    type Target = T;
    fn deref(&self) -> &T { unsafe { &*self.0 } }
}

impl<T: ?Sized> DerefMut for MutPtr<T> {
    fn deref_mut(&mut self) -> &mut T { unsafe { &mut *self.0 } }
}

#[allow(expl_impl_clone_on_copy)]
impl<T: ?Sized> Clone for MutPtr<T> {
    fn clone(&self) -> Self { MutPtr(self.0) }
}

impl<T: ?Sized> Copy for MutPtr<T> {}

/// Helper struct to enable sendable const pointers.
struct ConstPtr<T: ?Sized>(*const T);

unsafe impl<T: ?Sized> Send for ConstPtr<T> {}
unsafe impl<T: ?Sized> Sync for ConstPtr<T> {}

impl<T: ?Sized> Deref for ConstPtr<T> {
    type Target = T;
    fn deref(&self) -> &T { unsafe { &*self.0 } }
}

#[allow(expl_impl_clone_on_copy)]
impl<T: ?Sized> Clone for ConstPtr<T> {
    fn clone(&self) -> Self { ConstPtr(self.0) }
}

impl<T: ?Sized> Copy for ConstPtr<T> {}

impl<C, N, Es> Grid for TwodimGrid<C, N, Es>
    where C: Cell<State = Es> + Clone,
          N: Nhood<Coord = GridCoord>,
          Es: EvolutionState + Send,
{
    type Cell = C;
    type Coord = GridCoord;

    fn update(&mut self) {
        mem::swap(&mut self.cells, &mut self.old_cells);

        let mut cells = MutPtr(&mut *self.cells as *mut [C]);
        let old_cells = ConstPtr(&*self.old_cells as *const [C]);
        let neighbors = ConstPtr(&*self.neighbors as *const [Vec<Option<usize>>]);
        let neighbors_count = self.nhood.neighbors_count();
        let evolution_state = ConstPtr(&self.evolution_state as *const Es);

        let parts = &self.parts;

        self.pool.scoped(|scope| {
            for &(start, end) in parts {
                scope.execute(move || {
                    for i in start..end {
                        unsafe {
                            let neighbors = neighbors.get_unchecked(i);
                            let neighbors_iter = Iter::new(&*old_cells, neighbors, neighbors_count);

                            let old = (*old_cells).get_unchecked(i);
                            let cell = (*cells).get_unchecked_mut(i);
                            cell.update(old, neighbors_iter, &*evolution_state);
                        }
                    }
                });
            }
        });

        self.evolution_state.update();
    }

    fn set_cells(&mut self, new_cells: Vec<Self::Cell>) {

        for cell in new_cells.into_iter() {

            let index;

            {
                index = self.offset(cell.coord());
            }

            self.cells[index] = cell;
        }
    }

    fn cells(&self) -> &Vec<Self::Cell> { &self.cells }

    fn state(&self) -> &<<Self as Grid>::Cell as Cell>::State { &self.evolution_state }

    fn dimensions(&self) -> Self::Coord { self.dimensions.clone() }
}
<commit_msg>Removed println statements.<commit_after>//! 2D grid with neighbors iter and custom internal coordinate.

mod iter;
mod coord;
mod test;

use std::cmp;
use std::mem;
use std::ops::{Deref, DerefMut};

use scoped_threadpool::Pool;

use traits::Grid;
use traits::Cell;
use traits::EvolutionState;
use traits::Nhood;
use traits::Coord;

use self::iter::Iter;
pub use self::coord::GridCoord;

/// 2D grid. Implemented with two buffers.
/// They are swapped on every evolution step.
/// Old buffer is used for read-only neighbors data.
/// New buffer is writable and mutated through update process.
/// Grid uses one-dimensional `Vec` to store cells.
pub struct TwodimGrid<C, N, Es>
    where C: Cell<State = Es> + Clone,
          N: Nhood<Coord = GridCoord>,
          Es: EvolutionState,
{
    cells: Vec<C>,
    old_cells: Vec<C>,
    evolution_state: Es,
    nhood: N,
    neighbors: Vec<Vec<Option<usize>>>,
    dimensions: GridCoord,
    rows: u32,
    cols: u32,
    pool: Pool,
    parts: Vec<(usize, usize)>,
}

impl<C, N, Es> TwodimGrid<C, N, Es>
    where C: Cell<State = Es> + Clone,
          N: Nhood<Coord = GridCoord>,
          Es: EvolutionState,
{
    /// Constructs TwodimGrid with given ROWSxCOLS, neighborhood
    /// strategy, initial evolution state, threads count.
    pub fn new(rows: u32, cols: u32, nhood: N, state: C::State, threads: u32) -> Self {

        let len = (rows * cols) as usize;

        let cells = Vec::with_capacity(len);
        let old_cells = Vec::with_capacity(len);
        let neighbors = Vec::with_capacity(len);

        let pool = Pool::new(threads);

        let mut grid = TwodimGrid {
            cells: cells,
            old_cells: old_cells,
            evolution_state: state,
            nhood: nhood,
            neighbors: neighbors,
            rows: rows,
            cols: cols,
            dimensions: GridCoord::from_2d(cols as i32, rows as i32),
            pool: pool,
            parts: Vec::new(),
        };

        grid.init();

        grid
    }

    fn init(&mut self) {

        let cells_count = self.rows * self.cols;

        for offset in 0..cells_count {

            let coord = GridCoord::from_offset(offset, self.rows, self.cols);

            // init neighbors
            let neighbors = self.get_neighbors(&coord);
            self.neighbors.push(neighbors);

            // init cells
            let cell = C::with_coord(coord);
            self.cells.push(cell.clone());
            self.old_cells.push(cell.clone());
        }

        // Init split border indices.
        // Used later in `update` to split `cells` between threads.
        let cells_on_thread = cells_count / self.pool.thread_count();
        let mut start = 0;
        let mut end = cells_on_thread;
        // Emulating `do-while` loop.
        while {
            self.parts.push((start as usize, end as usize));
            start = end + 1;
            end = cmp::min(start + cells_on_thread, cells_count);
            end < cells_count
        } {}
    }

    fn get_neighbors(&self, coord: &GridCoord) -> Vec<Option<usize>> {

        let neighbors_count = self.nhood.neighbors_count();
        let mut neighbors = Vec::with_capacity(neighbors_count);

        let cols = self.cols as i32;
        let rows = self.rows as i32;

        for coord in &self.nhood.neighbors(coord) {

            if coord.x() >= 0 && coord.x() < cols && coord.y() >= 0 && coord.y() < rows {
                neighbors.push(Some(self.offset(coord)));
            } else {
                neighbors.push(None);
            }
        }

        neighbors
    }

    #[inline]
    fn offset<Crd: Coord>(&self, coord: &Crd) -> usize {
        (coord.y() * self.cols as i32 + coord.x()) as usize
    }
}

/// Helper struct to enable sendable mutable pointers.
struct MutPtr<T: ?Sized>(*mut T);

unsafe impl<T: ?Sized> Send for MutPtr<T> {}
unsafe impl<T: ?Sized> Sync for MutPtr<T> {}

impl<T: ?Sized> Deref for MutPtr<T> {
    type Target = T;
    fn deref(&self) -> &T { unsafe { &*self.0 } }
}

impl<T: ?Sized> DerefMut for MutPtr<T> {
    fn deref_mut(&mut self) -> &mut T { unsafe { &mut *self.0 } }
}

#[allow(expl_impl_clone_on_copy)]
impl<T: ?Sized> Clone for MutPtr<T> {
    fn clone(&self) -> Self { MutPtr(self.0) }
}

impl<T: ?Sized> Copy for MutPtr<T> {}

/// Helper struct to enable sendable const pointers.
struct ConstPtr<T: ?Sized>(*const T);

unsafe impl<T: ?Sized> Send for ConstPtr<T> {}
unsafe impl<T: ?Sized> Sync for ConstPtr<T> {}

impl<T: ?Sized> Deref for ConstPtr<T> {
    type Target = T;
    fn deref(&self) -> &T { unsafe { &*self.0 } }
}

#[allow(expl_impl_clone_on_copy)]
impl<T: ?Sized> Clone for ConstPtr<T> {
    fn clone(&self) -> Self { ConstPtr(self.0) }
}

impl<T: ?Sized> Copy for ConstPtr<T> {}

impl<C, N, Es> Grid for TwodimGrid<C, N, Es>
    where C: Cell<State = Es> + Clone,
          N: Nhood<Coord = GridCoord>,
          Es: EvolutionState + Send,
{
    type Cell = C;
    type Coord = GridCoord;

    fn update(&mut self) {
        mem::swap(&mut self.cells, &mut self.old_cells);

        let mut cells = MutPtr(&mut *self.cells as *mut [C]);
        let old_cells = ConstPtr(&*self.old_cells as *const [C]);
        let neighbors = ConstPtr(&*self.neighbors as *const [Vec<Option<usize>>]);
        let neighbors_count = self.nhood.neighbors_count();
        let evolution_state = ConstPtr(&self.evolution_state as *const Es);

        let parts = &self.parts;

        self.pool.scoped(|scope| {
            for &(start, end) in parts {
                scope.execute(move || {
                    for i in start..end {
                        unsafe {
                            let neighbors = neighbors.get_unchecked(i);
                            let neighbors_iter = Iter::new(&*old_cells, neighbors, neighbors_count);

                            let old = (*old_cells).get_unchecked(i);
                            let cell = (*cells).get_unchecked_mut(i);
                            cell.update(old, neighbors_iter, &*evolution_state);
                        }
                    }
                });
            }
        });

        self.evolution_state.update();
    }

    fn set_cells(&mut self, new_cells: Vec<Self::Cell>) {

        for cell in new_cells.into_iter() {

            let index;

            {
                index = self.offset(cell.coord());
            }

            self.cells[index] = cell;
        }
    }

    fn cells(&self) -> &Vec<Self::Cell> { &self.cells }

    fn state(&self) -> &<<Self as Grid>::Cell as Cell>::State { &self.evolution_state }

    fn dimensions(&self) -> Self::Coord { self.dimensions.clone() }
}
<|endoftext|>


<commit_before>use crate::syntax::qualified::QualifiedName;
use crate::syntax::Api;
#[cfg(test)]
use proc_macro2::Span;
use quote::IdentFragment;
use std::fmt::{self, Display};
use std::slice::Iter;
use syn::parse::{Parse, ParseStream, Result};
use syn::{Ident, Token};

mod kw {
    syn::custom_keyword!(namespace);
}

#[derive(Clone)]
pub struct Namespace {
    segments: Vec<Ident>,
}

impl Namespace {
    pub fn none() -> Self {
        Namespace {
            segments: Vec::new(),
        }
    }

    pub fn iter(&self) -> Iter<Ident> {
        self.segments.iter()
    }

    pub fn parse_bridge_attr_namespace(input: ParseStream) -> Result<Namespace> {
        if input.is_empty() {
            return Ok(Namespace::none());
        }

        input.parse::<kw::namespace>()?;
        input.parse::<Token![=]>()?;
        let ns = input.parse::<Namespace>()?;
        input.parse::<Option<Token![,]>>()?;
        Ok(ns)
    }

    #[cfg(test)]
    pub fn from_str(ns: &str) -> Self {
        Namespace {
            segments: ns
                .split("::")
                .map(|x| Ident::new(x, Span::call_site()))
                .collect(),
        }
    }
}

impl Parse for Namespace {
    fn parse(input: ParseStream) -> Result<Self> {
        let segments = QualifiedName::parse_quoted_or_unquoted(input)?.segments;
        Ok(Namespace { segments })
    }
}

impl Display for Namespace {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for segment in self {
            write!(f, "{}$", segment)?;
        }
        Ok(())
    }
}

impl IdentFragment for Namespace {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(self, f)
    }
}

impl<'a> IntoIterator for &'a Namespace {
    type Item = &'a Ident;
    type IntoIter = Iter<'a, Ident>;
    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl Api {
    pub fn get_namespace(&self) -> Option<&Namespace> {
        match self {
            Api::CxxFunction(cfn) => Some(&cfn.ident.cxx.ns),
            Api::CxxType(cty) => Some(&cty.ident.cxx.ns),
            Api::Enum(enm) => Some(&enm.ident.cxx.ns),
            Api::Struct(strct) => Some(&strct.ident.cxx.ns),
            Api::RustType(rty) => Some(&rty.ident.cxx.ns),
            Api::RustFunction(rfn) => Some(&rfn.ident.cxx.ns),
            Api::Impl(_) | Api::Include(_) | Api::TypeAlias(_) => None,
        }
    }
}
<commit_msg>Condense get_namespace's match<commit_after>use crate::syntax::qualified::QualifiedName;
use crate::syntax::Api;
#[cfg(test)]
use proc_macro2::Span;
use quote::IdentFragment;
use std::fmt::{self, Display};
use std::slice::Iter;
use syn::parse::{Parse, ParseStream, Result};
use syn::{Ident, Token};

mod kw {
    syn::custom_keyword!(namespace);
}

#[derive(Clone)]
pub struct Namespace {
    segments: Vec<Ident>,
}

impl Namespace {
    pub fn none() -> Self {
        Namespace {
            segments: Vec::new(),
        }
    }

    pub fn iter(&self) -> Iter<Ident> {
        self.segments.iter()
    }

    pub fn parse_bridge_attr_namespace(input: ParseStream) -> Result<Namespace> {
        if input.is_empty() {
            return Ok(Namespace::none());
        }

        input.parse::<kw::namespace>()?;
        input.parse::<Token![=]>()?;
        let ns = input.parse::<Namespace>()?;
        input.parse::<Option<Token![,]>>()?;
        Ok(ns)
    }

    #[cfg(test)]
    pub fn from_str(ns: &str) -> Self {
        Namespace {
            segments: ns
                .split("::")
                .map(|x| Ident::new(x, Span::call_site()))
                .collect(),
        }
    }
}

impl Parse for Namespace {
    fn parse(input: ParseStream) -> Result<Self> {
        let segments = QualifiedName::parse_quoted_or_unquoted(input)?.segments;
        Ok(Namespace { segments })
    }
}

impl Display for Namespace {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for segment in self {
            write!(f, "{}$", segment)?;
        }
        Ok(())
    }
}

impl IdentFragment for Namespace {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(self, f)
    }
}

impl<'a> IntoIterator for &'a Namespace {
    type Item = &'a Ident;
    type IntoIter = Iter<'a, Ident>;
    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl Api {
    pub fn get_namespace(&self) -> Option<&Namespace> {
        match self {
            Api::CxxFunction(efn) | Api::RustFunction(efn) => Some(&efn.ident.cxx.ns),
            Api::CxxType(ety) | Api::RustType(ety) => Some(&ety.ident.cxx.ns),
            Api::Enum(enm) => Some(&enm.ident.cxx.ns),
            Api::Struct(strct) => Some(&strct.ident.cxx.ns),
            Api::Impl(_) | Api::Include(_) | Api::TypeAlias(_) => None,
        }
    }
}
<|endoftext|>


<commit_before>/*!
generates images used to test NMF

reproducably (seeded) generate test data.

a series of pictures.
each picture is generated from a linear combination of factors.
the coefficients of the linear combination are chosen randomly.

two evolving factors change over time.
the two evolving factors change 6 times.
we generate 1000 pictures for each change of the evolving factors
during which the evolving factors stay constant.

the series of pictures is fed into ONMF one at a time.
a picture is fed as a 1D array (series of values, slice) into the ONMF
and not as a 2D array.
*/

use std::ops::{Range, Div};
use std::iter::{Map, Rev, once, Once, Chain, Zip};

use nalgebra::{DMat};
use num::traits::{Zero, One};
use rand::{Rng, Closed01, Rand};

use helpers::{random01, Normalize};

pub type HorizontalReturnT<T> = Map<Range<usize>, fn(usize) -> T>;
pub type VerticalReturnT<T> = Map<Rev<Range<usize>>, fn(usize) -> T>;
pub type StaticReturnT<T> = Chain<Chain<Chain<Once<T>, VerticalReturnT<T>>, Once<T>>, HorizontalReturnT<T>>;
pub type TestReturnT<T> = Map<Zip<HorizontalReturnT<T>, VerticalReturnT<T>>, fn((T, T)) -> T>;

/// returns a matrix that has `1` in `row` for all `cols` and `0` everywhere else
///
/// ```
/// # use onmf::testimage_generator::horizontal_line;
/// horizontal_line::<f64, _>(9, 0..5);
/// ```
pub fn horizontal_line<T, I>(row: usize, cols: I) -> DMat<T>
    where T: Clone + Copy + Zero + One,
          I: Iterator<Item = usize>
{
    let mut factor: DMat<T> = DMat::new_zeros(10, 10);
    for col in cols {
        factor[(row, col)] = T::one();
    }
    factor
}

pub fn horizontal_evolving_factors<T>() -> HorizontalReturnT<DMat<T>>
    where T: Clone + Copy + Zero + One
{
    fn helper<U: Clone + Copy + Zero + One>(start_col: usize) -> DMat<U> {
        horizontal_line(9, start_col..(start_col + 5))
    }
    (0..6).map(helper)
}

/// returns a matrix that has `1` in `col` for all `rows` and `0` everywhere else
///
/// ```
/// # use onmf::testimage_generator::vertical_line;
/// vertical_line::<f64, _>(5..10, 0);
/// ```
pub fn vertical_line<T, I>(rows: I, col: usize) -> DMat<T>
    where T: Clone + Copy + Zero + One,
          I: Iterator<Item = usize>
{
    let mut factor: DMat<T> = DMat::new_zeros(10, 10);
    for row in rows {
        factor[(row, col)] = T::one();
    }
    factor
}

pub fn vertical_evolving_factors<T>() -> VerticalReturnT<DMat<T>>
    where T: Clone + Copy + Zero + One
{
    fn helper<U: Clone + Copy + Zero + One>(start_row: usize) -> DMat<U> {
        vertical_line(start_row..(start_row + 5), 0)
    }
    (0..6).rev().map(helper)
}

pub fn static_factors<T>() -> StaticReturnT<DMat<T>>
    where T: Clone + Copy + Zero + One
{
    fn helper_horizontal<U: Clone + Copy + Zero + One>(row: usize) -> DMat<U> {
        horizontal_line(row, 0..10)
    }
    fn helper_vertical<U: Clone + Copy + Zero + One>(col: usize) -> DMat<U> {
        vertical_line(0..10, col)
    }
    once(horizontal_line(9, 0..5))
        .chain((0..9).rev().map(helper_horizontal as fn(usize) -> DMat<T>))
        .chain(once(vertical_line(5..10, 0)))
        .chain((1..10).map(helper_vertical as fn(usize) -> DMat<T>))
}

pub struct ImgGen<'a, R: 'a, T, IH, IV> {
    pub per_step: usize,
    pub ihorizontal: usize,
    pub ivertical: usize,
    pub i: usize,
    pub horizontal_iter: IH,
    pub vertical_iter: IV,
    pub current_horizontal: T,
    pub current_vertical: T,
    pub static_factors: Vec<T>,
    pub rng: &'a mut R,
}

impl<'a, R, T, IH, IV> Iterator for ImgGen<'a, R, DMat<T>, IH, IV>
    where R: 'a + Rng,
          IH: Iterator<Item=DMat<T>>,
          IV: Iterator<Item=DMat<T>>,
          T: Clone + Copy + Zero + One + PartialOrd,
          Closed01<T>: Rand,
          DMat<T>: Div<T, Output=DMat<T>>
{
    type Item = (usize, usize, usize, DMat<T>);

    fn next(&mut self) -> Option<Self::Item> {
        if self.i == self.per_step {
            if self.ihorizontal <= self.ivertical {
                let horizontal = self.horizontal_iter.next();
                if horizontal.is_none() { return None; }
                self.current_horizontal = horizontal.unwrap();
                self.ihorizontal += 1;
            } else{
                let vertical = self.vertical_iter.next();
                if vertical.is_none() { return None; }
                self.current_vertical = vertical.unwrap();
                self.ivertical += 1;
            }

            self.i = 0;
        }

        let i = self.i;
        self.i += 1;

        let mut result = DMat::<T>::new_zeros(10, 10);

        // random linear combination
        for factor in self.static_factors.iter() {
            result = result.clone() + (factor.clone() * random01(&mut self.rng));
        }
        result = result.clone() + (self.current_horizontal.clone() * random01(&mut self.rng))
            + (self.current_vertical.clone() * random01(&mut self.rng));

        Some((self.ihorizontal, self.ivertical, i, result.normalize()))
    }
}

pub fn testimages<'a, T, R>(per_step: usize, rng: &'a mut R) -> ImgGen<'a, R, DMat<T>, HorizontalReturnT<DMat<T>>, VerticalReturnT<DMat<T>>>
    where R: 'a,
          T: Clone + Copy + Zero + One
{
    assert!(0 < per_step);
    let mut horizontal_iter = horizontal_evolving_factors();
    let mut vertical_iter = vertical_evolving_factors();
    let horizontal = horizontal_iter.next().unwrap();
    let vertical = vertical_iter.next().unwrap();
    ImgGen {
        per_step: per_step,
        ihorizontal: 0,
        ivertical: 0,
        i: 0,
        horizontal_iter: horizontal_iter,
        vertical_iter: vertical_iter,
        current_horizontal: horizontal,
        current_vertical: vertical,
        rng: rng,
        static_factors: static_factors().collect::<Vec<DMat<T>>>(),
    }
}
<commit_msg>dont normalize testimages on generation<commit_after>/*!
generates images used to test NMF

reproducably (seeded) generate test data.

a series of pictures.
each picture is generated from a linear combination of factors.
the coefficients of the linear combination are chosen randomly.

two evolving factors change over time.
the two evolving factors change 6 times.
we generate 1000 pictures for each change of the evolving factors
during which the evolving factors stay constant.

the series of pictures is fed into ONMF one at a time.
a picture is fed as a 1D array (series of values, slice) into the ONMF
and not as a 2D array.
*/

use std::ops::{Range, Div};
use std::iter::{Map, Rev, once, Once, Chain, Zip};

use nalgebra::{DMat};
use num::traits::{Zero, One};
use rand::{Rng, Closed01, Rand};

use helpers::{random01, Normalize};

pub type HorizontalReturnT<T> = Map<Range<usize>, fn(usize) -> T>;
pub type VerticalReturnT<T> = Map<Rev<Range<usize>>, fn(usize) -> T>;
pub type StaticReturnT<T> = Chain<Chain<Chain<Once<T>, VerticalReturnT<T>>, Once<T>>, HorizontalReturnT<T>>;
pub type TestReturnT<T> = Map<Zip<HorizontalReturnT<T>, VerticalReturnT<T>>, fn((T, T)) -> T>;

/// returns a matrix that has `1` in `row` for all `cols` and `0` everywhere else
///
/// ```
/// # use onmf::testimage_generator::horizontal_line;
/// horizontal_line::<f64, _>(9, 0..5);
/// ```
pub fn horizontal_line<T, I>(row: usize, cols: I) -> DMat<T>
    where T: Clone + Copy + Zero + One,
          I: Iterator<Item = usize>
{
    let mut factor: DMat<T> = DMat::new_zeros(10, 10);
    for col in cols {
        factor[(row, col)] = T::one();
    }
    factor
}

pub fn horizontal_evolving_factors<T>() -> HorizontalReturnT<DMat<T>>
    where T: Clone + Copy + Zero + One
{
    fn helper<U: Clone + Copy + Zero + One>(start_col: usize) -> DMat<U> {
        horizontal_line(9, start_col..(start_col + 5))
    }
    (0..6).map(helper)
}

/// returns a matrix that has `1` in `col` for all `rows` and `0` everywhere else
///
/// ```
/// # use onmf::testimage_generator::vertical_line;
/// vertical_line::<f64, _>(5..10, 0);
/// ```
pub fn vertical_line<T, I>(rows: I, col: usize) -> DMat<T>
    where T: Clone + Copy + Zero + One,
          I: Iterator<Item = usize>
{
    let mut factor: DMat<T> = DMat::new_zeros(10, 10);
    for row in rows {
        factor[(row, col)] = T::one();
    }
    factor
}

pub fn vertical_evolving_factors<T>() -> VerticalReturnT<DMat<T>>
    where T: Clone + Copy + Zero + One
{
    fn helper<U: Clone + Copy + Zero + One>(start_row: usize) -> DMat<U> {
        vertical_line(start_row..(start_row + 5), 0)
    }
    (0..6).rev().map(helper)
}

pub fn static_factors<T>() -> StaticReturnT<DMat<T>>
    where T: Clone + Copy + Zero + One
{
    fn helper_horizontal<U: Clone + Copy + Zero + One>(row: usize) -> DMat<U> {
        horizontal_line(row, 0..10)
    }
    fn helper_vertical<U: Clone + Copy + Zero + One>(col: usize) -> DMat<U> {
        vertical_line(0..10, col)
    }
    once(horizontal_line(9, 0..5))
        .chain((0..9).rev().map(helper_horizontal as fn(usize) -> DMat<T>))
        .chain(once(vertical_line(5..10, 0)))
        .chain((1..10).map(helper_vertical as fn(usize) -> DMat<T>))
}

pub struct ImgGen<'a, R: 'a, T, IH, IV> {
    pub per_step: usize,
    pub ihorizontal: usize,
    pub ivertical: usize,
    pub i: usize,
    pub horizontal_iter: IH,
    pub vertical_iter: IV,
    pub current_horizontal: T,
    pub current_vertical: T,
    pub static_factors: Vec<T>,
    pub rng: &'a mut R,
}

impl<'a, R, T, IH, IV> Iterator for ImgGen<'a, R, DMat<T>, IH, IV>
    where R: 'a + Rng,
          IH: Iterator<Item=DMat<T>>,
          IV: Iterator<Item=DMat<T>>,
          T: Clone + Copy + Zero + One + PartialOrd,
          Closed01<T>: Rand,
          DMat<T>: Div<T, Output=DMat<T>>
{
    type Item = (usize, usize, usize, DMat<T>);

    fn next(&mut self) -> Option<Self::Item> {
        if self.i == self.per_step {
            if self.ihorizontal <= self.ivertical {
                let horizontal = self.horizontal_iter.next();
                if horizontal.is_none() { return None; }
                self.current_horizontal = horizontal.unwrap();
                self.ihorizontal += 1;
            } else{
                let vertical = self.vertical_iter.next();
                if vertical.is_none() { return None; }
                self.current_vertical = vertical.unwrap();
                self.ivertical += 1;
            }

            self.i = 0;
        }

        let i = self.i;
        self.i += 1;

        let mut result = DMat::<T>::new_zeros(10, 10);

        // random linear combination
        for factor in self.static_factors.iter() {
            result = result.clone() + (factor.clone() * random01(&mut self.rng));
        }
        result = result.clone() + (self.current_horizontal.clone() * random01(&mut self.rng))
            + (self.current_vertical.clone() * random01(&mut self.rng));

        Some((self.ihorizontal, self.ivertical, i, result))
    }
}

pub fn testimages<'a, T, R>(per_step: usize, rng: &'a mut R) -> ImgGen<'a, R, DMat<T>, HorizontalReturnT<DMat<T>>, VerticalReturnT<DMat<T>>>
    where R: 'a,
          T: Clone + Copy + Zero + One
{
    assert!(0 < per_step);
    let mut horizontal_iter = horizontal_evolving_factors();
    let mut vertical_iter = vertical_evolving_factors();
    let horizontal = horizontal_iter.next().unwrap();
    let vertical = vertical_iter.next().unwrap();
    ImgGen {
        per_step: per_step,
        ihorizontal: 0,
        ivertical: 0,
        i: 0,
        horizontal_iter: horizontal_iter,
        vertical_iter: vertical_iter,
        current_horizontal: horizontal,
        current_vertical: vertical,
        rng: rng,
        static_factors: static_factors().collect::<Vec<DMat<T>>>(),
    }
}
<|endoftext|>


<commit_before>//! The `ast` module contains a lot of useful functionality
//! to create and walk through the ast (abstract syntaxtree)

use frontend::lexer::Token;
use backend::zcode::zfile;
use backend::zcode::zfile::{FormattingState};
use std::collections::HashMap;

//==============================
// ast

pub struct AST {
    passages: Vec<ASTNode>
}

/// add zcode based on tokens
fn gen_zcode<'a>(node: &'a ASTNode, state: FormattingState, mut out: &mut zfile::Zfile, mut var_table: &mut HashMap<&'a str, u8>, mut var_id: &mut u8) {
    let mut state_copy = state.clone();

    match node {
        &ASTNode::Passage(ref node) => {
            match &node.category {
                &Token::TokPassageName(ref name) => {
                    out.routine(name, 0);
                },
                _ => {
                    debug!("no match 1");
                }
            };

            for child in &node.childs {
                gen_zcode(child, state_copy, out, var_table, var_id);
            }

            out.op_newline();
            out.op_call_1n("system_check_links");

        },
        &ASTNode::Default(ref t) => {
            match &t.category {
                &Token::TokText(ref s) => {
                    out.op_print(s);
                },
                &Token::TokNewLine => {
                    out.op_newline();
                },
                &Token::TokFormatBoldStart => {
                    state_copy.bold = true;
                    out.op_set_text_style(state_copy.bold, state_copy.inverted, state_copy.mono, state_copy.italic);
                },
                &Token::TokFormatItalicStart => {
                    state_copy.italic = true;
                    out.op_set_text_style(state_copy.bold, state_copy.inverted, state_copy.mono, state_copy.italic);
                },
                &Token::TokPassageLink (ref name, ref link) => {
                    out.op_call_2n_with_address("system_add_link", link);

                    out.op_set_text_style(state_copy.bold, true, state_copy.mono, state_copy.italic);
                    let link_text = format!("{}[", name);
                    out.op_print(&link_text);
                    out.op_print_num_var(16);
                    out.op_print("]");
                    out.op_set_text_style(state_copy.bold, state_copy.inverted, state_copy.mono, state_copy.italic);
                },
                &Token::TokAssign(ref var, ref operator) => {
                    if operator == "=" {
                        if !var_table.contains_key::<str>(var) {
                            var_table.insert(&var, *var_id);
                            debug!("Assigned id {} to variable {}", var_id, var);
                            *var_id += 1;
                        }
                        let id_option = var_table.get::<str>(var);
                        if t.childs.len() == 1 {
                            match t.childs[0] {
                                ASTNode::Default(ref def) => {
                                    let actual_id :u8 = match id_option {
                                        Some(id) => {
                                            *id
                                        },
                                        None => {
                                            panic!("Variable not in var table.")
                                        }
                                    };
                                    match def.category {
                                        Token::TokInt(value) => {
                                            out.op_store_u8(actual_id, value as u8);
                                        },
                                        Token::TokBoolean(ref bool_val) => {
                                            let value = match (*bool_val).as_ref() {
                                                "true" => { 1 as u8 },
                                                _ => { 0 as u8 }
                                            };
                                            out.op_store_u8(actual_id, value);
                                        }
                                        _ => { }
                                    }
                                },
                                _ => { }
                            }
                        } else {
                            debug!("Assign Expression currently not supported.");
                        }

                    }
                },
                _ => {
                    debug!("no match 2");
                }
            };

            for child in &t.childs {
                gen_zcode(child, state_copy, out, var_table, var_id);
            }

            out.op_set_text_style(false, false, false, false);
            out.op_set_text_style(state.bold, state.inverted, state.mono, state.italic);
        }
    };
}

impl AST {
    /// convert ast to zcode
    pub fn to_zcode(&self,  out: &mut zfile::Zfile) {
        let mut var_table = HashMap::<&str, u8>::new();
        let mut var_id : u8 = 25;
        let state = FormattingState {bold: false, italic: false, mono: false, inverted: false};
        for child in &self.passages {
            gen_zcode(child, state, out, &mut var_table, &mut var_id);
        }
    }

    pub fn new() -> AST {
        AST {
            passages: Vec::new()
        }
    }

    /// prints the tree
    pub fn print(&self) {
        debug!("Abstract Syntax Tree: ");
        for child in &self.passages {
            child.print(0);
        }
        debug!("");
    }

    /// adds a passage to the path in the ast
    pub fn add_passage(&mut self, token: Token) {
        let node = ASTNode::Passage(NodePassage { category: token, childs: Vec::new() });
        self.passages.push(node);
    }

    /// adds a child to the path in the ast
    pub fn add_child(&mut self, path: &Vec<usize>, token: Token) {
        if let Some(index) = path.first() {
            let mut new_path: Vec<usize> = path.to_vec();
            new_path.remove(0);

            self.passages[*index].add_child(new_path, token)
        } else {
            self.passages.push(ASTNode::Default(NodeDefault { category: token, childs: Vec::new() }));
        }
    }

    /// counts the childs of the path in the asts
    pub fn count_childs(&self, path: Vec<usize>) -> usize {
        if let Some(index) = path.first() {
            let mut new_path: Vec<usize> = path.to_vec();
            new_path.remove(0);

            self.passages[*index].count_childs(new_path)
        } else {
            self.passages.len()
        }
    }
}

// ================================
// node types
enum ASTNode {
    Default (NodeDefault),
    Passage (NodePassage)
}

struct NodePassage {
    category: Token,
    pub childs: Vec<ASTNode>,
    /*tags: Vec<ASTNode>*/
}

struct NodeDefault {
    category: Token,
    childs: Vec<ASTNode>
}

impl ASTNode {
    /// adds an child to the path in the ast
    pub fn add_child(&mut self, path: Vec<usize>, token: Token) {
        if let Some(index) = path.first() {
            let mut new_path: Vec<usize> = path.to_vec();
            new_path.remove(0);

            match self {
                &mut ASTNode::Default(ref mut node) => node.childs[*index].add_child(new_path, token),
                &mut ASTNode::Passage(ref mut node) => node.childs[*index].add_child(new_path, token),
            }
        } else {
            match self {
                &mut ASTNode::Default(ref mut node) => node.childs.push(ASTNode::Default(NodeDefault { category: token, childs: Vec::new() } )),
                &mut ASTNode::Passage(ref mut node) => node.childs.push(ASTNode::Default(NodeDefault { category: token, childs: Vec::new() } )),
            }
        }
    }

    /// counts the childs of the current path in the ast
    pub fn count_childs(&self, path: Vec<usize>) -> usize {
        if let Some(index) = path.first() {
            let mut new_path: Vec<usize> = path.to_vec();
            new_path.remove(0);

            match self {
                &ASTNode::Default(ref node) => node.childs[*index].count_childs(new_path),
                &ASTNode::Passage(ref node) => node.childs[*index].count_childs(new_path),
            }
        } else {
            match self {
                &ASTNode::Default(ref node) => node.childs.len(),
                &ASTNode::Passage(ref node) => node.childs.len(),
            }
        }
    }

    /// prints an node of an ast
    pub fn print(&self, indent: usize) {
        let mut spaces = "".to_string();
        for _ in 0..indent {
            spaces.push_str(" ");
        }

        match self {
            &ASTNode::Passage(ref t) => {
                debug!("{}|- : {:?}", spaces, t.category);
                for child in &t.childs {
                    child.print(indent+2);
                }
            },
            &ASTNode::Default(ref t) => {
                debug!("{}|- : {:?}", spaces, t.category);
                for child in &t.childs {
                    child.print(indent+2);
                }
            }
        }
    }
}
<commit_msg>Add support for "to" operator<commit_after>//! The `ast` module contains a lot of useful functionality
//! to create and walk through the ast (abstract syntaxtree)

use frontend::lexer::Token;
use backend::zcode::zfile;
use backend::zcode::zfile::{FormattingState};
use std::collections::HashMap;

//==============================
// ast

pub struct AST {
    passages: Vec<ASTNode>
}

/// add zcode based on tokens
fn gen_zcode<'a>(node: &'a ASTNode, state: FormattingState, mut out: &mut zfile::Zfile, mut var_table: &mut HashMap<&'a str, u8>, mut var_id: &mut u8) {
    let mut state_copy = state.clone();

    match node {
        &ASTNode::Passage(ref node) => {
            match &node.category {
                &Token::TokPassageName(ref name) => {
                    out.routine(name, 0);
                },
                _ => {
                    debug!("no match 1");
                }
            };

            for child in &node.childs {
                gen_zcode(child, state_copy, out, var_table, var_id);
            }

            out.op_newline();
            out.op_call_1n("system_check_links");

        },
        &ASTNode::Default(ref t) => {
            match &t.category {
                &Token::TokText(ref s) => {
                    out.op_print(s);
                },
                &Token::TokNewLine => {
                    out.op_newline();
                },
                &Token::TokFormatBoldStart => {
                    state_copy.bold = true;
                    out.op_set_text_style(state_copy.bold, state_copy.inverted, state_copy.mono, state_copy.italic);
                },
                &Token::TokFormatItalicStart => {
                    state_copy.italic = true;
                    out.op_set_text_style(state_copy.bold, state_copy.inverted, state_copy.mono, state_copy.italic);
                },
                &Token::TokPassageLink (ref name, ref link) => {
                    out.op_call_2n_with_address("system_add_link", link);

                    out.op_set_text_style(state_copy.bold, true, state_copy.mono, state_copy.italic);
                    let link_text = format!("{}[", name);
                    out.op_print(&link_text);
                    out.op_print_num_var(16);
                    out.op_print("]");
                    out.op_set_text_style(state_copy.bold, state_copy.inverted, state_copy.mono, state_copy.italic);
                },
                &Token::TokAssign(ref var, ref operator) => {
                    if operator == "=" || operator == "to" {
                        if !var_table.contains_key::<str>(var) {
                            var_table.insert(&var, *var_id);
                            debug!("Assigned id {} to variable {}", var_id, var);
                            *var_id += 1;
                        }
                        let id_option = var_table.get::<str>(var);
                        if t.childs.len() == 1 {
                            match t.childs[0] {
                                ASTNode::Default(ref def) => {
                                    let actual_id :u8 = match id_option {
                                        Some(id) => {
                                            *id
                                        },
                                        None => {
                                            panic!("Variable not in var table.")
                                        }
                                    };
                                    match def.category {
                                        Token::TokInt(value) => {
                                            out.op_store_u8(actual_id, value as u8);
                                        },
                                        Token::TokBoolean(ref bool_val) => {
                                            let value = match (*bool_val).as_ref() {
                                                "true" => { 1 as u8 },
                                                _ => { 0 as u8 }
                                            };
                                            out.op_store_u8(actual_id, value);
                                        }
                                        _ => { }
                                    }
                                },
                                _ => { }
                            }
                        } else {
                            debug!("Assign Expression currently not supported.");
                        }

                    }
                },
                _ => {
                    debug!("no match 2");
                }
            };

            for child in &t.childs {
                gen_zcode(child, state_copy, out, var_table, var_id);
            }

            out.op_set_text_style(false, false, false, false);
            out.op_set_text_style(state.bold, state.inverted, state.mono, state.italic);
        }
    };
}

impl AST {
    /// convert ast to zcode
    pub fn to_zcode(&self,  out: &mut zfile::Zfile) {
        let mut var_table = HashMap::<&str, u8>::new();
        let mut var_id : u8 = 25;
        let state = FormattingState {bold: false, italic: false, mono: false, inverted: false};
        for child in &self.passages {
            gen_zcode(child, state, out, &mut var_table, &mut var_id);
        }
    }

    pub fn new() -> AST {
        AST {
            passages: Vec::new()
        }
    }

    /// prints the tree
    pub fn print(&self) {
        debug!("Abstract Syntax Tree: ");
        for child in &self.passages {
            child.print(0);
        }
        debug!("");
    }

    /// adds a passage to the path in the ast
    pub fn add_passage(&mut self, token: Token) {
        let node = ASTNode::Passage(NodePassage { category: token, childs: Vec::new() });
        self.passages.push(node);
    }

    /// adds a child to the path in the ast
    pub fn add_child(&mut self, path: &Vec<usize>, token: Token) {
        if let Some(index) = path.first() {
            let mut new_path: Vec<usize> = path.to_vec();
            new_path.remove(0);

            self.passages[*index].add_child(new_path, token)
        } else {
            self.passages.push(ASTNode::Default(NodeDefault { category: token, childs: Vec::new() }));
        }
    }

    /// counts the childs of the path in the asts
    pub fn count_childs(&self, path: Vec<usize>) -> usize {
        if let Some(index) = path.first() {
            let mut new_path: Vec<usize> = path.to_vec();
            new_path.remove(0);

            self.passages[*index].count_childs(new_path)
        } else {
            self.passages.len()
        }
    }
}

// ================================
// node types
enum ASTNode {
    Default (NodeDefault),
    Passage (NodePassage)
}

struct NodePassage {
    category: Token,
    pub childs: Vec<ASTNode>,
    /*tags: Vec<ASTNode>*/
}

struct NodeDefault {
    category: Token,
    childs: Vec<ASTNode>
}

impl ASTNode {
    /// adds an child to the path in the ast
    pub fn add_child(&mut self, path: Vec<usize>, token: Token) {
        if let Some(index) = path.first() {
            let mut new_path: Vec<usize> = path.to_vec();
            new_path.remove(0);

            match self {
                &mut ASTNode::Default(ref mut node) => node.childs[*index].add_child(new_path, token),
                &mut ASTNode::Passage(ref mut node) => node.childs[*index].add_child(new_path, token),
            }
        } else {
            match self {
                &mut ASTNode::Default(ref mut node) => node.childs.push(ASTNode::Default(NodeDefault { category: token, childs: Vec::new() } )),
                &mut ASTNode::Passage(ref mut node) => node.childs.push(ASTNode::Default(NodeDefault { category: token, childs: Vec::new() } )),
            }
        }
    }

    /// counts the childs of the current path in the ast
    pub fn count_childs(&self, path: Vec<usize>) -> usize {
        if let Some(index) = path.first() {
            let mut new_path: Vec<usize> = path.to_vec();
            new_path.remove(0);

            match self {
                &ASTNode::Default(ref node) => node.childs[*index].count_childs(new_path),
                &ASTNode::Passage(ref node) => node.childs[*index].count_childs(new_path),
            }
        } else {
            match self {
                &ASTNode::Default(ref node) => node.childs.len(),
                &ASTNode::Passage(ref node) => node.childs.len(),
            }
        }
    }

    /// prints an node of an ast
    pub fn print(&self, indent: usize) {
        let mut spaces = "".to_string();
        for _ in 0..indent {
            spaces.push_str(" ");
        }

        match self {
            &ASTNode::Passage(ref t) => {
                debug!("{}|- : {:?}", spaces, t.category);
                for child in &t.childs {
                    child.print(indent+2);
                }
            },
            &ASTNode::Default(ref t) => {
                debug!("{}|- : {:?}", spaces, t.category);
                for child in &t.childs {
                    child.print(indent+2);
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::hash;
use std::marker::{MarkerTrait, PhantomData};
use std::mem;
use std::ops::{Deref, DerefMut};
use std::ptr;

use {Encode, EncodePtr, Message, ToMessage};
use runtime::Object;

#[link(name = "objc", kind = "dylib")]
extern {
    fn objc_retain(obj: *mut Object) -> *mut Object;
    fn objc_release(obj: *mut Object);
}

unsafe fn retain<T: Message>(ptr: *mut T) -> *mut T {
    objc_retain(ptr as *mut Object) as *mut T
}

unsafe fn release<T: Message>(ptr: *mut T) {
    objc_release(ptr as *mut Object);
}

/// A type used to mark that a struct owns the object(s) it contains,
/// so it has the sole references to them.
pub enum Owned { }
/// A type used to mark that the object(s) a struct contains are shared,
/// so there may be other references to them.
pub enum Shared { }

/// A type that marks what type of ownership a struct has over the object(s)
/// it contains; specifically, either `Owned` or `Shared`.
pub trait Ownership : MarkerTrait { }
impl Ownership for Owned { }
impl Ownership for Shared { }

/// A pointer type for Objective-C's reference counted objects. The object of
/// an `Id` is retained and sent a `release` message when the `Id` is dropped.
///
/// An `Id` may be either `Owned` or `Shared`, represented by the types `Id`
/// and `ShareId`, respectively. If owned, there are no other references to the
/// object and the `Id` can be mutably dereferenced. `ShareId`, however, can
/// only be immutably dereferenced because there may be other references to the
/// object, but a `ShareId` can be cloned to provide more references to the
/// object. An owned `Id` can be "downgraded" freely to a `ShareId`, but there
/// is no way to safely upgrade back.
#[unsafe_no_drop_flag]
pub struct Id<T, O = Owned> where T: Message, O: Ownership {
    ptr: *mut T,
    own: PhantomData<O>,
}

impl<T, O> Id<T, O> where T: Message, O: Ownership {
    unsafe fn from_ptr_unchecked(ptr: *mut T) -> Id<T, O> {
        Id { ptr: ptr, own: PhantomData }
    }

    /// Constructs an `Id` from a pointer to an unretained object and
    /// retains it. Panics if the pointer is null.
    /// Unsafe because the pointer must be to a valid object and
    /// the caller must ensure the ownership is correct.
    pub unsafe fn from_ptr(ptr: *mut T) -> Id<T, O> {
        assert!(!ptr.is_null(), "Attempted to construct an Id from a null pointer");
        let ptr = retain(ptr);
        Id::from_ptr_unchecked(ptr)
    }

    /// Constructs an `Id` from a pointer to a retained object; this won't
    /// retain the pointer, so the caller must ensure the object has a +1
    /// retain count. Panics if the pointer is null.
    /// Unsafe because the pointer must be to a valid object and
    /// the caller must ensure the ownership is correct.
    pub unsafe fn from_retained_ptr(ptr: *mut T) -> Id<T, O> {
        assert!(!ptr.is_null(), "Attempted to construct an Id from a null pointer");
        Id::from_ptr_unchecked(ptr)
    }
}

impl<T> Id<T, Owned> where T: Message {
    /// "Downgrade" an owned `Id` to a `ShareId`, allowing it to be cloned.
    pub fn share(self) -> ShareId<T> {
        unsafe {
            let ptr = self.ptr;
            mem::forget(self);
            Id::from_ptr_unchecked(ptr)
        }
    }
}

impl<T, O> Encode for Id<T, O> where T: Message + EncodePtr, O: Ownership {
    fn code() -> &'static str {
        <T as EncodePtr>::ptr_code()
    }
}

impl<T, O> ToMessage for Id<T, O> where T: Message, O: Ownership {
    fn as_id_ptr(&self) -> *mut Object {
        self.ptr as *mut Object
    }
}

impl<T> Clone for Id<T, Shared> where T: Message {
    fn clone(&self) -> ShareId<T> {
        unsafe {
            let ptr = retain(self.ptr);
            Id::from_ptr_unchecked(ptr)
        }
    }
}

#[unsafe_destructor]
impl<T, O> Drop for Id<T, O> where T: Message, O: Ownership {
    fn drop(&mut self) {
        if !self.ptr.is_null() {
            let ptr = mem::replace(&mut self.ptr, ptr::null_mut());
            unsafe {
                release(ptr);
            }
        }
    }
}

impl<T, O> Deref for Id<T, O> where T: Message, O: Ownership {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { &*self.ptr }
    }
}

impl<T> DerefMut for Id<T, Owned> where T: Message {
    fn deref_mut(&mut self) -> &mut T {
        unsafe { &mut *self.ptr }
    }
}

impl<T, O> PartialEq for Id<T, O> where T: Message + PartialEq, O: Ownership {
    fn eq(&self, other: &Id<T, O>) -> bool {
        self.deref() == other.deref()
    }

    fn ne(&self, other: &Id<T, O>) -> bool {
        self.deref() != other.deref()
    }
}

impl<T, O> Eq for Id<T, O> where T: Message + Eq, O: Ownership { }

impl<T, O> hash::Hash for Id<T, O> where T: Message + hash::Hash, O: Ownership {
    fn hash<H>(&self, state: &mut H) where H: hash::Hasher {
        self.deref().hash(state)
    }
}

impl<T, O> fmt::Debug for Id<T, O> where T: Message + fmt::Debug, O: Ownership {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.deref().fmt(f)
    }
}

/// A convenient alias for a shared `Id`.
pub type ShareId<T> = Id<T, Shared>;

/// Extension methods for slices containing `Id`s.
pub trait IdSlice {
    type Item;

    /// Convert a slice of `Id`s into a slice of references
    fn as_refs_slice(&self) -> &[&Self::Item];
}

impl<T, O> IdSlice for [Id<T, O>] where T: Message, O: Ownership {
    type Item = T;

    fn as_refs_slice(&self) -> &[&T] {
        unsafe {
            mem::transmute(self)
        }
    }
}

#[cfg(test)]
mod tests {
    use runtime::Object;
    use test_utils;

    fn retain_count(obj: &Object) -> usize {
        unsafe { msg_send![obj, retainCount] }
    }

    #[test]
    fn test_clone() {
        let obj = test_utils::sample_object();
        assert!(retain_count(&obj) == 1);

        let obj = obj.share();
        assert!(retain_count(&obj) == 1);

        let cloned = obj.clone();
        assert!(retain_count(&cloned) == 2);
        assert!(retain_count(&obj) == 2);

        drop(obj);
        assert!(retain_count(&cloned) == 1);
    }
}
<commit_msg>Removed trait bounds from the declaration of Id.<commit_after>use std::fmt;
use std::hash;
use std::marker::{MarkerTrait, PhantomData};
use std::mem;
use std::ops::{Deref, DerefMut};
use std::ptr;

use {Encode, EncodePtr, Message, ToMessage};
use runtime::Object;

#[link(name = "objc", kind = "dylib")]
extern {
    fn objc_retain(obj: *mut Object) -> *mut Object;
    fn objc_release(obj: *mut Object);
}

unsafe fn retain<T: Message>(ptr: *mut T) -> *mut T {
    objc_retain(ptr as *mut Object) as *mut T
}

unsafe fn release<T: Message>(ptr: *mut T) {
    objc_release(ptr as *mut Object);
}

/// A type used to mark that a struct owns the object(s) it contains,
/// so it has the sole references to them.
pub enum Owned { }
/// A type used to mark that the object(s) a struct contains are shared,
/// so there may be other references to them.
pub enum Shared { }

/// A type that marks what type of ownership a struct has over the object(s)
/// it contains; specifically, either `Owned` or `Shared`.
pub trait Ownership : MarkerTrait { }
impl Ownership for Owned { }
impl Ownership for Shared { }

/// A pointer type for Objective-C's reference counted objects. The object of
/// an `Id` is retained and sent a `release` message when the `Id` is dropped.
///
/// An `Id` may be either `Owned` or `Shared`, represented by the types `Id`
/// and `ShareId`, respectively. If owned, there are no other references to the
/// object and the `Id` can be mutably dereferenced. `ShareId`, however, can
/// only be immutably dereferenced because there may be other references to the
/// object, but a `ShareId` can be cloned to provide more references to the
/// object. An owned `Id` can be "downgraded" freely to a `ShareId`, but there
/// is no way to safely upgrade back.
#[unsafe_no_drop_flag]
pub struct Id<T, O = Owned> {
    ptr: *mut T,
    own: PhantomData<O>,
}

impl<T, O> Id<T, O> where T: Message, O: Ownership {
    unsafe fn from_ptr_unchecked(ptr: *mut T) -> Id<T, O> {
        Id { ptr: ptr, own: PhantomData }
    }

    /// Constructs an `Id` from a pointer to an unretained object and
    /// retains it. Panics if the pointer is null.
    /// Unsafe because the pointer must be to a valid object and
    /// the caller must ensure the ownership is correct.
    pub unsafe fn from_ptr(ptr: *mut T) -> Id<T, O> {
        assert!(!ptr.is_null(), "Attempted to construct an Id from a null pointer");
        let ptr = retain(ptr);
        Id::from_ptr_unchecked(ptr)
    }

    /// Constructs an `Id` from a pointer to a retained object; this won't
    /// retain the pointer, so the caller must ensure the object has a +1
    /// retain count. Panics if the pointer is null.
    /// Unsafe because the pointer must be to a valid object and
    /// the caller must ensure the ownership is correct.
    pub unsafe fn from_retained_ptr(ptr: *mut T) -> Id<T, O> {
        assert!(!ptr.is_null(), "Attempted to construct an Id from a null pointer");
        Id::from_ptr_unchecked(ptr)
    }
}

impl<T> Id<T, Owned> where T: Message {
    /// "Downgrade" an owned `Id` to a `ShareId`, allowing it to be cloned.
    pub fn share(self) -> ShareId<T> {
        unsafe {
            let ptr = self.ptr;
            mem::forget(self);
            Id::from_ptr_unchecked(ptr)
        }
    }
}

impl<T, O> Encode for Id<T, O> where T: EncodePtr {
    fn code() -> &'static str {
        <T as EncodePtr>::ptr_code()
    }
}

impl<T, O> ToMessage for Id<T, O> where T: Message {
    fn as_id_ptr(&self) -> *mut Object {
        self.ptr as *mut Object
    }
}

impl<T> Clone for Id<T, Shared> where T: Message {
    fn clone(&self) -> ShareId<T> {
        unsafe {
            let ptr = retain(self.ptr);
            Id::from_ptr_unchecked(ptr)
        }
    }
}

#[unsafe_destructor]
impl<T, O> Drop for Id<T, O> where T: Message {
    fn drop(&mut self) {
        if !self.ptr.is_null() {
            let ptr = mem::replace(&mut self.ptr, ptr::null_mut());
            unsafe {
                release(ptr);
            }
        }
    }
}

impl<T, O> Deref for Id<T, O> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { &*self.ptr }
    }
}

impl<T> DerefMut for Id<T, Owned> {
    fn deref_mut(&mut self) -> &mut T {
        unsafe { &mut *self.ptr }
    }
}

impl<T, O> PartialEq for Id<T, O> where T: PartialEq {
    fn eq(&self, other: &Id<T, O>) -> bool {
        self.deref() == other.deref()
    }

    fn ne(&self, other: &Id<T, O>) -> bool {
        self.deref() != other.deref()
    }
}

impl<T, O> Eq for Id<T, O> where T: Eq { }

impl<T, O> hash::Hash for Id<T, O> where T: hash::Hash {
    fn hash<H>(&self, state: &mut H) where H: hash::Hasher {
        self.deref().hash(state)
    }
}

impl<T, O> fmt::Debug for Id<T, O> where T: fmt::Debug {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.deref().fmt(f)
    }
}

/// A convenient alias for a shared `Id`.
pub type ShareId<T> = Id<T, Shared>;

/// Extension methods for slices containing `Id`s.
pub trait IdSlice {
    type Item;

    /// Convert a slice of `Id`s into a slice of references
    fn as_refs_slice(&self) -> &[&Self::Item];
}

impl<T, O> IdSlice for [Id<T, O>] {
    type Item = T;

    fn as_refs_slice(&self) -> &[&T] {
        unsafe {
            mem::transmute(self)
        }
    }
}

#[cfg(test)]
mod tests {
    use runtime::Object;
    use test_utils;

    fn retain_count(obj: &Object) -> usize {
        unsafe { msg_send![obj, retainCount] }
    }

    #[test]
    fn test_clone() {
        let obj = test_utils::sample_object();
        assert!(retain_count(&obj) == 1);

        let obj = obj.share();
        assert!(retain_count(&obj) == 1);

        let cloned = obj.clone();
        assert!(retain_count(&cloned) == 2);
        assert!(retain_count(&obj) == 2);

        drop(obj);
        assert!(retain_count(&cloned) == 1);
    }
}
<|endoftext|>


<commit_before>
use std::io::Write;
use std::io::Error as IoError;
use std::ascii::AsciiExt;
use super::{Parsable, ParseError, Streamable};
use super::types::{DateTime, MailboxList, Mailbox, AddressList};

macro_rules! req_name {
    ($rem:ident, $str:expr, $input:ident) => {
        let len: usize = $str.len();
        if $rem.len() < len || &(&$rem[0..len]).to_ascii_lowercase()!=$str {
            return Err(ParseError::NotFound);
        }
        $rem = &$rem[len..];
    };
}

macro_rules! req_crlf {
    ($rem:ident, $input:ident) => {
        if &$rem[..2] != b"\r\n" {
            return Err(ParseError::NotFound);
        }
        $rem = &$rem[2..];
    }
}

// 3.6.1
// orig-date       =   "Date:" date-time CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct OrigDate(pub DateTime);
impl Parsable for OrigDate {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"date:", input);
        if let Ok(dt) = parse!(DateTime, rem) {
            req_crlf!(rem, input);
            Ok((OrigDate(dt), rem))
        } else {
            Err(ParseError::NotFound)
        }
    }
}
impl Streamable for OrigDate {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        Ok(try!(w.write(b"Date:"))
           + try!(self.0.stream(w))
           + try!(w.write(b"\r\n")))
    }
}

// 3.6.2
// from            =   "From:" mailbox-list CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct From(pub MailboxList);
impl Parsable for From {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"from:", input);
        if let Ok(mbl) = parse!(MailboxList, rem) {
            req_crlf!(rem, input);
            return Ok((From(mbl), rem));
        }
        Err(ParseError::NotFound)
    }
}
impl Streamable for From {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        Ok(try!(w.write(b"From: "))
           + try!(self.0.stream(w))
           + try!(w.write(b"\r\n")))
    }
}

// 3.6.2
// sender          =   "Sender:" mailbox CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct Sender(pub Mailbox);
impl Parsable for Sender {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"sender:", input);
        if let Ok(mb) = parse!(Mailbox, rem) {
            req_crlf!(rem, input);
            return Ok((Sender(mb), rem));
        }
        Err(ParseError::NotFound)
    }
}
impl Streamable for Sender {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        Ok(try!(w.write(b"Sender: "))
           + try!(self.0.stream(w))
           + try!(w.write(b"\r\n")))
    }
}

// 3.6.2
// reply-to        =   "Reply-To:" address-list CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct ReplyTo(pub AddressList);
impl Parsable for ReplyTo {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"reply-to:", input);
        if let Ok(x) = parse!(AddressList, rem) {
            req_crlf!(rem, input);
            return Ok((ReplyTo(x), rem));
        }
        Err(ParseError::NotFound)
    }
}
impl Streamable for ReplyTo {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        Ok(try!(w.write(b"Reply-To: "))
           + try!(self.0.stream(w))
           + try!(w.write(b"\r\n")))
    }
}

// 3.6.3
// to              =   "To:" address-list CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct To(pub AddressList);
impl Parsable for To {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"to:", input);
        if let Ok(x) = parse!(AddressList, rem) {
            req_crlf!(rem, input);
            return Ok((To(x), rem));
        }
        Err(ParseError::NotFound)
    }
}
impl Streamable for To {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        Ok(try!(w.write(b"To: "))
           + try!(self.0.stream(w))
           + try!(w.write(b"\r\n")))
    }
}
<commit_msg>rfc5322: 3.6.3 cc<commit_after>
use std::io::Write;
use std::io::Error as IoError;
use std::ascii::AsciiExt;
use super::{Parsable, ParseError, Streamable};
use super::types::{DateTime, MailboxList, Mailbox, AddressList};

macro_rules! req_name {
    ($rem:ident, $str:expr, $input:ident) => {
        let len: usize = $str.len();
        if $rem.len() < len || &(&$rem[0..len]).to_ascii_lowercase()!=$str {
            return Err(ParseError::NotFound);
        }
        $rem = &$rem[len..];
    };
}

macro_rules! req_crlf {
    ($rem:ident, $input:ident) => {
        if &$rem[..2] != b"\r\n" {
            return Err(ParseError::NotFound);
        }
        $rem = &$rem[2..];
    }
}

// 3.6.1
// orig-date       =   "Date:" date-time CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct OrigDate(pub DateTime);
impl Parsable for OrigDate {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"date:", input);
        if let Ok(dt) = parse!(DateTime, rem) {
            req_crlf!(rem, input);
            Ok((OrigDate(dt), rem))
        } else {
            Err(ParseError::NotFound)
        }
    }
}
impl Streamable for OrigDate {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        Ok(try!(w.write(b"Date:"))
           + try!(self.0.stream(w))
           + try!(w.write(b"\r\n")))
    }
}

// 3.6.2
// from            =   "From:" mailbox-list CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct From(pub MailboxList);
impl Parsable for From {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"from:", input);
        if let Ok(mbl) = parse!(MailboxList, rem) {
            req_crlf!(rem, input);
            return Ok((From(mbl), rem));
        }
        Err(ParseError::NotFound)
    }
}
impl Streamable for From {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        Ok(try!(w.write(b"From: "))
           + try!(self.0.stream(w))
           + try!(w.write(b"\r\n")))
    }
}

// 3.6.2
// sender          =   "Sender:" mailbox CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct Sender(pub Mailbox);
impl Parsable for Sender {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"sender:", input);
        if let Ok(mb) = parse!(Mailbox, rem) {
            req_crlf!(rem, input);
            return Ok((Sender(mb), rem));
        }
        Err(ParseError::NotFound)
    }
}
impl Streamable for Sender {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        Ok(try!(w.write(b"Sender: "))
           + try!(self.0.stream(w))
           + try!(w.write(b"\r\n")))
    }
}

// 3.6.2
// reply-to        =   "Reply-To:" address-list CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct ReplyTo(pub AddressList);
impl Parsable for ReplyTo {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"reply-to:", input);
        if let Ok(x) = parse!(AddressList, rem) {
            req_crlf!(rem, input);
            return Ok((ReplyTo(x), rem));
        }
        Err(ParseError::NotFound)
    }
}
impl Streamable for ReplyTo {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        Ok(try!(w.write(b"Reply-To: "))
           + try!(self.0.stream(w))
           + try!(w.write(b"\r\n")))
    }
}

// 3.6.3
// to              =   "To:" address-list CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct To(pub AddressList);
impl Parsable for To {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"to:", input);
        if let Ok(x) = parse!(AddressList, rem) {
            req_crlf!(rem, input);
            return Ok((To(x), rem));
        }
        Err(ParseError::NotFound)
    }
}
impl Streamable for To {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        Ok(try!(w.write(b"To: "))
           + try!(self.0.stream(w))
           + try!(w.write(b"\r\n")))
    }
}

// 3.6.3
// cc              =   "Cc:" address-list CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct Cc(pub AddressList);
impl Parsable for Cc {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"cc:", input);
        if let Ok(x) = parse!(AddressList, rem) {
            req_crlf!(rem, input);
            return Ok((Cc(x), rem));
        }
        Err(ParseError::NotFound)
    }
}
impl Streamable for Cc {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        Ok(try!(w.write(b"Cc: "))
           + try!(self.0.stream(w))
           + try!(w.write(b"\r\n")))
    }
}
<|endoftext|>


<commit_before>use std::fmt::{Debug, Formatter, Error as FmtError};
use std::result::Result as RResult;

use libimagstore::store::Store;
use libimagstore::storeid::StoreIdIterator;

use diaryid::DiaryId;
use diaryid::FromStoreId;
use is_in_diary::IsInDiary;
use entry::Entry as DiaryEntry;
use error::DiaryError as DE;
use error::DiaryErrorKind as DEK;
use result::Result;

/// A iterator for iterating over diary entries
pub struct DiaryEntryIterator<'a> {
    store: &'a Store,
    name: &'a str,
    iter: StoreIdIterator,

    year: Option<i32>,
    month: Option<u32>,
    day: Option<u32>,
}

impl<'a> Debug for DiaryEntryIterator<'a> {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "DiaryEntryIterator<name = {}, year = {:?}, month = {:?}, day = {:?}>",
               self.name, self.year, self.month, self.day)
    }

}

impl<'a> DiaryEntryIterator<'a> {

    pub fn new(diaryname: &'a str, store: &'a Store, iter: StoreIdIterator) -> DiaryEntryIterator<'a> {
        DiaryEntryIterator {
            store: store,
            name: diaryname,
            iter: iter,

            year: None,
            month: None,
            day: None,
        }
    }

    // Filter by year, get all diary entries for this year
    pub fn year(mut self, year: i32) -> DiaryEntryIterator<'a> {
        self.year = Some(year);
        self
    }

    // Filter by month, get all diary entries for this month (every year)
    pub fn month(mut self, month: u32) -> DiaryEntryIterator<'a> {
        self.month = Some(month);
        self
    }

    // Filter by day, get all diary entries for this day (every year, every year)
    pub fn day(mut self, day: u32) -> DiaryEntryIterator<'a> {
        self.day = Some(day);
        self
    }

}

impl<'a> Iterator for DiaryEntryIterator<'a> {
    type Item = Result<DiaryEntry<'a>>;

    fn next(&mut self) -> Option<Result<DiaryEntry<'a>>> {
        loop {
            let next = match self.iter.next() {
                Some(s) => s,
                None => return None,
            };
            debug!("Next element: {:?}", next);

            if next.is_in_diary(self.name) {
                debug!("Seems to be in diary: {:?}", next);
                let id = DiaryId::from_storeid(&next);
                if id.is_none() {
                    debug!("Couldn't parse {:?} into DiaryId", next);
                    continue;
                }
                let id = id.unwrap();
                debug!("Success parsing id = {:?}", id);

                let y = match self.year  { None => true, Some(y) => y == id.year() };
                let m = match self.month { None => true, Some(m) => m == id.month() };
                let d = match self.day   { None => true, Some(d) => d == id.day() };

                if y && m && d {
                    debug!("Return = {:?}", id);
                    return Some(self
                                .store
                                .retrieve(next)
                                .map(|fle| DiaryEntry::new(fle))
                                .map_err(|e| DE::new(DEK::StoreReadError, Some(Box::new(e))))
                                );
                }
            } else {
                debug!("Not in the requested diary ({}): {:?}", self.name, next);
            }
        }
    }

}

<commit_msg>Replace unwrap() with match<commit_after>use std::fmt::{Debug, Formatter, Error as FmtError};
use std::result::Result as RResult;

use libimagstore::store::Store;
use libimagstore::storeid::StoreIdIterator;

use diaryid::DiaryId;
use diaryid::FromStoreId;
use is_in_diary::IsInDiary;
use entry::Entry as DiaryEntry;
use error::DiaryError as DE;
use error::DiaryErrorKind as DEK;
use result::Result;

/// A iterator for iterating over diary entries
pub struct DiaryEntryIterator<'a> {
    store: &'a Store,
    name: &'a str,
    iter: StoreIdIterator,

    year: Option<i32>,
    month: Option<u32>,
    day: Option<u32>,
}

impl<'a> Debug for DiaryEntryIterator<'a> {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "DiaryEntryIterator<name = {}, year = {:?}, month = {:?}, day = {:?}>",
               self.name, self.year, self.month, self.day)
    }

}

impl<'a> DiaryEntryIterator<'a> {

    pub fn new(diaryname: &'a str, store: &'a Store, iter: StoreIdIterator) -> DiaryEntryIterator<'a> {
        DiaryEntryIterator {
            store: store,
            name: diaryname,
            iter: iter,

            year: None,
            month: None,
            day: None,
        }
    }

    // Filter by year, get all diary entries for this year
    pub fn year(mut self, year: i32) -> DiaryEntryIterator<'a> {
        self.year = Some(year);
        self
    }

    // Filter by month, get all diary entries for this month (every year)
    pub fn month(mut self, month: u32) -> DiaryEntryIterator<'a> {
        self.month = Some(month);
        self
    }

    // Filter by day, get all diary entries for this day (every year, every year)
    pub fn day(mut self, day: u32) -> DiaryEntryIterator<'a> {
        self.day = Some(day);
        self
    }

}

impl<'a> Iterator for DiaryEntryIterator<'a> {
    type Item = Result<DiaryEntry<'a>>;

    fn next(&mut self) -> Option<Result<DiaryEntry<'a>>> {
        loop {
            let next = match self.iter.next() {
                Some(s) => s,
                None => return None,
            };
            debug!("Next element: {:?}", next);

            if next.is_in_diary(self.name) {
                debug!("Seems to be in diary: {:?}", next);
                let id = match DiaryId::from_storeid(&next) {
                    Some(i) => i,
                    None => {
                        debug!("Couldn't parse {:?} into DiaryId", next);
                        continue;
                    }
                };
                debug!("Success parsing id = {:?}", id);

                let y = match self.year  { None => true, Some(y) => y == id.year() };
                let m = match self.month { None => true, Some(m) => m == id.month() };
                let d = match self.day   { None => true, Some(d) => d == id.day() };

                if y && m && d {
                    debug!("Return = {:?}", id);
                    return Some(self
                                .store
                                .retrieve(next)
                                .map(|fle| DiaryEntry::new(fle))
                                .map_err(|e| DE::new(DEK::StoreReadError, Some(Box::new(e))))
                                );
                }
            } else {
                debug!("Not in the requested diary ({}): {:?}", self.name, next);
            }
        }
    }

}

<|endoftext|>