<commit_before>use piston_window::*;
use common::{ParamType, MoveDestination, GameEndState};

struct Block<'a> {
    name: &'a str,
    num: u32,
    old_num: u32,
    hotkey: char,
    selected: bool,
    min_val: u32,
    max_val: u32,
    param_type: ParamType
}

impl<'a> Block<'a> {
    pub fn new(name: &'a str,
               num: u32,
               hotkey: char,
               min_val: u32,
               max_val: u32,
               param_type: ParamType) -> Block<'a>
    {
        Block {
            name: name,
            num: num,
            old_num: num,
            hotkey: hotkey,
            selected: false,
            min_val: min_val,
            max_val: max_val,
            param_type: param_type
        }
    }

    pub fn draw(&self,
                context: Context,
                graphics: &mut G2d,
                rect: &mut [u32; 4],
                glyps: &mut Glyphs)
    {
        let margin = 10;
        let text_height = 20;
        let block_height = 30;
        let text_padding = 7;
        let color = if self.selected {
            [0.0, 1.0, 0.0, 1.0]
        } else {
            [1.0, 1.0, 1.0, 1.0]
        };
        rect[1] += 20;
        rectangle(color,
                  [
                    (rect[0] + margin) as f64,
                    (rect[1]) as f64,
                    (rect[2] - 2*margin) as f64,
                    block_height as f64
                  ],
                  context.transform,
                  graphics);
        rect[1] += block_height;
        let transform = context.transform.trans((rect[0] + margin + text_padding) as f64,
                                                (rect[1] - text_padding) as f64);
        text([0.0, 0.0, 0.0, 1.0],
             text_height,
             &*format!("{}: {}", self.name, self.num),
             glyps,
             transform,
             graphics);
        rect[1] += margin + text_height/2;
        let transform = context.transform.trans((rect[0] + margin) as f64,
                                                (rect[1]) as f64);
        let s = if self.selected {
            format!("Use arrows, press \"{}\" to apply changes", self.hotkey)
        } else {
            format!("Press \"{}\" to change", self.hotkey)
        };
        text([1.0, 1.0, 1.0, 1.0],
             text_height,
             &*s,
             glyps,
             transform,
             graphics);
    }

    pub fn inc_safe(&mut self) {
        if self.num < self.max_val {
            self.num += 1;
        }
    }

    pub fn dec_safe(&mut self) {
        if self.num > self.min_val {
            self.num -= 1;
        }
    }

    pub fn apply_changes(&mut self) {
        self.old_num = self.num;
    }

    pub fn discard_changes(&mut self) {
        self.num = self.old_num;
    }
}

pub struct UI<'a> {
    blocks: Vec<Block<'a>>,
    selected_block: i32,
}

impl<'a> UI<'a> {
    pub fn new(height: u32, width: u32, mines: u32) -> UI<'a> {
        UI {
            blocks: vec![Block::new("Field width", width, 'W', 5, 50, ParamType::Width),
                         Block::new("Field height", height, 'H', 5, 50, ParamType::Height),
                         Block::new("Mines", mines, 'M', 1, 2500, ParamType::Mines),
            ],
            selected_block: -1,
        }
    }

    pub fn draw(&mut self,
            context: Context,
            graphics: &mut G2d,
            mut rect: [u32; 4],
            glyps: &mut Glyphs,
            mines_total: u32,
            mines_marked: u32)
    {
        for b in self.blocks.iter() {
            b.draw(context, graphics, &mut rect, glyps);
        }

        let transform = context.transform.trans((rect[0]+10) as f64,
                                                 (rect[1]+27) as f64);
        text([1.0, 1.0, 1.0, 1.0],
             20,
             &*format!("{} marked {} remaining", mines_marked, mines_total as i32 - mines_marked as i32),
             glyps,
             transform,
             graphics);
    }

    pub fn proc_key(&mut self, block: ParamType) -> Option<u32> {
        if self.selected_block >= 0 {
            let selected = self.blocks.get_mut(self.selected_block as usize).unwrap();
            if selected.param_type == block {
                selected.selected = false;
                selected.apply_changes();
                self.selected_block = -1;
                return Some(selected.num);
            }
        }
        for i in 0..self.blocks.len() {
            let item = self.blocks.get_mut(i).unwrap();
            let b = item.param_type == block;
            item.selected = b;
            if b {
                self.selected_block = i as i32;
            } else {
                item.discard_changes();
            }
        }
        None
    }

    pub fn change_selected(&mut self, dest: MoveDestination) {
        assert!(self.selected_block >= 0);
        let selected = self.blocks.get_mut(self.selected_block as usize).unwrap();
        match dest {
            MoveDestination::Up | MoveDestination::Right => selected.inc_safe(),
            MoveDestination::Down | MoveDestination::Left => selected.dec_safe()
        }
    }
}

pub struct EndMessage<'a> {
    visible: bool,
    win: bool,
    message: &'a str
}

static EM_TEXT_BIG      : u32 = 40;
static EM_TEXT_SMALL    : u32 = 20;
static EM_TEXT_PADDING  : u32 = 5;
static EM_BORDER_WIDTH  : u32 = 3;
static EM_BORDER_WIDTH_2: u32 = 6;

static RETRY_MSG: &'static str = "Press 'R' to retry.";

impl<'a> EndMessage<'a> {
    pub fn new() -> EndMessage<'a> {
        EndMessage {
            visible: false,
            win: false,
            message: "Ready",
        }
    }

    pub fn show( &mut self, end_state: GameEndState ) {
        self.win = match end_state {
            GameEndState::Win => true,
            _                 => false };
        self.visible = true;
        self.message = if self.win {
                "You WIN :)"
            } else {
                "Game over :("
            };
    }

    pub fn hide( &mut self ) {
        self.visible = false;
    }

    /// Message Box's size. (width,height).
    pub fn size() -> (u32,u32) {
        (
            350,
            (EM_TEXT_BIG + EM_TEXT_SMALL + (EM_TEXT_PADDING*3) + (EM_BORDER_WIDTH*2))
        )
    }

    pub fn draw(&self,
        context: Context,
        graphics: &mut G2d,
        rect: [u32; 4],
        glyps: &mut Glyphs)
    {
        if !self.visible
        {
            return;
        }

        let border_color = if self.win {
            [0.0, 0.0, 1.0, 1.0]    // Win : Blue
        } else {
            [1.0, 1.0, 0.0, 1.0]    // Lose: yellow
        };

        // draw border
        rectangle(border_color,
            [
                (rect[0]) as f64,
                (rect[1]) as f64,
                (rect[2]) as f64,
                (rect[3]) as f64
            ],
            context.transform,
            graphics);

        // draw background
        rectangle( [1.0, 1.0, 1.0, 1.0],
            [
                (rect[0] +EM_BORDER_WIDTH) as f64,
                (rect[1] +EM_BORDER_WIDTH) as f64,
                (rect[2] -EM_BORDER_WIDTH_2) as f64,
                (rect[3] -EM_BORDER_WIDTH_2) as f64
            ],
            context.transform,
            graphics);

        // Draw game result message
        let trans_msg = context.transform.trans(
            (rect[0] + EM_BORDER_WIDTH + EM_TEXT_PADDING) as f64,
            (rect[1] + EM_BORDER_WIDTH + EM_TEXT_PADDING + EM_TEXT_BIG) as f64);

        text([0.0, 0.0, 0.0, 1.0],
             EM_TEXT_BIG,
             &*self.message,
             glyps,
             trans_msg,
             graphics);

        // Draw 'retry' message
        let trans_retry = context.transform.trans(
            (rect[0] + EM_BORDER_WIDTH + EM_TEXT_PADDING) as f64,
            (rect[1] + EM_BORDER_WIDTH + EM_TEXT_PADDING + EM_TEXT_BIG + EM_TEXT_SMALL) as f64);
        text([0.0, 0.0, 0.0, 1.0],
             EM_TEXT_SMALL,
             &*RETRY_MSG,
             glyps,
             trans_retry,
             graphics);
    }
}
<commit_msg>style: minor changes<commit_after>use piston_window::*;
use common::{ParamType, MoveDestination, GameEndState};

struct Block<'a> {
    name: &'a str,
    num: u32,
    old_num: u32,
    hotkey: char,
    selected: bool,
    min_val: u32,
    max_val: u32,
    param_type: ParamType
}

impl<'a> Block<'a> {
    pub fn new(name: &'a str,
               num: u32,
               hotkey: char,
               min_val: u32,
               max_val: u32,
               param_type: ParamType) -> Block<'a>
    {
        Block {
            name: name,
            num: num,
            old_num: num,
            hotkey: hotkey,
            selected: false,
            min_val: min_val,
            max_val: max_val,
            param_type: param_type
        }
    }

    pub fn draw(&self,
                context: Context,
                graphics: &mut G2d,
                rect: &mut [u32; 4],
                glyps: &mut Glyphs)
    {
        let margin = 10;
        let text_height = 20;
        let block_height = 30;
        let text_padding = 7;
        let color = if self.selected {
            [0.0, 1.0, 0.0, 1.0]
        } else {
            [1.0, 1.0, 1.0, 1.0]
        };
        rect[1] += 20;
        rectangle(color,
                  [
                    (rect[0] + margin) as f64,
                    (rect[1]) as f64,
                    (rect[2] - 2*margin) as f64,
                    block_height as f64
                  ],
                  context.transform,
                  graphics);
        rect[1] += block_height;
        let transform = context.transform.trans((rect[0] + margin + text_padding) as f64,
                                                (rect[1] - text_padding) as f64);
        text([0.0, 0.0, 0.0, 1.0],
             text_height,
             &*format!("{}: {}", self.name, self.num),
             glyps,
             transform,
             graphics);
        rect[1] += margin + text_height/2;
        let transform = context.transform.trans((rect[0] + margin) as f64,
                                                (rect[1]) as f64);
        let s = if self.selected {
            format!("Use arrows, press '{}' to apply changes", self.hotkey)
        } else {
            format!("Press '{}' to change", self.hotkey)
        };
        text([1.0, 1.0, 1.0, 1.0],
             text_height,
             &*s,
             glyps,
             transform,
             graphics);
    }

    pub fn inc_safe(&mut self) {
        if self.num < self.max_val {
            self.num += 1;
        }
    }

    pub fn dec_safe(&mut self) {
        if self.num > self.min_val {
            self.num -= 1;
        }
    }

    pub fn apply_changes(&mut self) {
        self.old_num = self.num;
    }

    pub fn discard_changes(&mut self) {
        self.num = self.old_num;
    }
}

pub struct UI<'a> {
    blocks: Vec<Block<'a>>,
    selected_block: i32,
}

impl<'a> UI<'a> {
    pub fn new(height: u32, width: u32, mines: u32) -> UI<'a> {
        UI {
            blocks: vec![Block::new("Field width", width, 'W', 5, 50, ParamType::Width),
                         Block::new("Field height", height, 'H', 5, 50, ParamType::Height),
                         Block::new("Mines", mines, 'M', 1, 2500, ParamType::Mines),
            ],
            selected_block: -1,
        }
    }

    pub fn draw(&mut self,
            context: Context,
            graphics: &mut G2d,
            mut rect: [u32; 4],
            glyps: &mut Glyphs,
            mines_total: u32,
            mines_marked: u32)
    {
        for b in self.blocks.iter() {
            b.draw(context, graphics, &mut rect, glyps);
        }

        let transform = context.transform.trans((rect[0]+10) as f64,
                                                 (rect[1]+27) as f64);
        text([1.0, 1.0, 1.0, 1.0],
             20,
             &*format!("{} marked {} remaining", mines_marked, mines_total as i32 - mines_marked as i32),
             glyps,
             transform,
             graphics);
    }

    pub fn proc_key(&mut self, block: ParamType) -> Option<u32> {
        if self.selected_block >= 0 {
            let selected = self.blocks.get_mut(self.selected_block as usize).unwrap();
            if selected.param_type == block {
                selected.selected = false;
                selected.apply_changes();
                self.selected_block = -1;
                return Some(selected.num);
            }
        }
        for i in 0..self.blocks.len() {
            let item = self.blocks.get_mut(i).unwrap();
            let b = item.param_type == block;
            item.selected = b;
            if b {
                self.selected_block = i as i32;
            } else {
                item.discard_changes();
            }
        }
        None
    }

    pub fn change_selected(&mut self, dest: MoveDestination) {
        assert!(self.selected_block >= 0);
        let selected = self.blocks.get_mut(self.selected_block as usize).unwrap();
        match dest {
            MoveDestination::Up | MoveDestination::Right => selected.inc_safe(),
            MoveDestination::Down | MoveDestination::Left => selected.dec_safe()
        }
    }
}

pub struct EndMessage<'a> {
    visible: bool,
    win: bool,
    message: &'a str
}

static EM_TEXT_BIG      : u32 = 40;
static EM_TEXT_SMALL    : u32 = 20;
static EM_TEXT_PADDING  : u32 = 5;
static EM_BORDER_WIDTH  : u32 = 3;
static EM_BORDER_WIDTH_2: u32 = 6;

static RETRY_MSG: &'static str = "Press 'R' to play again";

impl<'a> EndMessage<'a> {
    pub fn new() -> EndMessage<'a> {
        EndMessage {
            visible: false,
            win: false,
            message: "Ready",
        }
    }

    pub fn show( &mut self, end_state: GameEndState ) {
        self.win = match end_state {
            GameEndState::Win => true,
            _                 => false };
        self.visible = true;
        self.message = if self.win {
                "You WIN :)"
            } else {
                "Game over :("
            };
    }

    pub fn hide( &mut self ) {
        self.visible = false;
    }

    /// Message Box's size. (width,height).
    pub fn size() -> (u32,u32) {
        (
            350,
            (EM_TEXT_BIG + EM_TEXT_SMALL + (EM_TEXT_PADDING*4) + (EM_BORDER_WIDTH*2))
        )
    }

    pub fn draw(&self,
        context: Context,
        graphics: &mut G2d,
        rect: [u32; 4],
        glyps: &mut Glyphs)
    {
        if !self.visible
        {
            return;
        }

        let border_color = if self.win {
            [0.0, 0.0, 1.0, 1.0]    // Win : Blue
        } else {
            [1.0, 1.0, 0.0, 1.0]    // Lose: yellow
        };

        // draw border
        rectangle(border_color,
            [
                (rect[0]) as f64,
                (rect[1]) as f64,
                (rect[2]) as f64,
                (rect[3]) as f64
            ],
            context.transform,
            graphics);

        // draw background
        rectangle( [1.0, 1.0, 1.0, 1.0],
            [
                (rect[0] +EM_BORDER_WIDTH) as f64,
                (rect[1] +EM_BORDER_WIDTH) as f64,
                (rect[2] -EM_BORDER_WIDTH_2) as f64,
                (rect[3] -EM_BORDER_WIDTH_2) as f64
            ],
            context.transform,
            graphics);

        // Draw game result message
        let trans_msg = context.transform.trans(
            (rect[0] + EM_BORDER_WIDTH + EM_TEXT_PADDING) as f64,
            (rect[1] + EM_BORDER_WIDTH + EM_TEXT_PADDING + EM_TEXT_BIG) as f64);

        text([0.0, 0.0, 0.0, 1.0],
             EM_TEXT_BIG,
             &*self.message,
             glyps,
             trans_msg,
             graphics);

        // Draw 'play again' message
        let trans_retry = context.transform.trans(
            (rect[0] + EM_BORDER_WIDTH + EM_TEXT_PADDING) as f64,
            (rect[1] + EM_BORDER_WIDTH + EM_TEXT_PADDING*2 + EM_TEXT_BIG + EM_TEXT_SMALL) as f64);
        text([0.0, 0.0, 0.0, 1.0],
             EM_TEXT_SMALL,
             &*RETRY_MSG,
             glyps,
             trans_retry,
             graphics);
    }
}
<|endoftext|>


<commit_before>type Cell = u8;

pub struct VM {
    cells: [Cell; 30_000],
    data_pointer: usize,
}

impl VM {
    pub fn new() -> VM {
        VM { cells: [0; 30_000], data_pointer: 0 }
    }

    pub fn output(&self) -> Cell {
        self.cells[self.data_pointer]
    }

    pub fn increment(&mut self) {
        self.cells[self.data_pointer] = self.cells[self.data_pointer] + 1;
    }

    pub fn decrement(&mut self) {
        self.cells[self.data_pointer] = self.cells[self.data_pointer] - 1;
    }

    pub fn right_shift(&mut self) {
        self.data_pointer = self.data_pointer + 1;
    }

    pub fn left_shift(&mut self) {
        self.data_pointer = self.data_pointer - 1;
    }
}
<commit_msg>Change definition of vm.output to print cell value<commit_after>type Cell = u8;

pub struct VM {
    cells: [Cell; 30_000],
    data_pointer: usize,
}

impl VM {
    pub fn new() -> VM {
        VM { cells: [0; 30_000], data_pointer: 0 }
    }

    pub fn output(&self) {
        print!("{}", self.cells[self.data_pointer]);
    }

    pub fn increment(&mut self) {
        self.cells[self.data_pointer] = self.cells[self.data_pointer] + 1;
    }

    pub fn decrement(&mut self) {
        self.cells[self.data_pointer] = self.cells[self.data_pointer] - 1;
    }

    pub fn right_shift(&mut self) {
        self.data_pointer = self.data_pointer + 1;
    }

    pub fn left_shift(&mut self) {
        self.data_pointer = self.data_pointer - 1;
    }
}
<|endoftext|>


<commit_before>
type RegisterT = i64;

struct Vm {
    registers: Vec<RegisterT>,
    program_counter: usize,
    program: Program,
}

impl Vm {
    fn run(&mut self) -> RegisterT {
        use self::Instruction::*;

        let mut stack = vec![StackFrame { ret_addr: self.program_counter }];

        loop {
            let instr = self.program.instructions[self.program_counter];

            match instr {
                LoadConstImm(val) => {
                    self.push_reg(val);
                }
                Move { src_idx, num } => {
                    for i in 0..num as usize {
                        let val = self.registers[src_idx as usize + i];
                        self.push_reg(val);
                    }
                }
                CallSpecial { builtin_idx, begin_args_idx, num_args } => {
                    match builtin_idx {
                        0 => {
                            let begin = begin_args_idx as usize;
                            let end = begin + num_args as usize;
                            let ret_val = self.registers[begin..end]
                                              .iter()
                                              .fold(0, |acc, e| acc + e);

                            self.push_reg(ret_val);
                        }
                        _ => unimplemented!(),
                    }
                }
                CallNormal { .. } => unimplemented!(),
                Exit(reg_idx) => return self.registers[reg_idx as usize],
            }
            self.program_counter += 1;
        }
    }

    fn push_reg(&mut self, val: RegisterT) {
        self.registers.push(val);
    }
}

struct Program {
    instructions: Vec<Instruction>,
}

struct StackFrame {
    ret_addr: usize,
}

#[derive(Copy, Clone)]
enum Instruction {
    /// Load imm into a fresh register
    LoadConstImm(i64),
    /// Call builtin and put result into a fresh register
    CallSpecial {
        builtin_idx: u32,
        begin_args_idx: u16,
        num_args: u16,
    },
    /// Call fn and put result into a fresh register
    CallNormal {
        target_addr: u32,
        begin_args_idx: u16,
        num_args: u16,
    },
    /// Copy range of registers into range of fresh registers
    Move {
        src_idx: u16,
        num: u16,
    },
    /// Exit the program, returning value in indexed register
    Exit(u16),
}

#[cfg(test)]
mod test {
    use super::{Program, Vm};
    use super::Instruction::*;

    #[test]
    fn raw_program_addition() {
        // (+ 1 2 3) == 6

        let mut vm = Vm {
            program_counter: 0,
            registers: vec![],
            program: Program {
                instructions: vec![LoadConstImm(1),
                                   LoadConstImm(2),
                                   LoadConstImm(3),
                                   CallSpecial {
                                       builtin_idx: 0, // TODO
                                       begin_args_idx: 0,
                                       num_args: 3,
                                   },
                                   Exit(3)],
            },
        };

        assert_eq!(vm.run(), 6);
    }
}
<commit_msg>Program builder<commit_after>
type RegisterT = i64;

struct Vm {
    registers: Vec<RegisterT>,
    program_counter: usize,
    program: Program,
}

impl Vm {
    fn run(&mut self) -> RegisterT {
        use self::Instruction::*;

        let mut stack = vec![StackFrame { ret_addr: self.program_counter }];

        loop {
            let instr = self.program.instructions[self.program_counter];

            match instr {
                LoadConstImm(val) => {
                    self.push_reg(val);
                }
                Move { src_idx, num } => {
                    for i in 0..num as usize {
                        let val = self.registers[src_idx as usize + i];
                        self.push_reg(val);
                    }
                }
                CallSpecial { builtin_idx, begin_args_idx, num_args } => {
                    match builtin_idx {
                        0 => {
                            let begin = begin_args_idx as usize;
                            let end = begin + num_args as usize;
                            let ret_val = self.registers[begin..end]
                                              .iter()
                                              .fold(0, |acc, e| acc + e);

                            self.push_reg(ret_val);
                        }
                        _ => unimplemented!(),
                    }
                }
                CallNormal { .. } => unimplemented!(),
                Exit(reg_idx) => return self.registers[reg_idx as usize],
            }
            self.program_counter += 1;
        }
    }

    fn push_reg(&mut self, val: RegisterT) {
        self.registers.push(val);
    }
}

#[derive(Debug, PartialEq)]
struct Program {
    instructions: Vec<Instruction>,
}

fn new_program() -> ProgramBuilder {
    ProgramBuilder {
        reg_counter: 0,
        instructions: vec![],
    }
}

struct ProgramBuilder {
    reg_counter: usize,
    instructions: Vec<Instruction>,
}

impl ProgramBuilder {
    fn load_const(mut self, val: RegisterT) -> Self {
        self.instructions.push(Instruction::LoadConstImm(val));
        self.reg_counter += 1;
        self
    }

    fn call_special(mut self, builtin_idx: u32, arg_idx: u16, num_args: u16) -> Self {
        self.instructions.push(Instruction::CallSpecial {
            builtin_idx: builtin_idx,
            begin_args_idx: arg_idx,
            num_args: num_args,
        });
        self.reg_counter += 1;
        self
    }

    fn pop_exit(mut self) -> Self {
        let reg_idx = self.reg_counter - 1;
        self.instructions.push(Instruction::Exit(reg_idx as u16));
        self
    }

    fn finish(self) -> Program {
        Program { instructions: self.instructions }
    }
}

struct StackFrame {
    ret_addr: usize,
}

#[derive(Copy, Clone, PartialEq, Debug)]
enum Instruction {
    /// Load imm into a fresh register
    LoadConstImm(i64),
    /// Call builtin and put result into a fresh register
    CallSpecial {
        builtin_idx: u32,
        begin_args_idx: u16,
        num_args: u16,
    },
    /// Call fn and put result into a fresh register
    CallNormal {
        target_addr: u32,
        begin_args_idx: u16,
        num_args: u16,
    },
    /// Copy range of registers into range of fresh registers
    Move {
        src_idx: u16,
        num: u16,
    },
    /// Exit the program, returning value in indexed register
    Exit(u16),
}

#[cfg(test)]
mod test {
    use super::{Vm, new_program};

    #[test]
    fn raw_program_addition() {
        // (+ 1 2 3) == 6

        let mut vm = Vm {
            program_counter: 0,
            registers: vec![],
            program: new_program()
                         .load_const(1)
                         .load_const(2)
                         .load_const(3)
                         .call_special(0, 0, 3)
                         .pop_exit()
                         .finish(),
        };

        assert_eq!(vm.run(), 6);
    }
}
<|endoftext|>


<commit_before>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The `Clone` trait for types that cannot be 'implicitly copied'.
//!
//! In Rust, some simple types are "implicitly copyable" and when you
//! assign them or pass them as arguments, the receiver will get a copy,
//! leaving the original value in place. These types do not require
//! allocation to copy and do not have finalizers (i.e. they do not
//! contain owned boxes or implement [`Drop`]), so the compiler considers
//! them cheap and safe to copy. For other types copies must be made
//! explicitly, by convention implementing the [`Clone`] trait and calling
//! the [`clone`][clone] method.
//!
//! [`Clone`]: trait.Clone.html
//! [clone]: trait.Clone.html#tymethod.clone
//! [`Drop`]: ../../std/ops/trait.Drop.html
//!
//! Basic usage example:
//!
//! ```
//! let s = String::new(); // String type implements Clone
//! let copy = s.clone(); // so we can clone it
//! ```
//!
//! To easily implement the Clone trait, you can also use
//! `#[derive(Clone)]`. Example:
//!
//! ```
//! #[derive(Clone)] // we add the Clone trait to Morpheus struct
//! struct Morpheus {
//!    blue_pill: f32,
//!    red_pill: i64,
//! }
//!
//! fn main() {
//!    let f = Morpheus { blue_pill: 0.0, red_pill: 0 };
//!    let copy = f.clone(); // and now we can clone it!
//! }
//! ```

#![stable(feature = "rust1", since = "1.0.0")]

/// A common trait for the ability to explicitly duplicate an object.
///
/// Differs from [`Copy`] in that [`Copy`] is implicit and extremely inexpensive, while
/// `Clone` is always explicit and may or may not be expensive. In order to enforce
/// these characteristics, Rust does not allow you to reimplement [`Copy`], but you
/// may reimplement `Clone` and run arbitrary code.
///
/// Since `Clone` is more general than [`Copy`], you can automatically make anything
/// [`Copy`] be `Clone` as well.
///
/// ## Derivable
///
/// This trait can be used with `#[derive]` if all fields are `Clone`. The `derive`d
/// implementation of [`clone`] calls [`clone`] on each field.
///
/// ## How can I implement `Clone`?
///
/// Types that are [`Copy`] should have a trivial implementation of `Clone`. More formally:
/// if `T: Copy`, `x: T`, and `y: &T`, then `let x = y.clone();` is equivalent to `let x = *y;`.
/// Manual implementations should be careful to uphold this invariant; however, unsafe code
/// must not rely on it to ensure memory safety.
///
/// An example is an array holding more than 32 elements of a type that is `Clone`; the standard
/// library only implements `Clone` up until arrays of size 32. In this case, the implementation of
/// `Clone` cannot be `derive`d, but can be implemented as:
///
/// [`Copy`]: ../../std/marker/trait.Copy.html
/// [`clone`]: trait.Clone.html#tymethod.clone
///
/// ```
/// #[derive(Copy)]
/// struct Stats {
///    frequencies: [i32; 100],
/// }
///
/// impl Clone for Stats {
///     fn clone(&self) -> Stats { *self }
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Clone : Sized {
    /// Returns a copy of the value.
    ///
    /// # Examples
    ///
    /// ```
    /// let hello = "Hello"; // &str implements Clone
    ///
    /// assert_eq!("Hello", hello.clone());
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn clone(&self) -> Self;

    /// Performs copy-assignment from `source`.
    ///
    /// `a.clone_from(&b)` is equivalent to `a = b.clone()` in functionality,
    /// but can be overridden to reuse the resources of `a` to avoid unnecessary
    /// allocations.
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    fn clone_from(&mut self, source: &Self) {
        *self = source.clone()
    }
}

// FIXME(aburka): these structs are used solely by #[derive] to
// assert that every component of a type implements Clone or Copy.
//
// These structs should never appear in user code.
#[doc(hidden)]
#[allow(missing_debug_implementations)]
#[unstable(feature = "derive_clone_copy",
           reason = "deriving hack, should not be public",
           issue = "0")]
pub struct AssertParamIsClone<T: Clone + ?Sized> { _field: ::marker::PhantomData<T> }
#[doc(hidden)]
#[allow(missing_debug_implementations)]
#[unstable(feature = "derive_clone_copy",
           reason = "deriving hack, should not be public",
           issue = "0")]
pub struct AssertParamIsCopy<T: Copy + ?Sized> { _field: ::marker::PhantomData<T> }

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Clone for &'a T {
    /// Returns a shallow copy of the reference.
    #[inline]
    fn clone(&self) -> &'a T { *self }
}

macro_rules! clone_impl {
    ($t:ty) => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl Clone for $t {
            /// Returns a deep copy of the value.
            #[inline]
            fn clone(&self) -> $t { *self }
        }
    }
}

clone_impl! { isize }
clone_impl! { i8 }
clone_impl! { i16 }
clone_impl! { i32 }
clone_impl! { i64 }
clone_impl! { i128 }

clone_impl! { usize }
clone_impl! { u8 }
clone_impl! { u16 }
clone_impl! { u32 }
clone_impl! { u64 }
clone_impl! { u128 }

clone_impl! { f32 }
clone_impl! { f64 }

clone_impl! { () }
clone_impl! { bool }
clone_impl! { char }
<commit_msg>Auto merge of #43406 - canndrew:never-impl-clone, r=alexcrichton<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The `Clone` trait for types that cannot be 'implicitly copied'.
//!
//! In Rust, some simple types are "implicitly copyable" and when you
//! assign them or pass them as arguments, the receiver will get a copy,
//! leaving the original value in place. These types do not require
//! allocation to copy and do not have finalizers (i.e. they do not
//! contain owned boxes or implement [`Drop`]), so the compiler considers
//! them cheap and safe to copy. For other types copies must be made
//! explicitly, by convention implementing the [`Clone`] trait and calling
//! the [`clone`][clone] method.
//!
//! [`Clone`]: trait.Clone.html
//! [clone]: trait.Clone.html#tymethod.clone
//! [`Drop`]: ../../std/ops/trait.Drop.html
//!
//! Basic usage example:
//!
//! ```
//! let s = String::new(); // String type implements Clone
//! let copy = s.clone(); // so we can clone it
//! ```
//!
//! To easily implement the Clone trait, you can also use
//! `#[derive(Clone)]`. Example:
//!
//! ```
//! #[derive(Clone)] // we add the Clone trait to Morpheus struct
//! struct Morpheus {
//!    blue_pill: f32,
//!    red_pill: i64,
//! }
//!
//! fn main() {
//!    let f = Morpheus { blue_pill: 0.0, red_pill: 0 };
//!    let copy = f.clone(); // and now we can clone it!
//! }
//! ```

#![stable(feature = "rust1", since = "1.0.0")]

/// A common trait for the ability to explicitly duplicate an object.
///
/// Differs from [`Copy`] in that [`Copy`] is implicit and extremely inexpensive, while
/// `Clone` is always explicit and may or may not be expensive. In order to enforce
/// these characteristics, Rust does not allow you to reimplement [`Copy`], but you
/// may reimplement `Clone` and run arbitrary code.
///
/// Since `Clone` is more general than [`Copy`], you can automatically make anything
/// [`Copy`] be `Clone` as well.
///
/// ## Derivable
///
/// This trait can be used with `#[derive]` if all fields are `Clone`. The `derive`d
/// implementation of [`clone`] calls [`clone`] on each field.
///
/// ## How can I implement `Clone`?
///
/// Types that are [`Copy`] should have a trivial implementation of `Clone`. More formally:
/// if `T: Copy`, `x: T`, and `y: &T`, then `let x = y.clone();` is equivalent to `let x = *y;`.
/// Manual implementations should be careful to uphold this invariant; however, unsafe code
/// must not rely on it to ensure memory safety.
///
/// An example is an array holding more than 32 elements of a type that is `Clone`; the standard
/// library only implements `Clone` up until arrays of size 32. In this case, the implementation of
/// `Clone` cannot be `derive`d, but can be implemented as:
///
/// [`Copy`]: ../../std/marker/trait.Copy.html
/// [`clone`]: trait.Clone.html#tymethod.clone
///
/// ```
/// #[derive(Copy)]
/// struct Stats {
///    frequencies: [i32; 100],
/// }
///
/// impl Clone for Stats {
///     fn clone(&self) -> Stats { *self }
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Clone : Sized {
    /// Returns a copy of the value.
    ///
    /// # Examples
    ///
    /// ```
    /// let hello = "Hello"; // &str implements Clone
    ///
    /// assert_eq!("Hello", hello.clone());
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn clone(&self) -> Self;

    /// Performs copy-assignment from `source`.
    ///
    /// `a.clone_from(&b)` is equivalent to `a = b.clone()` in functionality,
    /// but can be overridden to reuse the resources of `a` to avoid unnecessary
    /// allocations.
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    fn clone_from(&mut self, source: &Self) {
        *self = source.clone()
    }
}

// FIXME(aburka): these structs are used solely by #[derive] to
// assert that every component of a type implements Clone or Copy.
//
// These structs should never appear in user code.
#[doc(hidden)]
#[allow(missing_debug_implementations)]
#[unstable(feature = "derive_clone_copy",
           reason = "deriving hack, should not be public",
           issue = "0")]
pub struct AssertParamIsClone<T: Clone + ?Sized> { _field: ::marker::PhantomData<T> }
#[doc(hidden)]
#[allow(missing_debug_implementations)]
#[unstable(feature = "derive_clone_copy",
           reason = "deriving hack, should not be public",
           issue = "0")]
pub struct AssertParamIsCopy<T: Copy + ?Sized> { _field: ::marker::PhantomData<T> }

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Clone for &'a T {
    /// Returns a shallow copy of the reference.
    #[inline]
    fn clone(&self) -> &'a T { *self }
}

macro_rules! clone_impl {
    ($t:ty) => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl Clone for $t {
            /// Returns a deep copy of the value.
            #[inline]
            fn clone(&self) -> $t { *self }
        }
    }
}

clone_impl! { isize }
clone_impl! { i8 }
clone_impl! { i16 }
clone_impl! { i32 }
clone_impl! { i64 }
clone_impl! { i128 }

clone_impl! { usize }
clone_impl! { u8 }
clone_impl! { u16 }
clone_impl! { u32 }
clone_impl! { u64 }
clone_impl! { u128 }

clone_impl! { f32 }
clone_impl! { f64 }

clone_impl! { ! }
clone_impl! { () }
clone_impl! { bool }
clone_impl! { char }
<|endoftext|>


<commit_before>#![feature(test)]

extern crate test;
extern crate rand;

const RAND_BENCH_N: u64 = 1000;

use test::Bencher;

use rand::prelude::*;
use rand::seq::*;

#[bench]
fn misc_gen_bool_const(b: &mut Bencher) {
    let mut rng = StdRng::from_rng(&mut thread_rng()).unwrap();
    b.iter(|| {
        let mut accum = true;
        for _ in 0..::RAND_BENCH_N {
            accum ^= rng.gen_bool(0.18);
        }
        accum
    })
}

#[bench]
fn misc_gen_bool_var(b: &mut Bencher) {
    let mut rng = StdRng::from_rng(&mut thread_rng()).unwrap();
    b.iter(|| {
        let mut accum = true;
        let mut p = 0.18;
        for _ in 0..::RAND_BENCH_N {
            accum ^= rng.gen_bool(p);
            p += 0.0001;
        }
        accum
    })
}

#[bench]
fn misc_bernoulli_const(b: &mut Bencher) {
    let mut rng = StdRng::from_rng(&mut thread_rng()).unwrap();
    let d = rand::distributions::Bernoulli::new(0.18);
    b.iter(|| {
        // Can be evaluated at compile time.
        let mut accum = true;
        for _ in 0..::RAND_BENCH_N {
            accum ^= rng.sample(d);
        }
        accum
    })
}

#[bench]
fn misc_bernoulli_var(b: &mut Bencher) {
    let mut rng = StdRng::from_rng(&mut thread_rng()).unwrap();
    b.iter(|| {
        let mut accum = true;
        let mut p = 0.18;
        for _ in 0..::RAND_BENCH_N {
            let d = rand::distributions::Bernoulli::new(p);
            accum ^= rng.sample(d);
            p += 0.0001;
        }
        accum
    })
}

macro_rules! sample_binomial {
    ($name:ident, $n:expr, $p:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
            let (n, p) = ($n, $p);
            b.iter(|| {
                let d = rand::distributions::Binomial::new(n, p);
                rng.sample(d)
            })
        }
    }
}

sample_binomial!(misc_binomial_1, 1, 0.9);
sample_binomial!(misc_binomial_10, 10, 0.9);
sample_binomial!(misc_binomial_100, 100, 0.99);
sample_binomial!(misc_binomial_1000, 1000, 0.01);
sample_binomial!(misc_binomial_1e12, 1000_000_000_000, 0.2);

#[bench]
fn misc_shuffle_100(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
    let x : &mut [usize] = &mut [1; 100];
    b.iter(|| {
        rng.shuffle(x);
        x[0]
    })
}

#[bench]
fn misc_sample_iter_10_of_100(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
    let x : &[usize] = &[1; 100];
    b.iter(|| {
        sample_iter(&mut rng, x, 10).unwrap_or_else(|e| e)
    })
}

#[bench]
fn misc_sample_slice_10_of_100(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
    let x : &[usize] = &[1; 100];
    b.iter(|| {
        sample_slice(&mut rng, x, 10)
    })
}

#[bench]
fn misc_sample_slice_ref_10_of_100(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
    let x : &[usize] = &[1; 100];
    b.iter(|| {
        sample_slice_ref(&mut rng, x, 10)
    })
}

macro_rules! sample_indices {
    ($name:ident, $amount:expr, $length:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
            b.iter(|| {
                sample_indices(&mut rng, $length, $amount)
            })
        }
    }
}

sample_indices!(misc_sample_indices_10_of_1k, 10, 1000);
sample_indices!(misc_sample_indices_50_of_1k, 50, 1000);
sample_indices!(misc_sample_indices_100_of_1k, 100, 1000);

#[bench]
fn gen_1k_iter_repeat(b: &mut Bencher) {
    use std::iter;
    let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
    b.iter(|| {
        let v: Vec<u64> = iter::repeat(()).map(|()| rng.gen()).take(128).collect();
        v
    });
    b.bytes = 1024;
}

#[bench]
#[allow(deprecated)]
fn gen_1k_gen_iter(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
    b.iter(|| {
        let v: Vec<u64> = rng.gen_iter().take(128).collect();
        v
    });
    b.bytes = 1024;
}

#[bench]
fn gen_1k_sample_iter(b: &mut Bencher) {
    use rand::distributions::{Distribution, Standard};
    let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
    b.iter(|| {
        let v: Vec<u64> = Standard.sample_iter(&mut rng).take(128).collect();
        v
    });
    b.bytes = 1024;
}

#[bench]
fn gen_1k_fill(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
    let mut buf = [0u64; 128];
    b.iter(|| {
        rng.fill(&mut buf[..]);
        buf
    });
    b.bytes = 1024;
}
<commit_msg>Add benchmark: gen_1k_gen_array<commit_after>#![feature(test)]

extern crate test;
extern crate rand;

const RAND_BENCH_N: u64 = 1000;

use test::Bencher;

use rand::prelude::*;
use rand::seq::*;

#[bench]
fn misc_gen_bool_const(b: &mut Bencher) {
    let mut rng = StdRng::from_rng(&mut thread_rng()).unwrap();
    b.iter(|| {
        let mut accum = true;
        for _ in 0..::RAND_BENCH_N {
            accum ^= rng.gen_bool(0.18);
        }
        accum
    })
}

#[bench]
fn misc_gen_bool_var(b: &mut Bencher) {
    let mut rng = StdRng::from_rng(&mut thread_rng()).unwrap();
    b.iter(|| {
        let mut accum = true;
        let mut p = 0.18;
        for _ in 0..::RAND_BENCH_N {
            accum ^= rng.gen_bool(p);
            p += 0.0001;
        }
        accum
    })
}

#[bench]
fn misc_bernoulli_const(b: &mut Bencher) {
    let mut rng = StdRng::from_rng(&mut thread_rng()).unwrap();
    let d = rand::distributions::Bernoulli::new(0.18);
    b.iter(|| {
        // Can be evaluated at compile time.
        let mut accum = true;
        for _ in 0..::RAND_BENCH_N {
            accum ^= rng.sample(d);
        }
        accum
    })
}

#[bench]
fn misc_bernoulli_var(b: &mut Bencher) {
    let mut rng = StdRng::from_rng(&mut thread_rng()).unwrap();
    b.iter(|| {
        let mut accum = true;
        let mut p = 0.18;
        for _ in 0..::RAND_BENCH_N {
            let d = rand::distributions::Bernoulli::new(p);
            accum ^= rng.sample(d);
            p += 0.0001;
        }
        accum
    })
}

macro_rules! sample_binomial {
    ($name:ident, $n:expr, $p:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
            let (n, p) = ($n, $p);
            b.iter(|| {
                let d = rand::distributions::Binomial::new(n, p);
                rng.sample(d)
            })
        }
    }
}

sample_binomial!(misc_binomial_1, 1, 0.9);
sample_binomial!(misc_binomial_10, 10, 0.9);
sample_binomial!(misc_binomial_100, 100, 0.99);
sample_binomial!(misc_binomial_1000, 1000, 0.01);
sample_binomial!(misc_binomial_1e12, 1000_000_000_000, 0.2);

#[bench]
fn misc_shuffle_100(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
    let x : &mut [usize] = &mut [1; 100];
    b.iter(|| {
        rng.shuffle(x);
        x[0]
    })
}

#[bench]
fn misc_sample_iter_10_of_100(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
    let x : &[usize] = &[1; 100];
    b.iter(|| {
        sample_iter(&mut rng, x, 10).unwrap_or_else(|e| e)
    })
}

#[bench]
fn misc_sample_slice_10_of_100(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
    let x : &[usize] = &[1; 100];
    b.iter(|| {
        sample_slice(&mut rng, x, 10)
    })
}

#[bench]
fn misc_sample_slice_ref_10_of_100(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
    let x : &[usize] = &[1; 100];
    b.iter(|| {
        sample_slice_ref(&mut rng, x, 10)
    })
}

macro_rules! sample_indices {
    ($name:ident, $amount:expr, $length:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
            b.iter(|| {
                sample_indices(&mut rng, $length, $amount)
            })
        }
    }
}

sample_indices!(misc_sample_indices_10_of_1k, 10, 1000);
sample_indices!(misc_sample_indices_50_of_1k, 50, 1000);
sample_indices!(misc_sample_indices_100_of_1k, 100, 1000);

#[bench]
fn gen_1k_iter_repeat(b: &mut Bencher) {
    use std::iter;
    let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
    b.iter(|| {
        let v: Vec<u64> = iter::repeat(()).map(|()| rng.gen()).take(128).collect();
        v
    });
    b.bytes = 1024;
}

#[bench]
#[allow(deprecated)]
fn gen_1k_gen_iter(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
    b.iter(|| {
        let v: Vec<u64> = rng.gen_iter().take(128).collect();
        v
    });
    b.bytes = 1024;
}

#[bench]
fn gen_1k_sample_iter(b: &mut Bencher) {
    use rand::distributions::{Distribution, Standard};
    let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
    b.iter(|| {
        let v: Vec<u64> = Standard.sample_iter(&mut rng).take(128).collect();
        v
    });
    b.bytes = 1024;
}

#[bench]
fn gen_1k_gen_array(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
    b.iter(|| {
        // max supported array length is 32!
        let v: [[u64; 32]; 4] = rng.gen();
        v
    });
    b.bytes = 1024;
}

#[bench]
fn gen_1k_fill(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
    let mut buf = [0u64; 128];
    b.iter(|| {
        rng.fill(&mut buf[..]);
        buf
    });
    b.bytes = 1024;
}
<|endoftext|>


<commit_before>extern crate mdbook;

mod dummy_book;

use dummy_book::DummyBook;
use mdbook::book::Book;
use mdbook::config::Config;
use mdbook::errors::*;
use mdbook::preprocess::{Preprocessor, PreprocessorContext};
use mdbook::renderer::{RenderContext, Renderer};
use mdbook::MDBook;
use std::sync::{Arc, Mutex};

struct Spy(Arc<Mutex<Inner>>);

#[derive(Debug, Default)]
struct Inner {
    run_count: usize,
    rendered_with: Vec<String>,
}

impl Preprocessor for Spy {
    fn name(&self) -> &str {
        "dummy"
    }

    fn run(&self, ctx: &PreprocessorContext, book: Book) -> Result<Book> {
        let mut inner = self.0.lock().unwrap();
        inner.run_count += 1;
        inner.rendered_with.push(ctx.renderer.clone());
        Ok(book)
    }
}

impl Renderer for Spy {
    fn name(&self) -> &str {
        "dummy"
    }

    fn render(&self, _ctx: &RenderContext) -> Result<()> {
        let mut inner = self.0.lock().unwrap();
        inner.run_count += 1;
        Ok(())
    }
}

#[test]
fn mdbook_runs_preprocessors() {
    let spy: Arc<Mutex<Inner>> = Default::default();

    let temp = DummyBook::new().build().unwrap();
    let cfg = Config::default();

    let mut book = MDBook::load_with_config(temp.path(), cfg).unwrap();
    book.with_preprecessor(Spy(Arc::clone(&spy)));
    book.build().unwrap();

    let inner = spy.lock().unwrap();
    assert_eq!(inner.run_count, 1);
    assert_eq!(inner.rendered_with.len(), 1);
    assert_eq!(
        "html", inner.rendered_with[0],
        "We should have been run with the default HTML renderer"
    );
}

#[test]
fn mdbook_runs_renderers() {
    let spy: Arc<Mutex<Inner>> = Default::default();

    let temp = DummyBook::new().build().unwrap();
    let cfg = Config::default();

    let mut book = MDBook::load_with_config(temp.path(), cfg).unwrap();
    book.with_renderer(Spy(Arc::clone(&spy)));
    book.build().unwrap();

    let inner = spy.lock().unwrap();
    assert_eq!(inner.run_count, 1);
}
<commit_msg>Update build_process.rs<commit_after>extern crate mdbook;

mod dummy_book;

use dummy_book::DummyBook;
use mdbook::book::Book;
use mdbook::config::Config;
use mdbook::errors::*;
use mdbook::preprocess::{Preprocessor, PreprocessorContext};
use mdbook::renderer::{RenderContext, Renderer};
use mdbook::MDBook;
use std::sync::{Arc, Mutex};

struct Spy(Arc<Mutex<Inner>>);

#[derive(Debug, Default)]
struct Inner {
    run_count: usize,
    rendered_with: Vec<String>,
}

impl Preprocessor for Spy {
    fn name(&self) -> &str {
        "dummy"
    }

    fn run(&self, ctx: &PreprocessorContext, book: Book) -> Result<Book> {
        let mut inner = self.0.lock().unwrap();
        inner.run_count += 1;
        inner.rendered_with.push(ctx.renderer.clone());
        Ok(book)
    }
}

impl Renderer for Spy {
    fn name(&self) -> &str {
        "dummy"
    }

    fn render(&self, _ctx: &RenderContext) -> Result<()> {
        let mut inner = self.0.lock().unwrap();
        inner.run_count += 1;
        Ok(())
    }
}

#[test]
fn mdbook_runs_preprocessors() {
    let spy: Arc<Mutex<Inner>> = Default::default();

    let temp = DummyBook::new().build().unwrap();
    let cfg = Config::default();

    let mut book = MDBook::load_with_config(temp.path(), cfg).unwrap();
    book.with_preprocessor(Spy(Arc::clone(&spy)));
    book.build().unwrap();

    let inner = spy.lock().unwrap();
    assert_eq!(inner.run_count, 1);
    assert_eq!(inner.rendered_with.len(), 1);
    assert_eq!(
        "html", inner.rendered_with[0],
        "We should have been run with the default HTML renderer"
    );
}

#[test]
fn mdbook_runs_renderers() {
    let spy: Arc<Mutex<Inner>> = Default::default();

    let temp = DummyBook::new().build().unwrap();
    let cfg = Config::default();

    let mut book = MDBook::load_with_config(temp.path(), cfg).unwrap();
    book.with_renderer(Spy(Arc::clone(&spy)));
    book.build().unwrap();

    let inner = spy.lock().unwrap();
    assert_eq!(inner.run_count, 1);
}
<|endoftext|>


<commit_before>// Copyright © 2018, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

extern crate csv;
extern crate failure;
extern crate geo;
extern crate mimir;
extern crate mimirsbrunn;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate slog;
#[macro_use]
extern crate slog_scope;
#[macro_use]
extern crate structopt;

use failure::ResultExt;
use mimir::rubber::Rubber;
use mimirsbrunn::admin_geofinder::AdminGeoFinder;
use std::cell::Cell;
use std::fs;
use std::path::PathBuf;

#[derive(Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub struct OpenAddresse {
    pub id: String,
    pub street: String,
    pub postcode: String,
    pub district: String,
    pub region: String,
    pub city: String,
    pub number: String,
    pub unit: String,
    pub lat: f64,
    pub lon: f64,
}

impl OpenAddresse {
    pub fn into_addr(self, admins_geofinder: &AdminGeoFinder) -> mimir::Addr {
        let street_name = format!("{} ({})", self.street, self.city);
        let addr_name = format!("{} {}", self.number, self.street);
        let addr_label = format!("{} ({})", addr_name, self.city);
        let street_id = format!("street:{}", self.id); // TODO check if thats ok
        let admins = admins_geofinder.get(&geo::Coordinate {
            x: self.lon,
            y: self.lat,
        });

        let weight = admins.iter().find(|a| a.is_city()).map_or(0., |a| a.weight);

        let street = mimir::Street {
            id: street_id,
            street_name: self.street.clone(),
            name: self.street,
            label: street_name.to_string(),
            administrative_regions: admins,
            weight: weight,
            zip_codes: vec![self.postcode.clone()],
            coord: mimir::Coord::new(self.lon, self.lat),
        };
        mimir::Addr {
            id: format!("addr:{};{}", self.lon, self.lat),
            name: addr_name,
            house_number: self.number,
            street: street,
            label: addr_label,
            coord: mimir::Coord::new(self.lon, self.lat),
            weight: weight,
            zip_codes: vec![self.postcode.clone()],
        }
    }
}

fn index_oa<I>(cnx_string: &str, dataset: &str, files: I) -> Result<(), mimirsbrunn::Error>
where
    I: Iterator<Item = std::path::PathBuf>,
{
    let mut rubber = Rubber::new(cnx_string);

    let admins = rubber
        .get_admins_from_dataset(dataset)
        .unwrap_or_else(|err| {
            info!(
                "Administratives regions not found in es db for dataset {}. (error: {})",
                dataset, err
            );
            vec![]
        });
    let admins_geofinder = admins.into_iter().collect();

    let addr_index = rubber
        .make_index(dataset)
        .with_context(|_| format!("error occureed when making index for {}", dataset))?;
    info!("Add data in elasticsearch db.");
    for f in files {
        info!("importing {:?}...", &f);
        let mut rdr = csv::ReaderBuilder::new().has_headers(true).from_path(&f)?;
        let iter = rdr
            .deserialize()
            .filter_map(|r| {
                r.map_err(|e| info!("impossible to read line, error: {}", e))
                    .ok()
                    .map(|v: OpenAddresse| v.into_addr(&admins_geofinder))
            })
            .filter(|a| {
                !a.street.street_name.is_empty() || {
                    info!(
                        "Address {}:{:?}:{:?} has no street name and has been ignored.",
                        a.id, a.coord, a.street
                    );
                    false
                }
            });
        let nb = rubber
            .bulk_index(&addr_index, iter)
            .with_context(|_| format!("failed to bulk insert file {:?}", &f))?;
        info!("importing {:?}: {} addresses", &f, nb);
    }
    rubber.publish_index(dataset, addr_index)
}

#[derive(StructOpt, Debug)]
struct Args {
    /// openaddresses files. Can be either a directory or a file.
    #[structopt(short = "i", long = "input", parse(from_os_str))]
    input: PathBuf,
    /// Elasticsearch parameters.
    #[structopt(
        short = "c", long = "connection-string", default_value = "http://localhost:9200/munin"
    )]
    connection_string: String,
    /// Name of the dataset.
    #[structopt(short = "d", long = "dataset", default_value = "fr")]
    dataset: String,
    /// Deprecated option.
    #[structopt(short = "C", long = "city-level")]
    city_level: Option<String>,
}

fn run(args: Args) -> Result<(), failure::Error> {
    info!("importing open addresses into Mimir");

    if args.city_level.is_some() {
        warn!("city-level option is deprecated, it now has no effect.");
    }

    if args.input.is_dir() {
        let paths: std::fs::ReadDir = fs::read_dir(&args.input)?;
        index_oa(
            &args.connection_string,
            &args.dataset,
            paths.map(|p| p.unwrap().path()),
        )
    } else {
        index_oa(
            &args.connection_string,
            &args.dataset,
            std::iter::once(args.input),
        )
    }
}

fn main() {
    mimirsbrunn::utils::launch_run(run);
}
<commit_msg>remove useless log<commit_after>// Copyright © 2018, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

extern crate csv;
extern crate failure;
extern crate geo;
extern crate mimir;
extern crate mimirsbrunn;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate slog;
#[macro_use]
extern crate slog_scope;
#[macro_use]
extern crate structopt;

use failure::ResultExt;
use mimir::rubber::Rubber;
use mimirsbrunn::admin_geofinder::AdminGeoFinder;
use std::cell::Cell;
use std::fs;
use std::path::PathBuf;

#[derive(Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub struct OpenAddresse {
    pub id: String,
    pub street: String,
    pub postcode: String,
    pub district: String,
    pub region: String,
    pub city: String,
    pub number: String,
    pub unit: String,
    pub lat: f64,
    pub lon: f64,
}

impl OpenAddresse {
    pub fn into_addr(self, admins_geofinder: &AdminGeoFinder) -> mimir::Addr {
        let street_name = format!("{} ({})", self.street, self.city);
        let addr_name = format!("{} {}", self.number, self.street);
        let addr_label = format!("{} ({})", addr_name, self.city);
        let street_id = format!("street:{}", self.id); // TODO check if thats ok
        let admins = admins_geofinder.get(&geo::Coordinate {
            x: self.lon,
            y: self.lat,
        });

        let weight = admins.iter().find(|a| a.is_city()).map_or(0., |a| a.weight);

        let street = mimir::Street {
            id: street_id,
            street_name: self.street.clone(),
            name: self.street,
            label: street_name.to_string(),
            administrative_regions: admins,
            weight: weight,
            zip_codes: vec![self.postcode.clone()],
            coord: mimir::Coord::new(self.lon, self.lat),
        };
        mimir::Addr {
            id: format!("addr:{};{}", self.lon, self.lat),
            name: addr_name,
            house_number: self.number,
            street: street,
            label: addr_label,
            coord: mimir::Coord::new(self.lon, self.lat),
            weight: weight,
            zip_codes: vec![self.postcode.clone()],
        }
    }
}

fn index_oa<I>(cnx_string: &str, dataset: &str, files: I) -> Result<(), mimirsbrunn::Error>
where
    I: Iterator<Item = std::path::PathBuf>,
{
    let mut rubber = Rubber::new(cnx_string);

    let admins = rubber
        .get_admins_from_dataset(dataset)
        .unwrap_or_else(|err| {
            info!(
                "Administratives regions not found in es db for dataset {}. (error: {})",
                dataset, err
            );
            vec![]
        });
    let admins_geofinder = admins.into_iter().collect();

    let addr_index = rubber
        .make_index(dataset)
        .with_context(|_| format!("error occureed when making index for {}", dataset))?;
    info!("Add data in elasticsearch db.");
    for f in files {
        info!("importing {:?}...", &f);
        let mut rdr = csv::ReaderBuilder::new().has_headers(true).from_path(&f)?;
        let iter = rdr
            .deserialize()
            .filter_map(|r| {
                r.map_err(|e| info!("impossible to read line, error: {}", e))
                    .ok()
                    .map(|v: OpenAddresse| v.into_addr(&admins_geofinder))
            })
            .filter(|a| {
                !a.street.street_name.is_empty() || {
                    info!("Address {} has no street name and has been ignored.", a.id);
                    false
                }
            });
        let nb = rubber
            .bulk_index(&addr_index, iter)
            .with_context(|_| format!("failed to bulk insert file {:?}", &f))?;
        info!("importing {:?}: {} addresses", &f, nb);
    }
    rubber.publish_index(dataset, addr_index)
}

#[derive(StructOpt, Debug)]
struct Args {
    /// openaddresses files. Can be either a directory or a file.
    #[structopt(short = "i", long = "input", parse(from_os_str))]
    input: PathBuf,
    /// Elasticsearch parameters.
    #[structopt(
        short = "c", long = "connection-string", default_value = "http://localhost:9200/munin"
    )]
    connection_string: String,
    /// Name of the dataset.
    #[structopt(short = "d", long = "dataset", default_value = "fr")]
    dataset: String,
    /// Deprecated option.
    #[structopt(short = "C", long = "city-level")]
    city_level: Option<String>,
}

fn run(args: Args) -> Result<(), failure::Error> {
    info!("importing open addresses into Mimir");

    if args.city_level.is_some() {
        warn!("city-level option is deprecated, it now has no effect.");
    }

    if args.input.is_dir() {
        let paths: std::fs::ReadDir = fs::read_dir(&args.input)?;
        index_oa(
            &args.connection_string,
            &args.dataset,
            paths.map(|p| p.unwrap().path()),
        )
    } else {
        index_oa(
            &args.connection_string,
            &args.dataset,
            std::iter::once(args.input),
        )
    }
}

fn main() {
    mimirsbrunn::utils::launch_run(run);
}
<|endoftext|>


<commit_before>//! Implementation of the `#[assert_instr]` macro
//!
//! This macro is used when testing the `stdsimd` crate and is used to generate
//! test cases to assert that functions do indeed contain the instructions that
//! we're expecting them to contain.
//!
//! The procedural macro here is relatively simple, it simply appends a
//! `#[test]` function to the original token stream which asserts that the
//! function itself contains the relevant instruction.

#![feature(proc_macro)]

extern crate proc_macro2;
extern crate proc_macro;
#[macro_use]
extern crate quote;
#[macro_use]
extern crate syn;

use proc_macro2::TokenStream;

#[proc_macro_attribute]
pub fn assert_instr(
    attr: proc_macro::TokenStream, item: proc_macro::TokenStream
) -> proc_macro::TokenStream {
    let invoc = syn::parse::<Invoc>(attr)
        .expect("expected #[assert_instr(instr, a = b, ...)]");
    let item =
        syn::parse::<syn::Item>(item).expect("must be attached to an item");
    let func = match item {
        syn::Item::Fn(ref f) => f,
        _ => panic!("must be attached to a function"),
    };

    let instr = &invoc.instr;
    let maybe_ignore = if cfg!(optimized) {
        TokenStream::empty()
    } else {
        (quote! { #[ignore] }).into()
    };
    let name = &func.ident;
    let assert_name = syn::Ident::from(
        &format!("assert_{}_{}", name.as_ref(), instr.as_ref())[..],
    );
    let shim_name =
        syn::Ident::from(format!("{}_shim", name.as_ref()));
    let (to_test, test_name) = if invoc.args.len() == 0 {
        (TokenStream::empty(), &func.ident)
    } else {
        let mut inputs = Vec::new();
        let mut input_vals = Vec::new();
        let ret = &func.decl.output;
        for arg in func.decl.inputs.iter() {
            let capture = match **arg.item() {
                syn::FnArg::Captured(ref c) => c,
                _ => panic!("arguments must not have patterns"),
            };
            let ident = match capture.pat {
                syn::Pat::Ident(ref i) => &i.ident,
                _ => panic!("must have bare arguments"),
            };
            match invoc.args.iter().find(|a| a.0 == ident.as_ref()) {
                Some(&(_, ref tts)) => {
                    input_vals.push(quote! { #tts });
                }
                None => {
                    inputs.push(capture);
                    input_vals.push(quote! { #ident });
                }
            };
        }

        let attrs = func.attrs
            .iter()
            .filter(|attr| {
                attr.path
                    .segments
                    .get(0)
                    .item()
                    .ident
                    .as_ref()
                    .starts_with("target")
            })
            .collect::<Vec<_>>();
        let attrs = Append(&attrs);
        (
            quote! {
                #attrs
                unsafe fn #shim_name(#(#inputs),*) #ret {
                    #name(#(#input_vals),*)
                }
            }.into(),
            &shim_name,
        )
    };

    let tts: TokenStream = quote_spanned! {
        proc_macro2::Span::call_site(),
        #[test]
        #[allow(non_snake_case)]
        #maybe_ignore
        fn #assert_name() {
            #to_test

            ::stdsimd_test::assert(#test_name as usize,
                                   stringify!(#test_name),
                                   stringify!(#instr));
        }
    }.into();
    // why? necessary now to get tests to work?
    let tts: TokenStream = tts.to_string().parse().unwrap();

    let tts: TokenStream = quote! {
        #item
        #tts
    }.into();
    tts.into()
}

struct Invoc {
    instr: syn::Ident,
    args: Vec<(syn::Ident, syn::Expr)>,
}

impl syn::synom::Synom for Invoc {
    named!(parse -> Self, map!(parens!(do_parse!(
        instr: syn!(syn::Ident) >>
        args: many0!(do_parse!(
            syn!(syn::token::Comma) >>
            name: syn!(syn::Ident) >>
            syn!(syn::token::Eq) >>
            expr: syn!(syn::Expr) >>
            (name, expr)
        )) >>
        (Invoc {
            instr,
            args,
        })
    )), |p| p.0));
}

struct Append<T>(T);

impl<T> quote::ToTokens for Append<T>
where
    T: Clone + IntoIterator,
    T::Item: quote::ToTokens,
{
    fn to_tokens(&self, tokens: &mut quote::Tokens) {
        for item in self.0.clone() {
            item.to_tokens(tokens);
        }
    }
}
<commit_msg>Fix compile with `syn` master<commit_after>//! Implementation of the `#[assert_instr]` macro
//!
//! This macro is used when testing the `stdsimd` crate and is used to generate
//! test cases to assert that functions do indeed contain the instructions that
//! we're expecting them to contain.
//!
//! The procedural macro here is relatively simple, it simply appends a
//! `#[test]` function to the original token stream which asserts that the
//! function itself contains the relevant instruction.

#![feature(proc_macro)]

extern crate proc_macro2;
extern crate proc_macro;
#[macro_use]
extern crate quote;
#[macro_use]
extern crate syn;

use proc_macro2::TokenStream;

#[proc_macro_attribute]
pub fn assert_instr(
    attr: proc_macro::TokenStream, item: proc_macro::TokenStream
) -> proc_macro::TokenStream {
    let invoc = syn::parse::<Invoc>(attr)
        .expect("expected #[assert_instr(instr, a = b, ...)]");
    let item =
        syn::parse::<syn::Item>(item).expect("must be attached to an item");
    let func = match item {
        syn::Item::Fn(ref f) => f,
        _ => panic!("must be attached to a function"),
    };

    let instr = &invoc.instr;
    let maybe_ignore = if cfg!(optimized) {
        TokenStream::empty()
    } else {
        (quote! { #[ignore] }).into()
    };
    let name = &func.ident;
    let assert_name = syn::Ident::from(
        &format!("assert_{}_{}", name.as_ref(), instr.as_ref())[..],
    );
    let shim_name =
        syn::Ident::from(format!("{}_shim", name.as_ref()));
    let (to_test, test_name) = if invoc.args.len() == 0 {
        (TokenStream::empty(), &func.ident)
    } else {
        let mut inputs = Vec::new();
        let mut input_vals = Vec::new();
        let ret = &func.decl.output;
        for arg in func.decl.inputs.iter() {
            let capture = match **arg.item() {
                syn::FnArg::Captured(ref c) => c,
                _ => panic!("arguments must not have patterns"),
            };
            let ident = match capture.pat {
                syn::Pat::Ident(ref i) => &i.ident,
                _ => panic!("must have bare arguments"),
            };
            match invoc.args.iter().find(|a| a.0 == ident.as_ref()) {
                Some(&(_, ref tts)) => {
                    input_vals.push(quote! { #tts });
                }
                None => {
                    inputs.push(capture);
                    input_vals.push(quote! { #ident });
                }
            };
        }

        let attrs = func.attrs
            .iter()
            .filter(|attr| {
                attr.path
                    .segments
                    .first()
                    .unwrap()
                    .item()
                    .ident
                    .as_ref()
                    .starts_with("target")
            })
            .collect::<Vec<_>>();
        let attrs = Append(&attrs);
        (
            quote! {
                #attrs
                unsafe fn #shim_name(#(#inputs),*) #ret {
                    #name(#(#input_vals),*)
                }
            }.into(),
            &shim_name,
        )
    };

    let tts: TokenStream = quote_spanned! {
        proc_macro2::Span::call_site(),
        #[test]
        #[allow(non_snake_case)]
        #maybe_ignore
        fn #assert_name() {
            #to_test

            ::stdsimd_test::assert(#test_name as usize,
                                   stringify!(#test_name),
                                   stringify!(#instr));
        }
    }.into();
    // why? necessary now to get tests to work?
    let tts: TokenStream = tts.to_string().parse().unwrap();

    let tts: TokenStream = quote! {
        #item
        #tts
    }.into();
    tts.into()
}

struct Invoc {
    instr: syn::Ident,
    args: Vec<(syn::Ident, syn::Expr)>,
}

impl syn::synom::Synom for Invoc {
    named!(parse -> Self, map!(parens!(do_parse!(
        instr: syn!(syn::Ident) >>
        args: many0!(do_parse!(
            syn!(syn::token::Comma) >>
            name: syn!(syn::Ident) >>
            syn!(syn::token::Eq) >>
            expr: syn!(syn::Expr) >>
            (name, expr)
        )) >>
        (Invoc {
            instr,
            args,
        })
    )), |p| p.0));
}

struct Append<T>(T);

impl<T> quote::ToTokens for Append<T>
where
    T: Clone + IntoIterator,
    T::Item: quote::ToTokens,
{
    fn to_tokens(&self, tokens: &mut quote::Tokens) {
        for item in self.0.clone() {
            item.to_tokens(tokens);
        }
    }
}
<|endoftext|>


<commit_before>#[rustversion::not(nightly)]
#[ignore]
#[test]
fn test_backtrace() {}

#[rustversion::nightly]
#[test]
fn test_backtrace() {
    use anyhow::anyhow;

    let error = anyhow!("oh no!");
    let _ = error.backtrace();
}
<commit_msg>Disable backtrace test on miri<commit_after>#![cfg(not(miri))]

#[rustversion::not(nightly)]
#[ignore]
#[test]
fn test_backtrace() {}

#[rustversion::nightly]
#[test]
fn test_backtrace() {
    use anyhow::anyhow;

    let error = anyhow!("oh no!");
    let _ = error.backtrace();
}
<|endoftext|>


<commit_before>use std::thread;
use std::sync::{Arc, Mutex};
use std::sync::mpsc;
use std::sync::mpsc::{Sender,Receiver};
use std::collections::HashMap;
use consts::WatchedEventType;
use proto::WatchedEvent;
use zookeeper::{ZkResult, ZooKeeper};
use zookeeper_ext::ZooKeeperExt;

pub type Data = HashMap<String, Arc<Vec<u8>>>;

pub struct ChildData;

pub enum PathChildrenCacheEvent {
    Initialized,
    ConnectionSuspended,
    ConnectionLost,
    ConnectionReconnected,
    ChildRemoved(ChildData),
    ChildAdded(ChildData),
    ChildUpdated(ChildData),
}

pub enum RefreshMode {
    Standard,
    ForceGetDataAndStat,
}

pub enum Operation {
    Refresh(RefreshMode),
    Event,
    GetData(String /* path */)
}

pub struct PathChildrenCache {
    zk: Arc<ZooKeeper>,
    data: Arc<Mutex<Data>>,
    worker_thread: Option<thread::JoinHandle<()>>,
    channel: Option<Sender<()>>,
}

impl PathChildrenCache {

    fn get_children(zk: Arc<ZooKeeper>, path: &str, data: Arc<Mutex<Data>>) -> ZkResult<()> {

        let zk1 = zk.clone();
        let data1 = data.clone();

        let watcher = move |event: &WatchedEvent| {
            match event.event_type {
                WatchedEventType::NodeChildrenChanged => {
                    let path = event.path.as_ref().expect("Path absent");
                    // Subscribe to new changes recursively
                    let _ = Self::get_children(zk1, path, data1); // ignore errors
                },
                _ => error!("Unexpected: {:?}", event)
            };
            // Send change event
        };

        let children = try!(zk.get_children_w(&path, watcher));

        let mut data_locked = data.lock().unwrap();

        for child in children.iter() {
            let child_path = path.to_owned() + "/" + child;

            if !data_locked.contains_key(&child_path) {

                let child_data = Self::get_data(zk.clone(), &child_path, data.clone());

                data_locked.insert(child_path, Arc::new(child_data));
            }
        }

        debug!("New data: {:?}", *data_locked);

        Ok(())
    }

    fn get_data(zk: Arc<ZooKeeper>, path: &str, data: Arc<Mutex<Data>>) -> Vec<u8> {
        let zk1 = zk.clone();
        let path1 = path.to_owned();

        let data_watcher = move |event: &WatchedEvent| {
            let mut data_locked = data.lock().unwrap();
            match event.event_type {
                WatchedEventType::NodeDeleted => {
                    data_locked.remove(&path1);
                },
                WatchedEventType::NodeDataChanged => {
                    // Subscribe to new changes recursively
                    let child_data = Self::get_data(zk1, &path1, data.clone());
                    data_locked.insert(path1, Arc::new(child_data));
                },
                _ => error!("Unexpected: {:?}", event)
            };

            debug!("New data: {:?}", *data_locked);

            //TODO Send change event
        };

        zk.get_data_w(path, data_watcher).unwrap().0
    }

    pub fn new(zk: Arc<ZooKeeper>, path: &str) -> ZkResult<PathChildrenCache> {

        let data = Arc::new(Mutex::new(HashMap::new()));

        try!(zk.ensure_path(path));

        try!(Self::get_children(zk.clone(), path, data.clone()));

        Ok(PathChildrenCache{
            zk: zk,
            data: data,
            worker_thread: None,
            channel: None,
        })
    }

    pub fn get_current_data(&self) -> Data {
        self.data.lock().unwrap().clone()
    }

    pub fn clear(&self) {
        self.data.lock().unwrap().clear()
    }

    pub fn start(&mut self) {
        let (tx, rx) = mpsc::channel();
        self.channel = Some(tx);

        self.worker_thread = Some(thread::spawn(move || {
            rx.recv();
        }));
    }
}
<commit_msg>receive operations in worker thread<commit_after>use std::thread;
use std::sync::{Arc, Mutex};
use std::sync::mpsc;
use std::sync::mpsc::{Sender,Receiver};
use std::collections::HashMap;
use consts::{WatchedEventType, ZkError};
use proto::WatchedEvent;
use zookeeper::{ZkResult, ZooKeeper};
use zookeeper_ext::ZooKeeperExt;

pub type Data = HashMap<String, Arc<Vec<u8>>>;

#[derive(Debug)]
pub struct ChildData;

#[derive(Debug)]
pub enum PathChildrenCacheEvent {
    Initialized,
    ConnectionSuspended,
    ConnectionLost,
    ConnectionReconnected,
    ChildRemoved(ChildData),
    ChildAdded(ChildData),
    ChildUpdated(ChildData),
}

#[derive(Debug)]
pub enum RefreshMode {
    Standard,
    ForceGetDataAndStat,
}

#[derive(Debug)]
pub enum Operation {
    Shutdown,
    Refresh(RefreshMode),
    Event(PathChildrenCacheEvent),
    GetData(String /* path */)
}

pub struct PathChildrenCache {
    zk: Arc<ZooKeeper>,
    data: Arc<Mutex<Data>>,
    worker_thread: Option<thread::JoinHandle<()>>,
    channel: Option<Sender<Operation>>,
}

impl PathChildrenCache {

    fn get_children(zk: Arc<ZooKeeper>, path: &str, data: Arc<Mutex<Data>>) -> ZkResult<()> {

        let zk1 = zk.clone();
        let data1 = data.clone();

        let watcher = move |event: &WatchedEvent| {
            match event.event_type {
                WatchedEventType::NodeChildrenChanged => {
                    let path = event.path.as_ref().expect("Path absent");
                    // Subscribe to new changes recursively
                    let _ = Self::get_children(zk1, path, data1); // ignore errors
                },
                _ => error!("Unexpected: {:?}", event)
            };
            // Send change event
        };

        let children = try!(zk.get_children_w(&path, watcher));

        let mut data_locked = data.lock().unwrap();

        for child in children.iter() {
            let child_path = path.to_owned() + "/" + child;

            if !data_locked.contains_key(&child_path) {

                let child_data = Self::get_data(zk.clone(), &child_path, data.clone());

                data_locked.insert(child_path, Arc::new(child_data));
            }
        }

        debug!("New data: {:?}", *data_locked);

        Ok(())
    }

    fn get_data(zk: Arc<ZooKeeper>, path: &str, data: Arc<Mutex<Data>>) -> Vec<u8> {
        let zk1 = zk.clone();
        let path1 = path.to_owned();

        let data_watcher = move |event: &WatchedEvent| {
            let mut data_locked = data.lock().unwrap();
            match event.event_type {
                WatchedEventType::NodeDeleted => {
                    data_locked.remove(&path1);
                },
                WatchedEventType::NodeDataChanged => {
                    // Subscribe to new changes recursively
                    let child_data = Self::get_data(zk1, &path1, data.clone());
                    data_locked.insert(path1, Arc::new(child_data));
                },
                _ => error!("Unexpected: {:?}", event)
            };

            debug!("New data: {:?}", *data_locked);

            //TODO Send change event
        };

        zk.get_data_w(path, data_watcher).unwrap().0
    }

    pub fn new(zk: Arc<ZooKeeper>, path: &str) -> ZkResult<PathChildrenCache> {

        let data = Arc::new(Mutex::new(HashMap::new()));

        try!(zk.ensure_path(path));

        try!(Self::get_children(zk.clone(), path, data.clone()));

        Ok(PathChildrenCache{
            zk: zk,
            data: data,
            worker_thread: None,
            channel: None,
        })
    }

    pub fn get_current_data(&self) -> Data {
        self.data.lock().unwrap().clone()
    }

    pub fn clear(&self) {
        self.data.lock().unwrap().clear()
    }

    pub fn start(&mut self) {
        let (tx, rx) = mpsc::channel();
        self.channel = Some(tx);

        self.worker_thread = Some(thread::spawn(move || {
            for op in rx.iter() {
                print!("handling op {:?}", op);
                match op {
                    Operation::Shutdown => {
                        break;
                    },
                    Operation::Refresh(mode) => {
                    },
                    Operation::GetData(path) => {
                    },
                    Operation::Event(event) => {
                    }
                }
            }
        }));
    }

    fn offer_operation(&self, op: Operation) -> ZkResult<()> {
        match self.channel {
            Some(ref chan) => {
                chan.send(op);
                Ok(())
            },
            None => Err(ZkError::APIError)
        }
    }

}
<|endoftext|>


<commit_before>use middleware::{Middleware, Continue, MiddlewareResult};
use super::path_utils;
use hyper::uri::RequestUri::AbsolutePath;
use request::Request;
use response::Response;
use router::HttpRouter;
use hyper::method::Method;
use hyper::status::StatusCode;
use regex::Regex;
use std::collections::HashMap;

/// A Route is the basic data structure that stores both the path
/// and the handler that gets executed for the route.
/// The path can contain variable pattern such as `user/:userid/invoices`
pub struct Route {
    pub path: String,
    pub method: Method,
    pub handler: Box<Middleware + Send + Sync + 'static>,
    pub variables: HashMap<String, usize>,
    matcher: Regex
}

/// A RouteResult is what the router returns when `match_route` is called.
/// It contains the matched `route` and also a `params` property holding
/// a HashMap with the keys being the variable names and the value being the
/// evaluated string
pub struct RouteResult<'a> {
    pub route: &'a Route,
    params: Vec<String>
}

impl<'a> RouteResult<'a> {
    pub fn param(&self, key: &str) -> &str {
        let idx = self.route.variables.get(key).unwrap();
        &*self.params[*idx]
    }
}

/// The Router's job is it to hold routes and to resolve them later against
/// concrete URLs. The router is also a regular middleware and needs to be
/// added to the middleware stack with `server.utilize(router)`.
pub struct Router {
    routes: Vec<Route>,
}

impl<'a> Router {
    pub fn new () -> Router {
        Router {
            routes: Vec::new()
        }
    }

    pub fn match_route(&'a self, method: &Method, path: &str) -> Option<RouteResult<'a>> {
        self.routes
            .iter()
            .find(|item| item.method == *method && item.matcher.is_match(path))
            .map(|route| {
                let vec = match route.matcher.captures(path) {
                    Some(captures) => {
                        range(0, route.variables.len())
                            .filter_map(|pos| {
                                captures.at(pos + 1).map(|c| c.to_string())
                            })
                            .collect()
                    },
                    None => vec![],
                };
                RouteResult {
                    route: route,
                    params: vec
                }
            })
    }
}

impl HttpRouter for Router {
    fn add_route<H: Middleware>(&mut self, method: Method, path: &str, handler: H) {
        let matcher = path_utils::create_regex(path);
        let variable_infos = path_utils::get_variable_info(path);
        let route = Route {
            path: path.to_string(),
            method: method,
            matcher: matcher,
            handler: Box::new(handler),
            variables: variable_infos
        };
        self.routes.push(route);
    }
}

impl Middleware for Router {
    fn invoke<'a, 'b>(&'a self, req: &mut Request<'b, 'a>, mut res: Response<'a>)
                        -> MiddlewareResult<'a> {
        debug!("Router::invoke for '{:?}'", req.origin.uri);
        let route_result = match req.origin.uri {
            AbsolutePath(ref url) => self.match_route(&req.origin.method, &**url),
            _ => None
        };
        debug!("route_result.route.path: {:?}", route_result.as_ref().map(|r| &*r.route.path));

        match route_result {
            Some(route_result) => {
                res.status_code(StatusCode::Ok);
                let handler = &route_result.route.handler;
                req.route_result = Some(route_result);
                handler.invoke(req, res)
            },
            None => Ok(Continue(res))
        }
    }
}

#[test]
fn creates_map_with_var_variable_infos () {
    let map = path_utils::get_variable_info("foo/:uid/bar/:groupid");

    assert_eq!(map.len(), 2);
    assert_eq!(map["uid".to_string()], 0);
    assert_eq!(map["groupid".to_string()], 1);
}

#[test]
fn creates_regex_with_captures () {
    let regex = path_utils::create_regex("foo/:uid/bar/:groupid");
    let caps = regex.captures("foo/4711/bar/5490").unwrap();

    assert_eq!(caps.at(1).unwrap(), "4711");
    assert_eq!(caps.at(2).unwrap(), "5490");

    let regex = path_utils::create_regex("foo/*/:uid/bar/:groupid");
    let caps = regex.captures("foo/test/4711/bar/5490").unwrap();

    assert_eq!(caps.at(1).unwrap(), "4711");
    assert_eq!(caps.at(2).unwrap(), "5490");

    let regex = path_utils::create_regex("foo/**/:uid/bar/:groupid");
    let caps = regex.captures("foo/test/another/4711/bar/5490").unwrap();

    assert_eq!(caps.at(1).unwrap(), "4711");
    assert_eq!(caps.at(2).unwrap(), "5490");
}

#[test]
fn creates_valid_regex_for_routes () {
    let regex1 = path_utils::create_regex("foo/:uid/bar/:groupid");
    let regex2 = path_utils::create_regex("foo/*/bar");
    let regex3 = path_utils::create_regex("foo/**/bar");

    assert_eq!(regex1.is_match("foo/4711/bar/5490"), true);
    assert_eq!(regex1.is_match("foo/4711/bar/5490?foo=true&bar=false"), true);
    assert_eq!(regex1.is_match("foo/4711/bar"), false);
    assert_eq!(regex1.is_match("foo/4711/bar?foo=true&bar=false"), false);
    assert_eq!(regex1.is_match("foo/4711/bar/test%20spacing"), true);
    assert_eq!(regex1.is_match("foo/4711/bar/5281?foo=test%20spacing&bar=false"), true);

    assert_eq!(regex2.is_match("foo/4711/bar"), true);
    assert_eq!(regex2.is_match("foo/4711/barr"), false);
    assert_eq!(regex2.is_match("foo/4711/bar?foo=true&bar=false"), true);
    assert_eq!(regex2.is_match("foo/4711/4712/bar"), false);
    assert_eq!(regex2.is_match("foo/4711/4712/bar?foo=true&bar=false"), false);

    assert_eq!(regex3.is_match("foo/4711/bar"), true);
    assert_eq!(regex3.is_match("foo/4711/bar?foo=true&bar=false"), true);
    assert_eq!(regex3.is_match("foo/4711/4712/bar"), true);
    assert_eq!(regex3.is_match("foo/4711/4712/bar?foo=true&bar=false"), true);

    //ensure that this works with commas too
    assert_eq!(regex1.is_match("foo/4711/bar/5490,1234"), true);
    assert_eq!(regex1.is_match("foo/4711/bar/5490,1234?foo=true&bar=false"), true);
    assert_eq!(regex1.is_match("foo/4711/bar"), false);
    assert_eq!(regex1.is_match("foo/4711/bar?foo=1,2,3&bar=false"), false);
}

#[test]
fn can_match_var_routes () {
    use hyper::method::Method;

    let route_store = &mut Router::new();
    let handler = middleware! { "hello from foo" };

    route_store.add_route(Method::Get, "/foo/:userid", handler);
    route_store.add_route(Method::Get, "/bar", handler);

    let route_result = route_store.match_route(&Method::Get, "/foo/4711").unwrap();
    let route = route_result.route;

    assert_eq!(route_result.param("userid"), "4711");

    //assert the route has identified the variable
    assert_eq!(route.variables.len(), 1);
    assert_eq!(route.variables["userid".to_string()], 0);

    let route_result = route_store.match_route(&Method::Get, "/bar/4711");
    assert!(route_result.is_none());

    let route_result = route_store.match_route(&Method::Get, "/foo");
    assert!(route_result.is_none());

    //ensure that this will work with commas too
    let route_result = route_store.match_route(&Method::Get, "/foo/123,456");
    assert!(route_result.is_some());

    let route_result = route_result.unwrap();
    assert_eq!(route_result.param("userid"), "123,456");

    //ensure that this will work with spacing too
    let route_result = route_store.match_route(&Method::Get, "/foo/John%20Doe");
    assert!(route_result.is_some());

    let route_result = route_result.unwrap();
    assert_eq!(route_result.param("userid"), "John%20Doe");
}

<commit_msg>fix(router): reintroduce PR #91<commit_after>use middleware::{Middleware, Continue, MiddlewareResult};
use super::path_utils;
use hyper::uri::RequestUri::AbsolutePath;
use request::Request;
use response::Response;
use router::HttpRouter;
use hyper::method::Method;
use hyper::status::StatusCode;
use regex::Regex;
use std::collections::HashMap;

/// A Route is the basic data structure that stores both the path
/// and the handler that gets executed for the route.
/// The path can contain variable pattern such as `user/:userid/invoices`
pub struct Route {
    pub path: String,
    pub method: Method,
    pub handler: Box<Middleware + Send + Sync + 'static>,
    pub variables: HashMap<String, usize>,
    matcher: Regex
}

/// A RouteResult is what the router returns when `match_route` is called.
/// It contains the matched `route` and also a `params` property holding
/// a HashMap with the keys being the variable names and the value being the
/// evaluated string
pub struct RouteResult<'a> {
    pub route: &'a Route,
    params: Vec<String>
}

impl<'a> RouteResult<'a> {
    pub fn param(&self, key: &str) -> &str {
        let idx = self.route.variables.get(key).unwrap();
        &*self.params[*idx]
    }
}

/// The Router's job is it to hold routes and to resolve them later against
/// concrete URLs. The router is also a regular middleware and needs to be
/// added to the middleware stack with `server.utilize(router)`.
pub struct Router {
    routes: Vec<Route>,
}

impl<'a> Router {
    pub fn new () -> Router {
        Router {
            routes: Vec::new()
        }
    }

    pub fn match_route(&'a self, method: &Method, path: &str) -> Option<RouteResult<'a>> {
        self.routes
            .iter()
            .find(|item| item.method == *method && item.matcher.is_match(path))
            .map(|route| {
                let vec = match route.matcher.captures(path) {
                    Some(captures) => {
                        range(0, route.variables.len())
                            .filter_map(|pos| {
                                captures.at(pos + 1).map(|c| c.to_string())
                            })
                            .collect()
                    },
                    None => vec![],
                };
                RouteResult {
                    route: route,
                    params: vec
                }
            })
    }
}

impl HttpRouter for Router {
    fn add_route<H: Middleware>(&mut self, method: Method, path: &str, handler: H) {
        static FORMAT_VAR: &'static str = ":format";

        let with_format = if path.contains(FORMAT_VAR) {
            path.to_string()
        } else {
            format!("{}(\\.{})?", path, FORMAT_VAR)
        };

        let matcher = path_utils::create_regex(&with_format);
        let variable_infos = path_utils::get_variable_info(&with_format);

        let route = Route {
            path: with_format,
            method: method,
            matcher: matcher,
            handler: Box::new(handler),
            variables: variable_infos
        };
        self.routes.push(route);
    }
}

impl Middleware for Router {
    fn invoke<'a, 'b>(&'a self, req: &mut Request<'b, 'a>, mut res: Response<'a>)
                        -> MiddlewareResult<'a> {
        debug!("Router::invoke for '{:?}'", req.origin.uri);
        let route_result = match req.origin.uri {
            AbsolutePath(ref url) => self.match_route(&req.origin.method, &**url),
            _ => None
        };
        debug!("route_result.route.path: {:?}", route_result.as_ref().map(|r| &*r.route.path));

        match route_result {
            Some(route_result) => {
                res.status_code(StatusCode::Ok);
                let handler = &route_result.route.handler;
                req.route_result = Some(route_result);
                handler.invoke(req, res)
            },
            None => Ok(Continue(res))
        }
    }
}

#[test]
fn creates_map_with_var_variable_infos () {
    let map = path_utils::get_variable_info("foo/:uid/bar/:groupid");

    assert_eq!(map.len(), 2);
    assert_eq!(map["uid".to_string()], 0);
    assert_eq!(map["groupid".to_string()], 1);
}

#[test]
fn creates_regex_with_captures () {
    let regex = path_utils::create_regex("foo/:uid/bar/:groupid");
    let caps = regex.captures("foo/4711/bar/5490").unwrap();

    assert_eq!(caps.at(1).unwrap(), "4711");
    assert_eq!(caps.at(2).unwrap(), "5490");

    let regex = path_utils::create_regex("foo/*/:uid/bar/:groupid");
    let caps = regex.captures("foo/test/4711/bar/5490").unwrap();

    assert_eq!(caps.at(1).unwrap(), "4711");
    assert_eq!(caps.at(2).unwrap(), "5490");

    let regex = path_utils::create_regex("foo/**/:uid/bar/:groupid");
    let caps = regex.captures("foo/test/another/4711/bar/5490").unwrap();

    assert_eq!(caps.at(1).unwrap(), "4711");
    assert_eq!(caps.at(2).unwrap(), "5490");
}

#[test]
fn creates_valid_regex_for_routes () {
    let regex1 = path_utils::create_regex("foo/:uid/bar/:groupid");
    let regex2 = path_utils::create_regex("foo/*/bar");
    let regex3 = path_utils::create_regex("foo/**/bar");

    assert_eq!(regex1.is_match("foo/4711/bar/5490"), true);
    assert_eq!(regex1.is_match("foo/4711/bar/5490?foo=true&bar=false"), true);
    assert_eq!(regex1.is_match("foo/4711/bar"), false);
    assert_eq!(regex1.is_match("foo/4711/bar?foo=true&bar=false"), false);
    assert_eq!(regex1.is_match("foo/4711/bar/test%20spacing"), true);
    assert_eq!(regex1.is_match("foo/4711/bar/5281?foo=test%20spacing&bar=false"), true);

    assert_eq!(regex2.is_match("foo/4711/bar"), true);
    assert_eq!(regex2.is_match("foo/4711/barr"), false);
    assert_eq!(regex2.is_match("foo/4711/bar?foo=true&bar=false"), true);
    assert_eq!(regex2.is_match("foo/4711/4712/bar"), false);
    assert_eq!(regex2.is_match("foo/4711/4712/bar?foo=true&bar=false"), false);

    assert_eq!(regex3.is_match("foo/4711/bar"), true);
    assert_eq!(regex3.is_match("foo/4711/bar?foo=true&bar=false"), true);
    assert_eq!(regex3.is_match("foo/4711/4712/bar"), true);
    assert_eq!(regex3.is_match("foo/4711/4712/bar?foo=true&bar=false"), true);

    //ensure that this works with commas too
    assert_eq!(regex1.is_match("foo/4711/bar/5490,1234"), true);
    assert_eq!(regex1.is_match("foo/4711/bar/5490,1234?foo=true&bar=false"), true);
    assert_eq!(regex1.is_match("foo/4711/bar"), false);
    assert_eq!(regex1.is_match("foo/4711/bar?foo=1,2,3&bar=false"), false);
}

#[test]
fn can_match_var_routes () {
    use hyper::method::Method;

    let route_store = &mut Router::new();
    let handler = middleware! { "hello from foo" };

    route_store.add_route(Method::Get, "/foo/:userid", handler);
    route_store.add_route(Method::Get, "/bar", handler);
    route_store.add_route(Method::Get, "/file/:format/:file", handler);

    let route_result = route_store.match_route(&Method::Get, "/foo/4711").unwrap();
    let route = route_result.route;

    assert_eq!(route_result.param("userid"), "4711");

    // assert the route has identified the variable
    assert_eq!(route.variables.len(), 2);
    assert_eq!(route.variables["userid".to_string()], 0);
    // routes have an implicit format variable
    assert_eq!(route.variables["format".to_string()], 1);

    let route_result = route_store.match_route(&Method::Get, "/bar/4711");
    assert!(route_result.is_none());

    let route_result = route_store.match_route(&Method::Get, "/foo");
    assert!(route_result.is_none());

    // ensure that this will work with commas too
    let route_result = route_store.match_route(&Method::Get, "/foo/123,456");
    assert!(route_result.is_some());

    let route_result = route_result.unwrap();
    assert_eq!(route_result.param("userid"), "123,456");

    // ensure that this will work with spacing too
    let route_result = route_store.match_route(&Method::Get, "/foo/John%20Doe");
    assert!(route_result.is_some());

    let route_result = route_result.unwrap();
    assert_eq!(route_result.param("userid"), "John%20Doe");

    // check for optional format param
    let route_result = route_store.match_route(&Method::Get, "/foo/John%20Doe.json");
    assert!(route_result.is_some());

    let route_result = route_result.unwrap();
    assert_eq!(route_result.param("userid"), "John%20Doe");
    assert_eq!(route_result.param("format"), ".json");

    // ensure format works with queries
    let route_result = route_store.match_route(&Method::Get,
    "/foo/5490,1234.csv?foo=true&bar=false");
    assert!(route_result.is_some());

    let route_result = route_result.unwrap();
    // NOTE: `.param` doesn't cover query params currently
    assert_eq!(route_result.param("userid"), "5490,1234");
    assert_eq!(route_result.param("format"), ".csv");

    // ensure format works if defined by user
    let route_result = route_store.match_route(&Method::Get, "/file/markdown/something?foo=true");
    assert!(route_result.is_some());

    let route_result = route_result.unwrap();
    // NOTE: `.param` doesn't cover query params currently
    assert_eq!(route_result.param("file"), "something");
    assert_eq!(route_result.param("format"), "markdown");
}

<|endoftext|>