<commit_before>use expr::Expr;

fn k_add_aux(x: &Expr, y: &Expr) -> Expr {
    match (x, y) {
        (&Expr::Int(x), &Expr::Int(y)) => Expr::Int(x + y),
        _ => panic!("non int args {:?} and {:?} are given to +", x, y)
    }
}

fn k_add(args:& Expr) -> Expr {
    let mut res = Expr::Int(0);
    let mut head = args;
    while head != &Expr::Nil {
        match head {
            &Expr::Cons(ref car,ref cdr) => {
                res = k_add_aux(&res, &car);
                head = &cdr
            }
            _ => panic!("invalid argument {:?} to function", args)
        }
    };
    res
}

fn funcall(f: &Expr, args: &Expr) -> Expr {
    match f {
        &Expr::Sym(ref sym) => match &sym[..] {
            "+" => k_add(args),
            _ => panic!("unknown function {:?}", f)
        },
        _ => panic!("not a function {:?}", f)
    }
}

fn eval(expr: &Expr) -> Expr {
    match expr {
        &Expr::Nil => Expr::Nil,
        &Expr::EOF => Expr::EOF,
        &Expr::Str(ref s) => Expr::Str(s.clone()),
        &Expr::Int(ref i) => Expr::Int(i.clone()),
        &Expr::Sym(_) => panic!("symbol evaluation is not supported"),
        &Expr::Cons(ref f, ref args) => funcall(&f, &args)
    }
}

#[test]
fn test_atom(){
    assert!(eval(&Expr::Int(0)) == Expr::Int(0));
    assert!(eval(&Expr::Nil) == Expr::Nil);
    assert!(eval(&Expr::EOF) == Expr::EOF);
    assert!(eval(&Expr::Str("string".to_string())) == Expr::Str("string".to_string()));
}

#[test]
fn test_add(){
    assert!(eval(&Expr::Cons(Box::new(Expr::Sym("+".to_string())),
                             Box::new(Expr::Cons(Box::new(Expr::Int(1)),
                                                 Box::new(Expr::Nil)))))
            == Expr::Int(1));
    assert!(eval(&Expr::Cons(Box::new(Expr::Sym("+".to_string())),
                             Box::new(Expr::Cons(Box::new(Expr::Int(1)),
                                                 Box::new(Expr::Cons(Box::new(Expr::Int(2)),
                                                            Box::new(Expr::Nil)))))))
            == Expr::Int(3));
    assert!(eval(&Expr::Cons(Box::new(Expr::Sym("+".to_string())),
                             Box::new(Expr::Cons(Box::new(Expr::Int(1)),
                                                 Box::new(Expr::Cons(Box::new(Expr::Int(2)),
                                                                     Box::new(Expr::Cons(Box::new(Expr::Int(3)),
                                                                                Box::new(Expr::Nil)))))))))
            == Expr::Int(6));
}
<commit_msg>rewrite with macros<commit_after>use expr::Expr;

fn k_fold<F:Fn(&Expr, &Expr) -> Expr>(f: F, init: Expr, args: &Expr) -> Expr {
    let mut res = init;
    let mut head = args;
    while head != &Expr::Nil {
        match head {
            &Expr::Cons(ref car,ref cdr) => {
                res = f(&res, &car);
                head = &cdr
            }
            _ => panic!("invalid argument {:?} to function", args)
        }
    };
    res

}

// since rust's macro cannot treat binop, work around macro is needed.

macro_rules! expr {
    ($e:expr) => {
        $e
    }
}

macro_rules! def_arith_op {
    ($name: ident, $op: tt, $init: expr) => {
        fn $name(args:& Expr) -> Expr {
            k_fold(|x, y| match (x, y) {
                (&Expr::Int(x), &Expr::Int(y)) => Expr::Int(expr!(x $op y)),
                _ => panic!("non int args {:?} and {:?} are given to $op", x, y)
            }, $init, args)
        }
    }
}

def_arith_op!(k_add, +, Expr::Int(0));

fn funcall(f: &Expr, args: &Expr) -> Expr {
    match f {
        &Expr::Sym(ref sym) => match &sym[..] {
            "+" => k_add(args),
            _ => panic!("unknown function {:?}", f)
        },
        _ => panic!("not a function {:?}", f)
    }
}

fn eval(expr: &Expr) -> Expr {
    match expr {
        &Expr::Nil => Expr::Nil,
        &Expr::EOF => Expr::EOF,
        &Expr::Str(ref s) => Expr::Str(s.clone()),
        &Expr::Int(ref i) => Expr::Int(i.clone()),
        &Expr::Sym(_) => panic!("symbol evaluation is not supported"),
        &Expr::Cons(ref f, ref args) => funcall(&f, &args)
    }
}

#[test]
fn test_atom(){
    assert!(eval(&Expr::Int(0)) == Expr::Int(0));
    assert!(eval(&Expr::Nil) == Expr::Nil);
    assert!(eval(&Expr::EOF) == Expr::EOF);
    assert!(eval(&Expr::Str("string".to_string())) == Expr::Str("string".to_string()));
}

#[test]
fn test_add(){
    assert!(eval(&Expr::Cons(Box::new(Expr::Sym("+".to_string())),
                             Box::new(Expr::Cons(Box::new(Expr::Int(1)),
                                                 Box::new(Expr::Nil)))))
            == Expr::Int(1));
    assert!(eval(&Expr::Cons(Box::new(Expr::Sym("+".to_string())),
                             Box::new(Expr::Cons(Box::new(Expr::Int(1)),
                                                 Box::new(Expr::Cons(Box::new(Expr::Int(2)),
                                                            Box::new(Expr::Nil)))))))
            == Expr::Int(3));
    assert!(eval(&Expr::Cons(Box::new(Expr::Sym("+".to_string())),
                             Box::new(Expr::Cons(Box::new(Expr::Int(1)),
                                                 Box::new(Expr::Cons(Box::new(Expr::Int(2)),
                                                                     Box::new(Expr::Cons(Box::new(Expr::Int(3)),
                                                                                Box::new(Expr::Nil)))))))))
            == Expr::Int(6));
}
<|endoftext|>


<commit_before>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

use core_foundation::base::{CFRelease, CFRetain, CFTypeID, CFTypeRef, TCFType};
use core_foundation::string::{CFString, CFStringRef};
use data_provider::{CGDataProvider, CGDataProviderRef};

use libc;
use serde::de::{self, Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer};
use std::mem;
use std::ptr;

pub type CGGlyph = libc::c_ushort;

#[repr(C)]
struct __CGFont;

pub type CGFontRef = *const __CGFont;

pub struct CGFont {
    obj: CGFontRef,
}

unsafe impl Send for CGFont {}
unsafe impl Sync for CGFont {}

impl Serialize for CGFont {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer {
        let postscript_name = self.postscript_name().to_string();
        postscript_name.serialize(serializer)
    }
}

impl Deserialize for CGFont {
    fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error> where D: Deserializer {
        let postscript_name: String = try!(Deserialize::deserialize(deserializer));
        CGFont::from_name(&CFString::new(&*postscript_name)).map_err(|err| {
            de::Error::invalid_value("Couldn't find a font with that PostScript name!")
        })
    }
}

impl Clone for CGFont {
    #[inline]
    fn clone(&self) -> CGFont {
        unsafe {
            TCFType::wrap_under_get_rule(self.obj)
        }
    }
}

impl Drop for CGFont {
    fn drop(&mut self) {
        unsafe {
            let ptr = self.as_CFTypeRef();
            assert!(ptr != ptr::null());
            CFRelease(ptr);
        }
    }
}

impl TCFType<CGFontRef> for CGFont {
    #[inline]
    fn as_concrete_TypeRef(&self) -> CGFontRef {
        self.obj
    }

    #[inline]
    unsafe fn wrap_under_get_rule(reference: CGFontRef) -> CGFont {
        let reference: CGFontRef = mem::transmute(CFRetain(mem::transmute(reference)));
        TCFType::wrap_under_create_rule(reference)
    }

    #[inline]
    fn as_CFTypeRef(&self) -> CFTypeRef {
        unsafe {
            mem::transmute(self.as_concrete_TypeRef())
        }
    }

    #[inline]
    unsafe fn wrap_under_create_rule(obj: CGFontRef) -> CGFont {
        CGFont {
            obj: obj,
        }
    }

    #[inline]
    fn type_id() -> CFTypeID {
        unsafe {
            CGFontGetTypeID()
        }
    }
}

impl CGFont {
    pub fn from_data_provider(provider: CGDataProvider) -> Result<CGFont, ()> {
        unsafe {
            let font_ref = CGFontCreateWithDataProvider(provider.as_concrete_TypeRef());
            if font_ref != ptr::null() {
                Ok(TCFType::wrap_under_create_rule(font_ref))
            } else {
                Err(())
            }
        }
    }

    pub fn from_name(name: &CFString) -> Result<CGFont, ()> {
        unsafe {
            let font_ref = CGFontCreateWithFontName(name.as_concrete_TypeRef());
            if font_ref != ptr::null() {
                Ok(TCFType::wrap_under_create_rule(font_ref))
            } else {
                Err(())
            }
        }
    }

    pub fn postscript_name(&self) -> CFString {
        unsafe {
            let string_ref = CGFontCopyPostScriptName(self.obj);
            TCFType::wrap_under_create_rule(string_ref)
        }
    }
}

#[link(name = "ApplicationServices", kind = "framework")]
extern {
    // TODO: basically nothing has bindings (even commented-out) besides what we use.
    fn CGFontCreateWithDataProvider(provider: CGDataProviderRef) -> CGFontRef;
    fn CGFontCreateWithFontName(name: CFStringRef) -> CGFontRef;
    fn CGFontGetTypeID() -> CFTypeID;

    fn CGFontCopyPostScriptName(font: CGFontRef) -> CFStringRef;

    // These do the same thing as CFRetain/CFRelease, except
    // gracefully handle a NULL argument. We don't use them.
    //fn CGFontRetain(font: CGFontRef);
    //fn CGFontRelease(font: CGFontRef);
}
<commit_msg>Silence an unused_variables warning<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

use core_foundation::base::{CFRelease, CFRetain, CFTypeID, CFTypeRef, TCFType};
use core_foundation::string::{CFString, CFStringRef};
use data_provider::{CGDataProvider, CGDataProviderRef};

use libc;
use serde::de::{self, Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer};
use std::mem;
use std::ptr;

pub type CGGlyph = libc::c_ushort;

#[repr(C)]
struct __CGFont;

pub type CGFontRef = *const __CGFont;

pub struct CGFont {
    obj: CGFontRef,
}

unsafe impl Send for CGFont {}
unsafe impl Sync for CGFont {}

impl Serialize for CGFont {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer {
        let postscript_name = self.postscript_name().to_string();
        postscript_name.serialize(serializer)
    }
}

impl Deserialize for CGFont {
    fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error> where D: Deserializer {
        let postscript_name: String = try!(Deserialize::deserialize(deserializer));
        CGFont::from_name(&CFString::new(&*postscript_name)).map_err(|_| {
            de::Error::invalid_value("Couldn't find a font with that PostScript name!")
        })
    }
}

impl Clone for CGFont {
    #[inline]
    fn clone(&self) -> CGFont {
        unsafe {
            TCFType::wrap_under_get_rule(self.obj)
        }
    }
}

impl Drop for CGFont {
    fn drop(&mut self) {
        unsafe {
            let ptr = self.as_CFTypeRef();
            assert!(ptr != ptr::null());
            CFRelease(ptr);
        }
    }
}

impl TCFType<CGFontRef> for CGFont {
    #[inline]
    fn as_concrete_TypeRef(&self) -> CGFontRef {
        self.obj
    }

    #[inline]
    unsafe fn wrap_under_get_rule(reference: CGFontRef) -> CGFont {
        let reference: CGFontRef = mem::transmute(CFRetain(mem::transmute(reference)));
        TCFType::wrap_under_create_rule(reference)
    }

    #[inline]
    fn as_CFTypeRef(&self) -> CFTypeRef {
        unsafe {
            mem::transmute(self.as_concrete_TypeRef())
        }
    }

    #[inline]
    unsafe fn wrap_under_create_rule(obj: CGFontRef) -> CGFont {
        CGFont {
            obj: obj,
        }
    }

    #[inline]
    fn type_id() -> CFTypeID {
        unsafe {
            CGFontGetTypeID()
        }
    }
}

impl CGFont {
    pub fn from_data_provider(provider: CGDataProvider) -> Result<CGFont, ()> {
        unsafe {
            let font_ref = CGFontCreateWithDataProvider(provider.as_concrete_TypeRef());
            if font_ref != ptr::null() {
                Ok(TCFType::wrap_under_create_rule(font_ref))
            } else {
                Err(())
            }
        }
    }

    pub fn from_name(name: &CFString) -> Result<CGFont, ()> {
        unsafe {
            let font_ref = CGFontCreateWithFontName(name.as_concrete_TypeRef());
            if font_ref != ptr::null() {
                Ok(TCFType::wrap_under_create_rule(font_ref))
            } else {
                Err(())
            }
        }
    }

    pub fn postscript_name(&self) -> CFString {
        unsafe {
            let string_ref = CGFontCopyPostScriptName(self.obj);
            TCFType::wrap_under_create_rule(string_ref)
        }
    }
}

#[link(name = "ApplicationServices", kind = "framework")]
extern {
    // TODO: basically nothing has bindings (even commented-out) besides what we use.
    fn CGFontCreateWithDataProvider(provider: CGDataProviderRef) -> CGFontRef;
    fn CGFontCreateWithFontName(name: CFStringRef) -> CGFontRef;
    fn CGFontGetTypeID() -> CFTypeID;

    fn CGFontCopyPostScriptName(font: CGFontRef) -> CFStringRef;

    // These do the same thing as CFRetain/CFRelease, except
    // gracefully handle a NULL argument. We don't use them.
    //fn CGFontRetain(font: CGFontRef);
    //fn CGFontRelease(font: CGFontRef);
}
<|endoftext|>


<commit_before>use piston_window::*;

use board::Board;
use randomizer::Randomizer;
use tetromino::*;
use settings::*;
use stats::GameStats;

#[derive(Debug, PartialEq)]
pub enum GameState {
    NotStarted,
    Playing,
    Paused,
    GameOver
}

pub trait Game {
    fn on_input(&mut self, input: Input);
    fn on_update(&mut self, update_args: UpdateArgs);
    fn render(&mut self, context: Context, graphics: &mut G2d);
}

pub struct Rustris {
    board: Board,
    randomizer: Randomizer,
    current_piece: Piece,
    next_piece: Piece,
    stats: GameStats,
    time_since_moved: f64,
    state: GameState
}
impl Rustris {
    pub fn new() -> Rustris {
        let mut randomizer = Randomizer::new();
        let current_piece = randomizer.create_piece();
        let next_piece = randomizer.create_piece();
        Rustris {
            board: Board::new(),
            randomizer: randomizer,
            current_piece: current_piece,
            next_piece: next_piece,
            stats: GameStats::new(),
            time_since_moved: 0.0,
            state: GameState::Playing
        }
    }

    pub fn get_game_stats(&self) -> &GameStats {
        &self.stats
    }

    pub fn set_current_piece(&mut self, piece: Piece) {
        self.current_piece = piece;
    }

    pub fn is_paused(&self) -> bool {
        self.state == GameState::Paused
    }

    pub fn set_game_state(&mut self, state: GameState) {
        self.state = state;
    }

    fn iteration_delay(&self) -> f64 {
        ((MAX_GAME_LEVEL + 1) - self.stats.get_level()) as f64 * 0.10
    }

    fn is_valid_board_position(&self, piece: &Piece) -> bool {
        // TODO: Add tests for this
        piece.blocks_iter().all(|block| {
            (block.x >= 0 && block.x < WIDTH_IN_BLOCKS &&
             block.y >= 0 && block.y < HEIGHT_IN_BLOCKS &&
             !self.board.is_space_occupied(block))
        })
    }

    fn lock_current_piece(&mut self) {
        self.board.set_piece(&self.current_piece);
        self.remove_completed_lines();
        self.get_new_piece();
    }

    fn remove_completed_lines(&mut self) {
        let number_removed = self.board.remove_completed_rows();
        self.stats.score_completed_lines(number_removed);
    }

    fn calculate_ghost_piece(&self) -> Piece {
        let mut ghost = self.current_piece;
        while self.is_valid_board_position(&ghost) {
            ghost.y += 1;
        }
        ghost.y -= 1;
        ghost
    }

    fn get_new_piece(&mut self) {
        let next = self.next_piece;
        if self.is_valid_board_position(&next){
            self.set_current_piece(next);
            self.next_piece = self.randomizer.create_piece();
        } else {
            self.state = GameState::GameOver;
        }
    }

    fn update(&mut self) {
        let moved = self.current_piece.moved(Direction::Down);
        if !self.is_valid_board_position(&moved) {
            self.lock_current_piece();
        } else {
            self.set_current_piece(moved);
        }
    }

    fn handle_playing_input(&mut self, input: Input) {
        let mut moved: Option<Piece> = None;
        match input {
            Input::Press(key) => {
                match key {
                    Button::Keyboard(Key::Up) => {
                        moved = Some(self.current_piece.rotated());
                    }
                    Button::Keyboard(Key::Down) => {
                        let move_down = self.current_piece.moved(Direction::Down);
                        if self.is_valid_board_position(&move_down) {
                            self.time_since_moved = 0.0;
                            self.stats.score_soft_drop();
                            self.set_current_piece(move_down);
                        }
                    }
                    Button::Keyboard(Key::Left) => {
                        moved = Some(self.current_piece.moved(Direction::Left));
                    }
                    Button::Keyboard(Key::Right) => {
                        moved = Some(self.current_piece.moved(Direction::Right));
                    }
                    Button::Keyboard(Key::Space) => {
                        let ghost = self.calculate_ghost_piece();
                        let rows_dropped = (ghost.y - self.current_piece.y) as u32;
                        self.stats.score_hard_drop(rows_dropped);
                        self.set_current_piece(ghost);
                        self.lock_current_piece();
                    }
                    Button::Keyboard(Key::P) => {
                        self.state = GameState::Paused
                    }
                    _ => {}
                }
            }
            _ => {}
        }
        if let Some(piece) = moved {
            if self.is_valid_board_position(&piece) {
                self.set_current_piece(piece);
            }
        }
    }

    fn handle_paused_input(&mut self, input: Input) {
        match input {
            Input::Press(key) => {
                match key {
                    Button::Keyboard(Key::P) => {
                        self.state = GameState::Playing
                    },
                    _ => {}
                }
            },
            _ => {}
        }
    }
}
impl Game for Rustris {
    fn on_input(&mut self, input: Input) {
        match self.state {
            GameState::Playing => self.handle_playing_input(input),
            GameState::Paused => self.handle_paused_input(input),
            _ => {}
        }
    }

    fn on_update(&mut self, update_args: UpdateArgs) {
        match self.state {
            GameState::Playing => {
                self.time_since_moved += update_args.dt;
                let delay = self.iteration_delay();
                if self.time_since_moved >= delay {
                    self.time_since_moved -= delay;
                    self.update();
                }
            },
            _ => {}
        }
    }

    fn render(&mut self, context: Context, graphics: &mut G2d) {
        self.board.render(context, graphics);
        self.calculate_ghost_piece().render_ghost(context, graphics);
        self.current_piece.render_normal(context, graphics);
    }
}

// TODO: Move this into its own module
pub fn render_square_in_grid(x: i32, y: i32, rect: Rectangle, context: Context, graphics: &mut G2d) {
    let square = rectangle::square(
        0.0, 0.0, BLOCK_SIZE - (2.0 * GRID_LINE_WIDTH)
    );
    let transform = context.transform
        // Translate the origin of the transform based on where the grid starts
        .trans(GRID_X_OFFSET, GRID_Y_OFFSET)
        // Translate the square into the first grid cell (off of the bounding box)
        .trans(GRID_LINE_WIDTH, GRID_LINE_WIDTH)
        // Translate the square into the proper grid cell based on the grid x and y position
        .trans((x as f64)*BLOCK_SIZE, (y as f64)*BLOCK_SIZE);
    rect.draw(square, &Default::default(), transform, graphics);
}
<commit_msg>rename iteration_delay to drop_delay<commit_after>use piston_window::*;

use board::Board;
use randomizer::Randomizer;
use tetromino::*;
use settings::*;
use stats::GameStats;

#[derive(Debug, PartialEq)]
pub enum GameState {
    NotStarted,
    Playing,
    Paused,
    GameOver
}

pub trait Game {
    fn on_input(&mut self, input: Input);
    fn on_update(&mut self, update_args: UpdateArgs);
    fn render(&mut self, context: Context, graphics: &mut G2d);
}

pub struct Rustris {
    board: Board,
    randomizer: Randomizer,
    current_piece: Piece,
    next_piece: Piece,
    stats: GameStats,
    time_since_moved: f64,
    state: GameState
}
impl Rustris {
    pub fn new() -> Rustris {
        let mut randomizer = Randomizer::new();
        let current_piece = randomizer.create_piece();
        let next_piece = randomizer.create_piece();
        Rustris {
            board: Board::new(),
            randomizer: randomizer,
            current_piece: current_piece,
            next_piece: next_piece,
            stats: GameStats::new(),
            time_since_moved: 0.0,
            state: GameState::Playing
        }
    }

    pub fn get_game_stats(&self) -> &GameStats {
        &self.stats
    }

    pub fn set_current_piece(&mut self, piece: Piece) {
        self.current_piece = piece;
    }

    pub fn is_paused(&self) -> bool {
        self.state == GameState::Paused
    }

    pub fn set_game_state(&mut self, state: GameState) {
        self.state = state;
    }

    fn drop_delay(&self) -> f64 {
        ((MAX_GAME_LEVEL + 1) - self.stats.get_level()) as f64 * 0.10
    }

    fn is_valid_board_position(&self, piece: &Piece) -> bool {
        // TODO: Add tests for this
        piece.blocks_iter().all(|block| {
            (block.x >= 0 && block.x < WIDTH_IN_BLOCKS &&
             block.y >= 0 && block.y < HEIGHT_IN_BLOCKS &&
             !self.board.is_space_occupied(block))
        })
    }

    fn lock_current_piece(&mut self) {
        self.board.set_piece(&self.current_piece);
        self.remove_completed_lines();
        self.get_new_piece();
    }

    fn remove_completed_lines(&mut self) {
        let number_removed = self.board.remove_completed_rows();
        self.stats.score_completed_lines(number_removed);
    }

    fn calculate_ghost_piece(&self) -> Piece {
        let mut ghost = self.current_piece;
        while self.is_valid_board_position(&ghost) {
            ghost.y += 1;
        }
        ghost.y -= 1;
        ghost
    }

    fn get_new_piece(&mut self) {
        let next = self.next_piece;
        if self.is_valid_board_position(&next){
            self.set_current_piece(next);
            self.next_piece = self.randomizer.create_piece();
        } else {
            self.state = GameState::GameOver;
        }
    }

    fn update(&mut self) {
        let moved = self.current_piece.moved(Direction::Down);
        if !self.is_valid_board_position(&moved) {
            self.lock_current_piece();
        } else {
            self.set_current_piece(moved);
        }
    }

    fn handle_playing_input(&mut self, input: Input) {
        let mut moved: Option<Piece> = None;
        match input {
            Input::Press(key) => {
                match key {
                    Button::Keyboard(Key::Up) => {
                        moved = Some(self.current_piece.rotated());
                    }
                    Button::Keyboard(Key::Down) => {
                        let move_down = self.current_piece.moved(Direction::Down);
                        if self.is_valid_board_position(&move_down) {
                            self.time_since_moved = 0.0;
                            self.stats.score_soft_drop();
                            self.set_current_piece(move_down);
                        }
                    }
                    Button::Keyboard(Key::Left) => {
                        moved = Some(self.current_piece.moved(Direction::Left));
                    }
                    Button::Keyboard(Key::Right) => {
                        moved = Some(self.current_piece.moved(Direction::Right));
                    }
                    Button::Keyboard(Key::Space) => {
                        let ghost = self.calculate_ghost_piece();
                        let rows_dropped = (ghost.y - self.current_piece.y) as u32;
                        self.stats.score_hard_drop(rows_dropped);
                        self.set_current_piece(ghost);
                        self.lock_current_piece();
                    }
                    Button::Keyboard(Key::P) => {
                        self.state = GameState::Paused
                    }
                    _ => {}
                }
            }
            _ => {}
        }
        if let Some(piece) = moved {
            if self.is_valid_board_position(&piece) {
                self.set_current_piece(piece);
            }
        }
    }

    fn handle_paused_input(&mut self, input: Input) {
        match input {
            Input::Press(key) => {
                match key {
                    Button::Keyboard(Key::P) => {
                        self.state = GameState::Playing
                    },
                    _ => {}
                }
            },
            _ => {}
        }
    }
}
impl Game for Rustris {
    fn on_input(&mut self, input: Input) {
        match self.state {
            GameState::Playing => self.handle_playing_input(input),
            GameState::Paused => self.handle_paused_input(input),
            _ => {}
        }
    }

    fn on_update(&mut self, update_args: UpdateArgs) {
        match self.state {
            GameState::Playing => {
                self.time_since_moved += update_args.dt;
                let delay = self.drop_delay();
                if self.time_since_moved >= delay {
                    self.time_since_moved -= delay;
                    self.update();
                }
            },
            _ => {}
        }
    }

    fn render(&mut self, context: Context, graphics: &mut G2d) {
        self.board.render(context, graphics);
        self.calculate_ghost_piece().render_ghost(context, graphics);
        self.current_piece.render_normal(context, graphics);
    }
}

// TODO: Move this into its own module
pub fn render_square_in_grid(x: i32, y: i32, rect: Rectangle, context: Context, graphics: &mut G2d) {
    let square = rectangle::square(
        0.0, 0.0, BLOCK_SIZE - (2.0 * GRID_LINE_WIDTH)
    );
    let transform = context.transform
        // Translate the origin of the transform based on where the grid starts
        .trans(GRID_X_OFFSET, GRID_Y_OFFSET)
        // Translate the square into the first grid cell (off of the bounding box)
        .trans(GRID_LINE_WIDTH, GRID_LINE_WIDTH)
        // Translate the square into the proper grid cell based on the grid x and y position
        .trans((x as f64)*BLOCK_SIZE, (y as f64)*BLOCK_SIZE);
    rect.draw(square, &Default::default(), transform, graphics);
}
<|endoftext|>


<commit_before>pub struct Point<T> {
    pub x: T,
    pub y: T
}

impl<T> Point<T> {
    pub fn new(x: T, y: T) -> Point<T> {
        return Point{x: x, y: y};
    }
}

impl<T:Clone + Add<T,T>> Add<Point<T>, Point<T>> for Point<T> {
    fn add(&self, other: &Point<T>) -> Point<T> {
        return Point::new(self.x + other.x, self.y + other.y);
    }
}

impl<T:Clone + Sub<T,T>> Sub<Point<T>, Point<T>> for Point<T> {
    fn sub(&self, other: &Point<T>) -> Point<T> {
        return Point::new(self.x - other.x, self.y - other.y);
    }
}

impl<T:Clone + Mul<T,T>> Point<T> {
    pub fn scale(&self, factor: T) -> Point<T> {
        return Point::new(self.x * factor, self.y * factor);
    }
}

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

    #[test]
    fn test_add() {
        let p1 = Point::<int>::new(2, 3);
        let p2 = Point::<int>::new(1, 5);
        let p3 = p1 + p2;
        assert_eq!((p3.x, p3.y), (3, 8));
    }

    #[test]
    fn test_sub() {
        let p1 = Point::<int>::new(2, 3);
        let p2 = Point::<int>::new(1, 5);
        let p3 = p1 - p2;
        assert_eq!((p3.x, p3.y), (1, -2));
    }

    #[test]
    fn test_scale() {
        let p = Point::<int>::new(2, 3).scale(2);
        assert_eq!((p.x, p.y), (4, 6));
    }
}
<commit_msg>fix ownership errors<commit_after>pub struct Point<T> {
    pub x: T,
    pub y: T
}

impl<T> Point<T> {
    pub fn new(x: T, y: T) -> Point<T> {
        return Point{x: x, y: y};
    }
}

impl<T:Clone + Add<T,T>> Add<Point<T>, Point<T>> for Point<T> {
    fn add(self, other: Point<T>) -> Point<T> {
        return Point::new(self.x + other.x, self.y + other.y);
    }
}

impl<T:Clone + Sub<T,T>> Sub<Point<T>, Point<T>> for Point<T> {
    fn sub(self, other: Point<T>) -> Point<T> {
        return Point::new(self.x - other.x, self.y - other.y);
    }
}

impl<T:Clone + Mul<T,T>> Point<T> {
    pub fn scale(&self, factor: T) -> Point<T> {
        let x = self.x.clone() * factor.clone();
        let y = self.y.clone() * factor;
        return Point::new(x, y);
    }
}

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

    #[test]
    fn test_add() {
        let p1 = Point::<int>::new(2, 3);
        let p2 = Point::<int>::new(1, 5);
        let p3 = p1 + p2;
        assert_eq!((p3.x, p3.y), (3, 8));
    }

    #[test]
    fn test_sub() {
        let p1 = Point::<int>::new(2, 3);
        let p2 = Point::<int>::new(1, 5);
        let p3 = p1 - p2;
        assert_eq!((p3.x, p3.y), (1, -2));
    }

    #[test]
    fn test_scale() {
        let p = Point::<int>::new(2, 3).scale(2);
        assert_eq!((p.x, p.y), (4, 6));
    }
}
<|endoftext|>


<commit_before>extern crate libloading as libl;

use std::collections::HashMap;
use std::ffi::CString;
use std::io;
use std::os::raw::{c_char, c_int, c_uint, c_void};

// -- Private utility functions -- //
fn to_c_str<T: Into<Vec<u8>>>(t: T) -> *const c_char {
    CString::new(t).unwrap().as_ptr() as *const c_char
}

// -- Model the functions we'll dynamically load -- //
pub type CoreClrInitializeFn = unsafe extern fn(
    *const c_char,
    *const c_char,
    c_int,
    *const *const c_char,
    *const *const c_char,
    *const *const c_void,
    *const c_uint) -> c_int;

pub type CoreClrShutdownFn = unsafe extern fn(*const c_void, c_uint) -> c_int;

pub type CoreClrShutdown2Fn = unsafe extern fn(*const c_void, c_uint, *const c_int) -> c_int;

// -- Model the CLR -- //
pub struct CoreClr {
    host_handle: *const c_void,
    domain_id: c_uint
}

impl CoreClr {
    fn library() -> libl::Result<libl::Library> {
        libl::Library::new("/usr/local/share/dotnet/shared/Microsoft.NETCore.App/2.0.0")
    }

    pub fn init(
        exe_path: &str,
        app_domain_friendly_name: &str,
        properties_option: Option<HashMap<&str, &str>>) -> libl::Result<CoreClr>
    {
        // Create the host handle and its ref
        let host_handle = 0 as *const c_void;
        let host_handle_ref = &host_handle as *const *const c_void;

        // Create the domain id and its ref
        let domain_id = 0 as c_uint;
        let domain_id_ref = &domain_id as *const c_uint;

        // Raw C string refs from exe_path and app_domain_friendly_name slices
        let exe_path_raw = to_c_str(exe_path);
        let app_domain_friendly_name_raw = to_c_str(app_domain_friendly_name);

        // Either use the provided option or a blank hashmap
        let properties = properties_option.unwrap_or_else(HashMap::new);

        // Count for upcoming vecs
        let properties_count = properties.len() as c_int;

        // Collect property keys into a vec
        let properties_keys: Vec<*const c_char> = properties.keys()
                .map(|&k| to_c_str(k))
                .collect();

        // Collect equivalent property values into another vec
        let properties_values: Vec<*const c_char> = properties.values()
                .map(|&v| to_c_str(v))
                .collect();

        // Grab refs of the two to pass into the actual function call
        let properties_keys_ref = &properties_keys[0] as *const *const c_char;
        let properties_values_ref = &properties_values[0] as *const *const c_char;

        // Open up an unsafe block for actually loading functions from the CLR libs
        unsafe {
            let coreclr_library = CoreClr::library()?;
            let coreclr_initialize: libl::Symbol<CoreClrInitializeFn> = coreclr_library.get(b"coreclr_initialize")?;

            // Initialize the CLR
            match coreclr_initialize(
                exe_path_raw,
                app_domain_friendly_name_raw,
                properties_count,
                properties_keys_ref,
                properties_values_ref,
                host_handle_ref,
                domain_id_ref)
            {
                // If healthy exit code, return a model of the CLR
                0 => Ok(CoreClr {
                    host_handle: host_handle,
                    domain_id: domain_id
                }),
                // Else panic
                _ => panic!("Failed to initialize")
            }
        }
    }

    pub fn shutdown(self: Self) -> io::Result<()> {
        unsafe {
            let coreclr_library = CoreClr::library()?;
            let coreclr_shutdown_fn: libl::Symbol<CoreClrShutdownFn> = coreclr_library.get(b"coreclr_shutdown")?;

            // Shutdown the CLR
            match coreclr_shutdown_fn(self.host_handle, self.domain_id) {
                // If healthy exit code, return unit
                0 => Ok(()),
                // Else panic
                _ => panic!("Failed to shutdown")
            }
        }
    }

    pub fn shutdown_2(self: Self) -> io::Result<c_int> {
        let latched_exit_code = -1 as c_int;
        let latched_exit_code_ref = &latched_exit_code as *const c_int;

        unsafe {
            let coreclr_library = CoreClr::library()?;
            let coreclr_shutdown_2_fn: libl::Symbol<CoreClrShutdown2Fn> = coreclr_library.get(b"coreclr_shutdown_2")?;

            // Shutdown the CLR
            match coreclr_shutdown_2_fn(self.host_handle, self.domain_id, latched_exit_code_ref) {
                // If healthy exit code, return the resulting exit code
                0 => Ok(latched_exit_code),
                // Else panic
                _ => panic!("Failed to shutdown")
            }
        }
    }
}<commit_msg>Small name updates<commit_after>extern crate libloading as libl;

use std::collections::HashMap;
use std::ffi::CString;
use std::io;
use std::os::raw::{c_char, c_int, c_uint, c_void};

// -- Private utility functions -- //
fn to_c_str<T: Into<Vec<u8>>>(t: T) -> *const c_char {
    CString::new(t).unwrap().as_ptr() as *const c_char
}

// -- Model the functions we'll dynamically load -- //
pub type CoreClrInitializeFn = unsafe extern fn(
    *const c_char,
    *const c_char,
    c_int,
    *const *const c_char,
    *const *const c_char,
    *const *const c_void,
    *const c_uint) -> c_int;

pub type CoreClrShutdownFn = unsafe extern fn(*const c_void, c_uint) -> c_int;

pub type CoreClrShutdown2Fn = unsafe extern fn(*const c_void, c_uint, *const c_int) -> c_int;

// -- Model the CLR -- //
pub struct CoreClr {
    host_handle: *const c_void,
    domain_id: c_uint
}

impl CoreClr {
    fn library() -> libl::Result<libl::Library> {
        libl::Library::new("/usr/local/share/dotnet/shared/Microsoft.NETCore.App/2.0.0")
    }

    pub fn init(
        exe_path: &str,
        app_domain_friendly_name: &str,
        properties_option: Option<HashMap<&str, &str>>) -> libl::Result<CoreClr>
    {
        // Create the host handle and its ref
        let host_handle = 0 as *const c_void;
        let host_handle_ref = &host_handle as *const *const c_void;

        // Create the domain id and its ref
        let domain_id = 0 as c_uint;
        let domain_id_ref = &domain_id as *const c_uint;

        // Raw C string refs from exe_path and app_domain_friendly_name slices
        let exe_path_raw = to_c_str(exe_path);
        let app_domain_friendly_name_raw = to_c_str(app_domain_friendly_name);

        // Either use the provided option or a blank hashmap
        let properties = properties_option.unwrap_or_else(HashMap::new);

        // Count for upcoming vecs
        let properties_count = properties.len() as c_int;

        // Collect property keys into a vec
        let properties_keys: Vec<*const c_char> = properties.keys()
                .map(|&k| to_c_str(k))
                .collect();

        // Collect equivalent property values into another vec
        let properties_values: Vec<*const c_char> = properties.values()
                .map(|&v| to_c_str(v))
                .collect();

        // Grab refs of the two to pass into the actual function call
        let properties_keys_ref = &properties_keys[0] as *const *const c_char;
        let properties_values_ref = &properties_values[0] as *const *const c_char;

        // Open up an unsafe block for actually loading functions from the CLR libs
        unsafe {
            let coreclr_library = CoreClr::library()?;
            let coreclr_initialize: libl::Symbol<CoreClrInitializeFn> = coreclr_library.get(b"coreclr_initialize")?;

            // Initialize the CLR
            match coreclr_initialize(
                exe_path_raw,
                app_domain_friendly_name_raw,
                properties_count,
                properties_keys_ref,
                properties_values_ref,
                host_handle_ref,
                domain_id_ref)
            {
                // If healthy exit code, return a model of the CLR
                0 => Ok(CoreClr {
                    host_handle: host_handle,
                    domain_id: domain_id
                }),
                // Else panic
                _ => panic!("Failed to initialize")
            }
        }
    }

    pub fn shutdown(self: Self) -> io::Result<()> {
        unsafe {
            let coreclr_library = CoreClr::library()?;
            let coreclr_shutdown: libl::Symbol<CoreClrShutdownFn> = coreclr_library.get(b"coreclr_shutdown")?;

            // Shutdown the CLR
            match coreclr_shutdown(self.host_handle, self.domain_id) {
                // If healthy exit code, return unit
                0 => Ok(()),
                // Else panic
                _ => panic!("Failed to shutdown")
            }
        }
    }

    pub fn shutdown_2(self: Self) -> io::Result<c_int> {
        let latched_exit_code = -1 as c_int;
        let latched_exit_code_ref = &latched_exit_code as *const c_int;

        unsafe {
            let coreclr_library = CoreClr::library()?;
            let coreclr_shutdown_2: libl::Symbol<CoreClrShutdown2Fn> = coreclr_library.get(b"coreclr_shutdown_2")?;

            // Shutdown the CLR
            match coreclr_shutdown_2(self.host_handle, self.domain_id, latched_exit_code_ref) {
                // If healthy exit code, return the resulting exit code
                0 => Ok(latched_exit_code),
                // Else panic
                _ => panic!("Failed to shutdown")
            }
        }
    }
}<|endoftext|>


<commit_before>//! Utilities for iteration with duration objects.

use duration::FloatDuration;
use std::iter;

/// An iterator over an evenly spaced lattice of `FloatDuration`s.
///
/// This type is returned by `subdivide` and friends, and it not meant to be
/// instantiated directly.
#[derive(Debug, Clone)]
pub struct Subdivide {
    start: FloatDuration,
    step_size: FloatDuration,
    len: usize,
    index: usize,
}

impl Subdivide {
    fn new(start: FloatDuration, end: FloatDuration, steps: usize) -> Subdivide {
        assert!(steps >= 2, "subdivide requires at least two steps");
        let step_size = (end - start) / (steps - 1) as f64;

        Subdivide {
            start: start,
            step_size: step_size,
            len: steps,
            index: 0,
        }
    }

    /// The distance between steps in the iteration.
    pub fn step_size(&self) -> FloatDuration {
        self.step_size
    }
}

impl Iterator for Subdivide {
    type Item = FloatDuration;

    #[inline]
    fn next(&mut self) -> Option<FloatDuration> {
        if self.index >= self.len {
            None
        } else {
            let index = self.index;
            self.index += 1;
            Some(self.start + self.step_size * (index as f64))
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let left = self.len - self.index;
        (left, Some(left))
    }
}

impl DoubleEndedIterator for Subdivide {
    fn next_back(&mut self) -> Option<FloatDuration> {
        if self.index >= self.len {
            None
        } else {
            self.len -= 1;
            let index = self.len;
            Some(self.start + self.step_size * (index as f64))
        }
    }
}

impl ExactSizeIterator for Subdivide {}

/// Subdivide the distance between two duration into `steps` evenly spaced points.
///
/// `subdivide` returns an iterator that lazily computes and returns exactly `steps`
/// evenly spaced
/// points between `begin` and `end`. This iterator is *inclusive* in that it
/// returns `begin` as the first element and `end` as the final element.
///
/// The returned iterator [`Subdivide`](struct.Subdivide.html) implements
/// `DoubleEndedIterator`, and thus can be reversed or consumed from both sides.
///
/// ```rust
/// use float_duration::FloatDuration;
/// use float_duration::iter::subdivide;
///
/// fn cost_function(t: &FloatDuration) -> f64 {
///     return 0.5*t.as_seconds()*t.as_seconds()
/// }
/// fn main() {
///     let start = FloatDuration::zero();
///     let end = FloatDuration::minutes(10.0);
///     let total: f64 = subdivide(start, end, 100).map(|x| cost_function(&x)).sum();
/// }
/// ```
///
/// # Panics
/// This function panics if `steps < 2` as this would violate the property
/// that the iterator visits both endpoints.
pub fn subdivide(begin: FloatDuration, end: FloatDuration, steps: usize) -> Subdivide {
    Subdivide::new(begin, end, steps)
}

/// Subdivide the distance between two duration into `steps` evenly spaced points
/// and include a timestep.
///
/// `subdivide_with_step` is equivalent to [`subdivide`](fn.subdivide.html)
/// except that it returns the
/// step size with the current time in each iteration. It is mainly a convenience
/// function for the common case of running a simulation over discrete time steps.
///
/// It is exactly equivalent to:
///
/// ```rust
/// # use float_duration::FloatDuration;
/// # use float_duration::iter::subdivide;
/// use std::iter;
///
/// let steps = 100;
/// # let begin = FloatDuration::zero();
/// # let end = FloatDuration::minutes(5.0);
///
/// let sub = subdivide(begin, end, steps);
/// let step_size = sub.step_size();
/// let my_iter = sub.zip(iter::repeat(step_size));
/// ```
///
/// Example usage in a simulation:
///
/// ```rust
/// use float_duration::FloatDuration;
/// use float_duration::iter::subdivide_with_step;
///
/// let start = FloatDuration::zero();
/// let end = FloatDuration::hours(1.0);
///
/// let mut x = 5.0;
/// let mut v = 0.0;
///
/// for (t, dt) in subdivide_with_step(start, end, 100) {
///      let a = x*x - v*x;
///      let v = a*dt.as_seconds();
///      let x = v*dt.as_seconds();
///
///      println!("Position: {}", x);
/// }
/// ```
///
/// # Panics
/// This function panics if `steps < 2` as this would violate the property
/// that the iterator visits both endpoints.
///
pub fn subdivide_with_step(begin: FloatDuration,
                           end: FloatDuration,
                           steps: usize)
                           -> iter::Zip<Subdivide, iter::Repeat<FloatDuration>> {
    let sub = subdivide(begin, end, steps);
    let step_size = sub.step_size();
    sub.zip(iter::repeat(step_size))
}

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

    #[test]
    fn test_subdivide() {
        let s = subdivide(FloatDuration::zero(), FloatDuration::minutes(1.0), 3);
        let s_rev = s.clone().rev();
        assert_eq!(s.collect::<Vec<_>>(),
                   vec![FloatDuration::zero(),
                        FloatDuration::seconds(30.0),
                        FloatDuration::minutes(1.0)]);
        assert_eq!(s_rev.collect::<Vec<_>>(),
                   vec![FloatDuration::minutes(1.0),
                        FloatDuration::seconds(30.0),
                        FloatDuration::zero()]);

    }
}
<commit_msg>Added more tests in `iter`.<commit_after>//! Utilities for iteration with duration objects.

use duration::FloatDuration;
use std::iter;

/// An iterator over an evenly spaced lattice of `FloatDuration`s.
///
/// This type is returned by `subdivide` and friends, and it not meant to be
/// instantiated directly.
#[derive(Debug, Clone)]
pub struct Subdivide {
    start: FloatDuration,
    step_size: FloatDuration,
    len: usize,
    index: usize,
}

impl Subdivide {
    fn new(start: FloatDuration, end: FloatDuration, steps: usize) -> Subdivide {
        assert!(steps >= 2, "subdivide requires at least two steps");
        let step_size = (end - start) / (steps - 1) as f64;

        Subdivide {
            start: start,
            step_size: step_size,
            len: steps,
            index: 0,
        }
    }

    /// The distance between steps in the iteration.
    pub fn step_size(&self) -> FloatDuration {
        self.step_size
    }
}

impl Iterator for Subdivide {
    type Item = FloatDuration;

    #[inline]
    fn next(&mut self) -> Option<FloatDuration> {
        if self.index >= self.len {
            None
        } else {
            let index = self.index;
            self.index += 1;
            Some(self.start + self.step_size * (index as f64))
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let left = self.len - self.index;
        (left, Some(left))
    }
}

impl DoubleEndedIterator for Subdivide {
    fn next_back(&mut self) -> Option<FloatDuration> {
        if self.index >= self.len {
            None
        } else {
            self.len -= 1;
            let index = self.len;
            Some(self.start + self.step_size * (index as f64))
        }
    }
}

impl ExactSizeIterator for Subdivide {}

/// Subdivide the distance between two duration into `steps` evenly spaced points.
///
/// `subdivide` returns an iterator that lazily computes and returns exactly `steps`
/// evenly spaced
/// points between `begin` and `end`. This iterator is *inclusive* in that it
/// returns `begin` as the first element and `end` as the final element.
///
/// The returned iterator [`Subdivide`](struct.Subdivide.html) implements
/// `DoubleEndedIterator`, and thus can be reversed or consumed from both sides.
///
/// ```rust
/// use float_duration::FloatDuration;
/// use float_duration::iter::subdivide;
///
/// fn cost_function(t: &FloatDuration) -> f64 {
///     return 0.5*t.as_seconds()*t.as_seconds()
/// }
/// fn main() {
///     let start = FloatDuration::zero();
///     let end = FloatDuration::minutes(10.0);
///     let total: f64 = subdivide(start, end, 100).map(|x| cost_function(&x)).sum();
/// }
/// ```
///
/// # Panics
/// This function panics if `steps < 2` as this would violate the property
/// that the iterator visits both endpoints.
pub fn subdivide(begin: FloatDuration, end: FloatDuration, steps: usize) -> Subdivide {
    Subdivide::new(begin, end, steps)
}

/// Subdivide the distance between two duration into `steps` evenly spaced points
/// and include a timestep.
///
/// `subdivide_with_step` is equivalent to [`subdivide`](fn.subdivide.html)
/// except that it returns the
/// step size with the current time in each iteration. It is mainly a convenience
/// function for the common case of running a simulation over discrete time steps.
///
/// It is exactly equivalent to:
///
/// ```rust
/// # use float_duration::FloatDuration;
/// # use float_duration::iter::subdivide;
/// use std::iter;
///
/// let steps = 100;
/// # let begin = FloatDuration::zero();
/// # let end = FloatDuration::minutes(5.0);
///
/// let sub = subdivide(begin, end, steps);
/// let step_size = sub.step_size();
/// let my_iter = sub.zip(iter::repeat(step_size));
/// ```
///
/// Example usage in a simulation:
///
/// ```rust
/// use float_duration::FloatDuration;
/// use float_duration::iter::subdivide_with_step;
///
/// let start = FloatDuration::zero();
/// let end = FloatDuration::hours(1.0);
///
/// let mut x = 5.0;
/// let mut v = 0.0;
///
/// for (t, dt) in subdivide_with_step(start, end, 100) {
///      let a = x*x - v*x;
///      let v = a*dt.as_seconds();
///      let x = v*dt.as_seconds();
///
///      println!("Position: {}", x);
/// }
/// ```
///
/// # Panics
/// This function panics if `steps < 2` as this would violate the property
/// that the iterator visits both endpoints.
///
pub fn subdivide_with_step(begin: FloatDuration,
                           end: FloatDuration,
                           steps: usize)
                           -> iter::Zip<Subdivide, iter::Repeat<FloatDuration>> {
    let sub = subdivide(begin, end, steps);
    let step_size = sub.step_size();
    sub.zip(iter::repeat(step_size))
}

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

    #[test]
    fn test_subdivide() {
        let s = subdivide(FloatDuration::zero(), FloatDuration::minutes(1.0), 3);
        let s_rev = s.clone().rev();
        assert_eq!(s.collect::<Vec<_>>(),
                   vec![FloatDuration::zero(),
                        FloatDuration::seconds(30.0),
                        FloatDuration::minutes(1.0)]);
        assert_eq!(s_rev.collect::<Vec<_>>(),
                   vec![FloatDuration::minutes(1.0),
                        FloatDuration::seconds(30.0),
                        FloatDuration::zero()]);

        assert_eq!(subdivide(FloatDuration::zero(), FloatDuration::zero(), 3).collect::<Vec<_>>(),
                   vec![FloatDuration::zero(), FloatDuration::zero(), FloatDuration::zero()]);
    }

    #[should_panic]
    #[test]
    fn test_subdivide_panic() {
        subdivide(FloatDuration::zero(), FloatDuration::minutes(1.0), 1);
    }
}
<|endoftext|>


<commit_before>use std::path::PathBuf;
use std::collections::HashMap;

use rsh::State;
use rsh::utils;

pub type Builtin = fn(&mut State) -> i32;

pub fn load() -> HashMap<String, Builtin> {
    let mut h = HashMap::new();

    h.insert("cd".to_string(), cd as fn(&mut State) -> i32);
    h.insert("ls".to_string(), ls as fn(&mut State) -> i32);
    h.insert("echo".to_string(), echo as fn(&mut State) -> i32);
    h.insert("set".to_string(), set as fn(&mut State) -> i32);
    h.insert("unset".to_string(), unset as fn(&mut State) -> i32);
    h.insert("get".to_string(), get as fn(&mut State) -> i32);

    h
}

fn cd(s: &mut State) -> i32 {
    match s.argv.get(1) {
        Some(x) => {
            let new_path = PathBuf::from(x);

            if new_path.has_root() {
                s.cwd = new_path;
                return 0;
            }

            match utils::make_absolute(new_path) {
                Ok(p) => s.cwd = p,
                Err(e) => {
                    println!("cd: {}", e);
                    return 1;
                }
            };

            0
        }
        None => 0,
    }
}

fn ls(s: &mut State) -> i32 {
    if s.argv.len() == 1 {
        list_dir(&s.cwd);
        return 0;
    }

    for d in s.argv.iter() {
        let p = PathBuf::from(d);
        list_dir(&p);
    }

    0
}

fn list_dir(p: &PathBuf) {
    // Cheking if file so we don't do extra processing
    if p.is_file() {
        println!("FILE: {}", p.to_str().unwrap_or("WTF"));
        return;
    }

    // Unwrapping because we know it's a dir, not a file
    for entry in p.read_dir().unwrap() {
        match entry {
            Ok(e) => {
                // TODO replace this unwrap to something safer
                print!("{} ", e.file_name().into_string().unwrap());
            }
            Err(e) => println!("Error: {}", e),
        }
    }

    print!("\n");
}

pub fn echo(s: &mut State) -> i32 {
    if s.argv[1] == "-n" {
        let strings = &s.argv[2..s.argv.len()].join(" ");
        print!("{}", strings);
    } else {
        let strings = &s.argv[1..s.argv.len()].join(" ");
        println!("{}", strings);
    }

    0
}

fn set(s: &mut State) -> i32 {

    let var_name = s.argv.get(1);
    let value = s.argv.get(2);

    if var_name.is_none() || value.is_none() {
        println!("set: not enough arguments to set");
        return 0;
    }

    let var = var_name.unwrap().clone();
    let val = value.unwrap().clone();

    s.variables.insert(var.to_string(), val.to_string());

    0
}

fn unset(s: &mut State) -> i32 {
    match s.argv.get(1) {
        Some(var) => {
            s.variables.remove(var);

            0
        }
        None => {
            println!("unset: not enough arguments");
            1
        }
    }
}

fn get(s: &mut State) -> i32 {
    match s.argv.get(1) {
        Some(var) => {
            s.variables
                .get(var)
                .map(|val| {
                    println!("{}", val);
                });

            0
        }
        None => {
            println!("get: not enough arguments");
            1
        }
    }
}
<commit_msg>wrote unit tests for builtins<commit_after>use std::path::PathBuf;
use std::collections::HashMap;

use rsh::State;
use rsh::utils;

pub type Builtin = fn(&mut State) -> i32;

pub fn load() -> HashMap<String, Builtin> {
    let mut h = HashMap::new();

    h.insert("cd".to_string(), cd as fn(&mut State) -> i32);
    h.insert("ls".to_string(), ls as fn(&mut State) -> i32);
    h.insert("echo".to_string(), echo as fn(&mut State) -> i32);
    h.insert("set".to_string(), set as fn(&mut State) -> i32);
    h.insert("unset".to_string(), unset as fn(&mut State) -> i32);
    h.insert("get".to_string(), get as fn(&mut State) -> i32);

    h
}

fn cd(s: &mut State) -> i32 {
    match s.argv.get(1) {
        Some(x) => {
            let new_path = PathBuf::from(x);

            if new_path.has_root() {
                s.cwd = new_path;
                return 0;
            }

            match utils::make_absolute(new_path) {
                Ok(p) => {
                    if !p.exists() {
                        return 1;
                    }

                    s.cwd = p;
                }
                Err(e) => {
                    println!("cd: {}", e);
                    return 1;
                }
            };

            0
        }
        None => 0,
    }
}

fn ls(s: &mut State) -> i32 {
    if s.argv.len() == 1 {
        list_dir(&s.cwd);
        return 0;
    }

    for d in s.argv.iter() {
        let p = PathBuf::from(d);
        list_dir(&p);
    }

    0
}

fn list_dir(p: &PathBuf) {
    // Cheking if file so we don't do extra processing
    if p.is_file() {
        println!("FILE: {}", p.to_str().unwrap_or("WTF"));
        return;
    }

    // Unwrapping because we know it's a dir, not a file
    for entry in p.read_dir().unwrap() {
        match entry {
            Ok(e) => {
                // TODO replace this unwrap to something safer
                print!("{} ", e.file_name().into_string().unwrap());
            }
            Err(e) => println!("Error: {}", e),
        }
    }

    print!("\n");
}

pub fn echo(s: &mut State) -> i32 {
    if s.argv[1] == "-n" {
        let strings = &s.argv[2..s.argv.len()].join(" ");
        print!("{}", strings);
    } else {
        let strings = &s.argv[1..s.argv.len()].join(" ");
        println!("{}", strings);
    }

    0
}

fn set(s: &mut State) -> i32 {

    let var_name = s.argv.get(1);
    let value = s.argv.get(2);

    if var_name.is_none() || value.is_none() {
        println!("set: not enough arguments to set");
        return 0;
    }

    let var = var_name.unwrap().clone();
    let val = value.unwrap().clone();

    s.variables.insert(var.to_string(), val.to_string());

    0
}

fn unset(s: &mut State) -> i32 {
    match s.argv.get(1) {
        Some(var) => {
            s.variables.remove(var);
            0
        }
        None => {
            println!("unset: not enough arguments");
            1
        }
    }
}

fn get(s: &mut State) -> i32 {
    match s.argv.get(1) {
        Some(var) => {
            s.variables
                .get(var)
                .map(|val| {
                    println!("{}", val);
                });

            0
        }
        None => {
            println!("get: not enough arguments");
            1
        }
    }
}

// TODO make these tests better once we can capture stdout
#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_cd() {
        let mut s = State::default();
        s.argv = vec!["cd".to_string(), "/".to_string()];

        let i = cd(&mut s);

        assert_eq!(i, 0);
        assert_eq!(s.cwd.to_str().unwrap(), "/");
    }

    #[test]
    #[should_panic]
    fn test_cd_bad_path() {
        let mut s = State::default();
        s.argv = vec!["cd".to_string(), "/123".to_string()];

        let i = cd(&mut s);

        assert_eq!(i, 0);
    }

    #[test]
    fn test_set() {
        let mut s = State::default();
        s.argv = vec!["set".to_string(), "test".to_string(), "hello world".to_string()];

        let i = set(&mut s);

        assert_eq!(i, 0);
        assert_eq!(s.variables.get("test").unwrap(), "hello world");
    }

    #[test]
    fn test_unset() {
        let mut s = State::default();
        s.variables.insert("test".to_string(), "hello world".to_string());
        s.argv = vec!["unset".to_string(), "test".to_string()];

        let i = unset(&mut s);

        assert_eq!(i, 0);
        assert_eq!(s.variables.get("test"), None);
    }

    #[test]
    fn test_get() {
        let mut s = State::default();
        s.variables.insert("test".to_string(), "hello world".to_string());
        s.argv = vec!["get".to_string(), "test".to_string()];

        let i = get(&mut s);

        assert_eq!(i, 0);
    }

    #[test]
    #[should_panic]
    fn test_get_failure() {
        let mut s = State::default();
        s.argv = vec!["get".to_string(), "test".to_string()];

        let i = get(&mut s);

        assert_eq!(i, 0);
    }

    #[test]
    fn test_ls() {
        let mut s = State::default();
        s.argv = vec!["ls".to_string()];

        let i = ls(&mut s);

        assert_eq!(i, 0);
    }

    #[test]
    fn test_echo() {
        let mut s = State::default();
        s.argv = vec!["echo".to_string(), "\"Hello world!\"".to_string()];

        let i = get(&mut s);

        assert_eq!(i, 0);
    }
}
<|endoftext|>


<commit_before>use std::io::Write;
use std::default::Default;

use termion::{clear, style, cursor};

use cursor::Cursor;
use errors::*;

fn _return_true() -> bool {
    true
}

#[derive(Deserialize, Debug, PartialEq, Clone)]
pub struct Line {
    pub text: Option<String>,
    #[serde(rename="cursor")]
    pub cursors: Option<Vec<u16>>,
    pub styles: Option<Vec<i64>>,
    #[serde(default="_return_true")]
    #[serde(skip_deserializing)]
    pub is_valid: bool,
}

impl Default for Line {
    fn default() -> Line {
        Line {
            text: None,
            cursors: None,
            styles: None,
            is_valid: true,
        }
    }
}

impl Line {
    /// Insert the cursors and handle styles (not implemented yet)
    pub fn render<W: Write>(&self, w: &mut W, lineno: u16, cursor: Option<&Cursor>) -> Result<()> {
        let mut line = self.text
                           .as_ref()
                           .map(|s| s.clone())
                           .unwrap_or(String::new());

        // Draw "fake" cursors. we have only one "real" cursor in a terminal so we render the
        // others manually by inserting escape sequences in the string.
        if let Some(ref cursors) = self.cursors {
            // We need to keep track of the escape sequences we add, since they count as 1
            // character and change the indices. One solution to avoid that would be to insert them
            // right to left.
            let mut offset: usize = 0;

            for idx in cursors {
                // If this cursor is the real cursor we don't want to draw it.
                // We skip it, and the cursor will be set here later.
                if let Some(real_cursor) = cursor {
                    if real_cursor.column == *idx {
                        continue;
                    }
                }

                // Make sure the cursor is within the bounds of the string. It *should* be the case
                // after padding, assuming the core sends correct updates, but better be safe than
                // sorry. Note that padding is necessary for cases where the cursor is at the end
                // of the line.
                self.pad(&mut line);
                let idx = offset + *idx as usize;
                if idx + 1 > line.len() {
                    error!(
                        "Cannot set cursor: cursor index {} is bigger than line length ({})",
                        idx,
                        line.len());
                    bail!(ErrorKind::DisplayError);
                }

                // Insert the "cursor".
                line.insert_str(idx + 1, &format!("{}", style::Reset));
                line.insert_str(idx, &format!("{}", style::Invert));
                offset += 2;
            }
        }
        write!(w, "{}{}{}", cursor::Goto(1, lineno), line, clear::AfterCursor)
            .chain_err(|| ErrorKind::DisplayError)?;
        w.flush().chain_err(|| ErrorKind::DisplayError)?;
        Ok(())
    }

    fn pad(&self, text: &mut String) {
        if let Some('\n') = text.chars().last() {
            text.pop();
            text.push_str(" \n");
        } else {
            text.push(' ');
        }
    }
}
<commit_msg>when rendering a line clear it then write it<commit_after>use std::io::Write;
use std::default::Default;

use termion::{clear, style, cursor};

use cursor::Cursor;
use errors::*;

fn _return_true() -> bool {
    true
}

#[derive(Deserialize, Debug, PartialEq, Clone)]
pub struct Line {
    pub text: Option<String>,
    #[serde(rename="cursor")]
    pub cursors: Option<Vec<u16>>,
    pub styles: Option<Vec<i64>>,
    #[serde(default="_return_true")]
    #[serde(skip_deserializing)]
    pub is_valid: bool,
}

impl Default for Line {
    fn default() -> Line {
        Line {
            text: None,
            cursors: None,
            styles: None,
            is_valid: true,
        }
    }
}

impl Line {
    /// Insert the cursors and handle styles (not implemented yet)
    pub fn render<W: Write>(&self, w: &mut W, lineno: u16, cursor: Option<&Cursor>) -> Result<()> {
        let mut line = self.text
                           .as_ref()
                           .map(|s| s.clone())
                           .unwrap_or(String::new());

        // Draw "fake" cursors. we have only one "real" cursor in a terminal so we render the
        // others manually by inserting escape sequences in the string.
        if let Some(ref cursors) = self.cursors {
            // We need to keep track of the escape sequences we add, since they count as 1
            // character and change the indices. One solution to avoid that would be to insert them
            // right to left.
            let mut offset: usize = 0;

            for idx in cursors {
                // If this cursor is the real cursor we don't want to draw it.
                // We skip it, and the cursor will be set here later.
                if let Some(real_cursor) = cursor {
                    if real_cursor.column == *idx {
                        continue;
                    }
                }

                // Make sure the cursor is within the bounds of the string. It *should* be the case
                // after padding, assuming the core sends correct updates, but better be safe than
                // sorry. Note that padding is necessary for cases where the cursor is at the end
                // of the line.
                self.pad(&mut line);
                let idx = offset + *idx as usize;
                if idx + 1 > line.len() {
                    error!(
                        "Cannot set cursor: cursor index {} is bigger than line length ({})",
                        idx,
                        line.len());
                    bail!(ErrorKind::DisplayError);
                }

                // Insert the "cursor".
                line.insert_str(idx + 1, &format!("{}", style::Reset));
                line.insert_str(idx, &format!("{}", style::Invert));
                offset += 2;
            }
        }
        write!(w, "{}{}{}", cursor::Goto(1, lineno), clear::CurrentLine, line)
            .chain_err(|| ErrorKind::DisplayError)?;
        w.flush().chain_err(|| ErrorKind::DisplayError)?;
        Ok(())
    }

    fn pad(&self, text: &mut String) {
        if let Some('\n') = text.chars().last() {
            text.pop();
            text.push_str(" \n");
        } else {
            text.push(' ');
        }
    }
}
<|endoftext|>


<commit_before>//! Draw Line

use current::{ Get, Modifier, Set };
use internal;
use triangulation;
use BackEnd;
use Context;
use ImageSize;
use Color;

/// The shape of the line
pub enum Shape {
    /// Square edges
    Square,
    /// Round edges
    Round,
    /// Bevel edges
    Bevel,
}

/// Wrapper trait for `Get<Shape>`
pub trait GetShape: Get<Shape> {
    /// Get shape
    #[inline(always)]
    fn get_shape(&self) -> Shape {
        self.get()
    }
}

impl<T: Get<Shape>> GetShape for T {}

/// Wrapper trait for `Set<Shape>`
pub trait SetShape: Set<Shape> {
    /// Set shape
    #[inline(always)]
    fn set_shape(&mut self, val: Shape) {
        self.set_mut(val);
    }
}

impl<T: Set<Shape>> SetShape for T {}

/// The line border radius
pub struct Radius(pub internal::Radius);

/// Wrapper trait for `Get<Radius>`
pub trait GetRadius: Get<Radius> {
    /// Get radius
    #[inline(always)]
    fn get_radius(&self) -> Radius {
        self.get()
    }
}

impl<T: Get<Radius>> GetRadius for T {}

/// Wrapper trait for `Set<Radius>`
pub trait SetRadius: Set<Radius> {
    /// Set radius
    #[inline(always)]
    fn set_radius(&mut self, val: Radius) {
        self.set_mut(val);
    }
}

impl<T: Set<Radius>> SetRadius for T {}

/// A colored line with a default border radius
#[deriving(Copy)]
pub struct Line {
    /// The line color
    pub color: internal::Color,
    /// The line radius
    pub radius: internal::Radius,
    /// The line shape
    pub shape: Shape,
}

impl Line {
    /// Creates a new line
    pub fn new(color: internal::Color, radius: internal::Radius) -> Line {
        Line {
            color: color,
            radius: radius,
            shape: Shape::Square,
        }
    }

    /// Draw the line.
    pub fn draw<B: BackEnd<I>, I: ImageSize>(
        &self,
        line: internal::Line,
        c: &Context,
        back_end: &mut B
    ) {
        // Complete transparency does not need to be rendered.
        if self.color[3] == 0.0 { return; }
        back_end.color(self.color);
        match self.shape {
            Shape::Square => {
                triangulation::with_round_border_line_tri_list(
                    2,
                    c.transform,
                    line,
                    self.radius,
                    |vertices| back_end.tri_list(vertices)
                );
            }
            Shape::Round => {
                triangulation::with_round_border_line_tri_list(
                    64,
                    c.transform,
                    line,
                    self.radius,
                    |vertices| back_end.tri_list(vertices)
                );
            }
            Shape::Bevel => {
                triangulation::with_round_border_line_tri_list(
                    3,
                    c.transform,
                    line,
                    self.radius,
                    |vertices| back_end.tri_list(vertices)
                );
            }
        }
    }
}

impl Modifier<Line> for Color {
    fn modify(self, l: &mut Line) {
        let Color(val) = self;
        l.color = val;
    }
}

impl Modifier<Line> for Radius {
    fn modify(self, l: &mut Line) {
        let Radius(val) = self;
        l.radius = val;
    }
}

impl Modifier<Line> for Shape {
    fn modify(self, l: &mut Line) {
        l.shape = self;
    }
}

#[cfg(test)]
mod test {
    use current::Set;
    use super::Line;
    use super::Shape;
    use super::Radius;
    use Color;

    #[test]
    fn test_line() {
        let _line = Line::new([0.0, ..4], 3.0)
            .set(Color([1.0, ..4]))
            .set(Radius(3.0))
            .set(Shape::Round);
    }
}
<commit_msg>Implemented `Get` for Line<commit_after>//! Draw Line

use current::{ Get, Modifier, Set };
use internal;
use triangulation;
use BackEnd;
use Context;
use ImageSize;
use Color;

/// The shape of the line
pub enum Shape {
    /// Square edges
    Square,
    /// Round edges
    Round,
    /// Bevel edges
    Bevel,
}

/// Wrapper trait for `Get<Shape>`
pub trait GetShape: Get<Shape> {
    /// Get shape
    #[inline(always)]
    fn get_shape(&self) -> Shape {
        self.get()
    }
}

impl<T: Get<Shape>> GetShape for T {}

/// Wrapper trait for `Set<Shape>`
pub trait SetShape: Set<Shape> {
    /// Set shape
    #[inline(always)]
    fn set_shape(&mut self, val: Shape) {
        self.set_mut(val);
    }
}

impl<T: Set<Shape>> SetShape for T {}

/// The line border radius
pub struct Radius(pub internal::Radius);

/// Wrapper trait for `Get<Radius>`
pub trait GetRadius: Get<Radius> {
    /// Get radius
    #[inline(always)]
    fn get_radius(&self) -> Radius {
        self.get()
    }
}

impl<T: Get<Radius>> GetRadius for T {}

/// Wrapper trait for `Set<Radius>`
pub trait SetRadius: Set<Radius> {
    /// Set radius
    #[inline(always)]
    fn set_radius(&mut self, val: Radius) {
        self.set_mut(val);
    }
}

impl<T: Set<Radius>> SetRadius for T {}

/// A colored line with a default border radius
#[deriving(Copy)]
pub struct Line {
    /// The line color
    pub color: internal::Color,
    /// The line radius
    pub radius: internal::Radius,
    /// The line shape
    pub shape: Shape,
}

impl Line {
    /// Creates a new line
    pub fn new(color: internal::Color, radius: internal::Radius) -> Line {
        Line {
            color: color,
            radius: radius,
            shape: Shape::Square,
        }
    }

    /// Draw the line.
    pub fn draw<B: BackEnd<I>, I: ImageSize>(
        &self,
        line: internal::Line,
        c: &Context,
        back_end: &mut B
    ) {
        // Complete transparency does not need to be rendered.
        if self.color[3] == 0.0 { return; }
        back_end.color(self.color);
        match self.shape {
            Shape::Square => {
                triangulation::with_round_border_line_tri_list(
                    2,
                    c.transform,
                    line,
                    self.radius,
                    |vertices| back_end.tri_list(vertices)
                );
            }
            Shape::Round => {
                triangulation::with_round_border_line_tri_list(
                    64,
                    c.transform,
                    line,
                    self.radius,
                    |vertices| back_end.tri_list(vertices)
                );
            }
            Shape::Bevel => {
                triangulation::with_round_border_line_tri_list(
                    3,
                    c.transform,
                    line,
                    self.radius,
                    |vertices| back_end.tri_list(vertices)
                );
            }
        }
    }
}

impl Modifier<Line> for Color {
    #[inline(always)]
    fn modify(self, l: &mut Line) {
        let Color(val) = self;
        l.color = val;
    }
}

impl Get<Color> for Line {
    #[inline(always)]
    fn get(&self) -> Color {
        Color(self.color)
    }
}

impl Modifier<Line> for Radius {
    #[inline(always)]
    fn modify(self, l: &mut Line) {
        let Radius(val) = self;
        l.radius = val;
    }
}

impl Get<Radius> for Line {
    #[inline(always)]
    fn get(&self) -> Radius {
        Radius(self.radius)
    }
}

impl Modifier<Line> for Shape {
    #[inline(always)]
    fn modify(self, l: &mut Line) {
        l.shape = self;
    }
}

impl Get<Shape> for Line {
    #[inline(always)]
    fn get(&self) -> Shape {
        self.shape
    }
}

#[cfg(test)]
mod test {
    use current::Set;
    use super::Line;
    use super::Shape;
    use super::Radius;
    use Color;

    #[test]
    fn test_line() {
        let _line = Line::new([0.0, ..4], 3.0)
            .set(Color([1.0, ..4]))
            .set(Radius(3.0))
            .set(Shape::Round);
    }
}
<|endoftext|>


<commit_before>use events::{Event, EventHandler};
use formatter::formatter::Formatter;
use runner;
use std::io;

pub struct Simple<'a, Io: io::Write + 'a> {
    buf: &'a mut Io,
    pub name_stack: Vec<String>,
    pub failures: Vec<String>,
}

impl<'a, T: io::Write> Simple<'a, T> {
    pub fn new(buf: &mut T) -> Simple<T> {
        Simple {
            buf: buf,
            name_stack: vec![],
            failures: vec![],
        }
    }

    fn failures_summary(&self) -> String {
        let res = String::with_capacity(100);
        let mut idx = 0;
        self.failures.iter()
                     .map(|fail| {
                         idx += 1;
                         format!("  {}) {}\n", idx, fail)
                     })
                     .fold(res, |mut acc, elt| {
                        acc.push_str(&elt);
                        acc
                     })
    }

    fn write_summary(&mut self, result: runner::RunnerResult) -> Result<(), io::Error> {
        let (res, report) = match result {
            Ok(report) => ("ok", report),
            Err(report) => ("FAILED", report),
        };

        writeln!(self.buf,
                 "\n\ntest result: {}. {} examples; {} passed; {} failed;",
                 res,
                 report.total_tests,
                 report.success_count,
                 report.error_count)
    }
}

impl<'a, T: io::Write> EventHandler for Simple<'a, T> {
    fn trigger(&mut self, event: &Event) {
        // FIXME: do something with the io::Error ?
        let _ = match *event {
            Event::StartRunner => writeln!(self.buf, "Running tests:\n"),
            Event::StartDescribe(ref name) |
            Event::StartTest(ref name) => {
                self.name_stack.push(name.clone());
                Ok(())
            }
            Event::EndTest(result) => {
                if !self.name_stack.is_empty() {
                    let failure_name = self.name_stack.join(" | ");
                    self.failures.push(failure_name);
                    self.name_stack.pop();
                }
                let chr = if result.is_ok() {
                    "."
                } else {
                    "F"
                };
                write!(self.buf, "{}", chr)
            }
            Event::FinishedRunner(result) => self.write_summary(result),
            Event::EndDescribe => {
                self.name_stack.pop();
                Ok(())
            }
            // _ => Ok(()),
        };
    }
}
impl<'a, T: io::Write> Formatter for Simple<'a, T> {}

#[cfg(test)]
mod tests {
    pub use super::*;
    pub use formatter::formatter::Formatter;
    pub use events::{Event, EventHandler};
    pub use std::io;
    pub use std::str;

    #[test]
    fn it_can_be_instanciated() {
        Simple::new(&mut vec![1u8]);
    }

    #[test]
    fn it_impl_formatter_trait() {
        let _: &Formatter = &Simple::new(&mut vec![1u8]) as &Formatter;
    }

    mod event_start_runner {
        pub use super::*;

        #[test]
        fn it_display_that_tests_started() {
            let mut v = vec![];
            {
                let mut s = Simple::new(&mut v);
                s.trigger(&Event::StartRunner);
            }

            assert_eq!("Running tests:\n\n", str::from_utf8(&v).unwrap());
        }
    }

    mod event_finished_runner {
        pub use super::*;
        use runner::TestReport;

        fn make_report(succes: u32, errors: u32) -> Result<TestReport, TestReport> {
            let mut report = TestReport::default();
            report.success_count = succes;
            report.error_count = errors;
            report.total_tests = succes + errors;

            if errors != 0 {
                Err(report)
            } else {
                Ok(report)
            }
        }

        macro_rules! test_and_compare_output {
            ($(
                $test_name:ident : (success: $succ:expr, errors: $err:expr) => $msg:expr
            ),+) => {

                $(
                    #[test]
                    fn $test_name() {
                        let mut v = vec!();
                        {
                            let mut s = Simple::new(&mut v);
                            s.trigger(&Event::FinishedRunner(make_report($succ, $err)))
                        }

                        assert_eq!($msg, str::from_utf8(&v).unwrap())
                    }
                )+
            }
        }

        test_and_compare_output! {
            no_test_is_ok: (success: 0, errors: 0) =>
                "\n\ntest result: ok. 0 examples; 0 passed; 0 failed;\n",
            one_test: (success: 1, errors: 0) =>
                "\n\ntest result: ok. 1 examples; 1 passed; 0 failed;\n",
            multiple_ok: (success: 42, errors: 0) =>
                "\n\ntest result: ok. 42 examples; 42 passed; 0 failed;\n",
            one_error: (success: 0, errors: 1) =>
              "\n\ntest result: FAILED. 1 examples; 0 passed; 1 failed;\n",
            multiple_errors: (success: 0, errors: 37) =>
              "\n\ntest result: FAILED. 37 examples; 0 passed; 37 failed;\n",
            one_of_each: (success: 1, errors: 1) =>
              "\n\ntest result: FAILED. 2 examples; 1 passed; 1 failed;\n",
            multiple_of_each: (success: 12, errors: 21) =>
              "\n\ntest result: FAILED. 33 examples; 12 passed; 21 failed;\n"
        }
    }

    mod event_end_test {
        pub use super::*;

        #[test]
        fn it_displays_a_dot_when_success() {
            let mut v = vec![];
            {
                let mut s = Simple::new(&mut v);
                s.trigger(&Event::EndTest(Ok(())));
            }

            assert_eq!(".", str::from_utf8(&v).unwrap());
        }

        #[test]
        #[allow(non_snake_case)]
        fn it_displays_a_F_when_error() {
            let mut v = vec![];
            {
                let mut s = Simple::new(&mut v);
                s.trigger(&Event::EndTest(Err(())));
            }

            assert_eq!("F", str::from_utf8(&v).unwrap());
        }
    }

    mod event_start_end_describe {
        pub use super::*;

        #[test]
        fn start_describe_event_push_the_name_stack() {
            let mut sink = &mut io::sink();
            let mut s = Simple::new(&mut sink);

            s.trigger(&Event::StartDescribe(String::from("Hey !")));
            assert_eq!(vec![String::from("Hey !")], s.name_stack);

            s.trigger(&Event::StartDescribe(String::from("Ho !")));
            assert_eq!(vec![String::from("Hey !"), String::from("Ho !")],
                       s.name_stack)
        }

        #[test]
        fn end_describe_event_pop_the_name_stack() {
            let mut sink = &mut io::sink();
            let mut s = Simple::new(&mut sink);

            s.trigger(&Event::StartDescribe(String::from("Hey !")));
            s.trigger(&Event::StartDescribe(String::from("Ho !")));

            s.trigger(&Event::EndDescribe);
            assert_eq!(vec![String::from("Hey !")], s.name_stack);

            s.trigger(&Event::EndDescribe);
            assert_eq!(0, s.name_stack.len());
        }
    }

    mod failures_pretty_printing {
        use super::*;

        #[test]
        fn it_register_failures() {
            let mut sink = &mut io::sink();
            let mut s = Simple::new(&mut sink);
            s.trigger(&Event::StartTest("hola".into()));
            s.trigger(&Event::EndTest(Err(())));
            assert_eq!(1, s.failures.len());
        }

        #[test]
        fn it_keep_track_of_the_failure_name() {
            let mut sink = &mut io::sink();
            let mut s = Simple::new(&mut sink);
            s.trigger(&Event::StartTest("hola".into()));
            s.trigger(&Event::EndTest(Err(())));
            assert_eq!(Some(&"hola".into()), s.failures.get(0));
        }

        #[test]
        fn it_has_a_nice_diplay_for_describes() {
            let mut sink = &mut io::sink();
            let mut s = Simple::new(&mut sink);
            s.trigger(&Event::StartDescribe("hola".into()));
            s.trigger(&Event::StartTest("holé".into()));
            s.trigger(&Event::EndTest(Err(())));
            assert_eq!(Some(&"hola | holé".into()), s.failures.get(0));

            s.trigger(&Event::StartDescribe("ohééé".into()));
            s.trigger(&Event::StartTest("holé".into()));
            s.trigger(&Event::EndTest(Err(())));
            assert_eq!(Some(&"hola | ohééé | holé".into()), s.failures.get(1));
        }

        #[test]
        fn it_works_with_multiple_describes() {
            let mut sink = &mut io::sink();
            let mut s = Simple::new(&mut sink);
            s.trigger(&Event::StartDescribe("hola".into()));
            s.trigger(&Event::StartTest("holé".into()));
            s.trigger(&Event::EndTest(Err(())));

            s.trigger(&Event::EndDescribe);
            s.trigger(&Event::StartDescribe("ok".into()));
            s.trigger(&Event::StartTest("cacao".into()));
            s.trigger(&Event::EndTest(Err(())));
            assert_eq!(Some(&"ok | cacao".into()), s.failures.get(1));
        }

        // test the correct formating of one failure
        #[test]
        fn format_all_failures_one_error() {
            let mut buf = vec!();
            let res = {
                let mut s = Simple::new(&mut buf);
                s.trigger(&Event::StartDescribe("hola".into()));
                s.trigger(&Event::StartTest("holé".into()));
                s.trigger(&Event::EndTest(Err(())));
                s.failures_summary()
            };

            assert_eq!("  1) hola | holé\n", res);
        }
        #[test]
        fn format_all_failures() {
            let mut buf = vec!();
            let res = {
                let mut s = Simple::new(&mut buf);
                s.trigger(&Event::StartDescribe("hola".into()));
                s.trigger(&Event::StartTest("holé".into()));
                s.trigger(&Event::EndTest(Err(())));
                s.trigger(&Event::StartTest("hola".into()));
                s.trigger(&Event::EndTest(Err(())));
                s.failures_summary()
            };

            assert_eq!("  1) hola | holé\n  2) hola | hola\n", res);

            let res = {
                let mut s = Simple::new(&mut buf);
                s.trigger(&Event::StartDescribe("hola".into()));
                s.trigger(&Event::StartTest("holé".into()));
                s.trigger(&Event::EndTest(Err(())));
                s.trigger(&Event::EndDescribe);
                s.trigger(&Event::StartDescribe("second".into()));
                s.trigger(&Event::StartDescribe("third".into()));
                s.trigger(&Event::StartTest("hola".into()));
                s.trigger(&Event::EndTest(Err(())));
                s.failures_summary()
            };

            assert_eq!("  1) hola | holé\n  2) second | third | hola\n", res);
        }
    }
}
<commit_msg> cargo fmt + refactor Simple::write_summary tests<commit_after>use events::{Event, EventHandler};
use formatter::formatter::Formatter;
use runner;
use std::io;

pub struct Simple<'a, Io: io::Write + 'a> {
    buf: &'a mut Io,
    pub name_stack: Vec<String>,
    pub failures: Vec<String>,
}

impl<'a, T: io::Write> Simple<'a, T> {
    pub fn new(buf: &mut T) -> Simple<T> {
        Simple {
            buf: buf,
            name_stack: vec![],
            failures: vec![],
        }
    }

    fn failures_summary(&self) -> String {
        let res = String::with_capacity(100);
        let mut idx = 0;
        self.failures
            .iter()
            .map(|fail| {
                idx += 1;
                format!("  {}) {}\n", idx, fail)
            })
            .fold(res, |mut acc, elt| {
                acc.push_str(&elt);
                acc
            })
    }

    fn write_summary(&mut self, result: runner::RunnerResult) -> String {
        let (res, report) = match result {
            Ok(report) => ("ok", report),
            Err(report) => ("FAILED", report),
        };

        format!("\n\ntest result: {}. {} examples; {} passed; {} failed;",
                res,
                report.total_tests,
                report.success_count,
                report.error_count)
    }
}

impl<'a, T: io::Write> EventHandler for Simple<'a, T> {
    fn trigger(&mut self, event: &Event) {
        // FIXME: do something with the io::Error ?
        let _ = match *event {
            Event::StartRunner => writeln!(self.buf, "Running tests:\n"),
            Event::StartDescribe(ref name) |
            Event::StartTest(ref name) => {
                self.name_stack.push(name.clone());
                Ok(())
            }
            Event::EndTest(result) => {
                if !self.name_stack.is_empty() {
                    let failure_name = self.name_stack.join(" | ");
                    self.failures.push(failure_name);
                    self.name_stack.pop();
                }
                let chr = if result.is_ok() {
                    "."
                } else {
                    "F"
                };
                write!(self.buf, "{}", chr)
            }
            Event::FinishedRunner(result) => {
                let res = self.write_summary(result);
                writeln!(self.buf, "{}", res)
            }
            Event::EndDescribe => {
                self.name_stack.pop();
                Ok(())
            }
            // _ => Ok(()),
        };
    }
}
impl<'a, T: io::Write> Formatter for Simple<'a, T> {}

#[cfg(test)]
mod tests {
    pub use super::*;
    pub use formatter::formatter::Formatter;
    pub use events::{Event, EventHandler};
    pub use std::io;
    pub use std::str;

    #[test]
    fn it_can_be_instanciated() {
        Simple::new(&mut vec![1u8]);
    }

    #[test]
    fn it_impl_formatter_trait() {
        let _: &Formatter = &Simple::new(&mut vec![1u8]) as &Formatter;
    }

    mod event_start_runner {
        pub use super::*;

        #[test]
        fn it_display_that_tests_started() {
            let mut v = vec![];
            {
                let mut s = Simple::new(&mut v);
                s.trigger(&Event::StartRunner);
            }

            assert_eq!("Running tests:\n\n", str::from_utf8(&v).unwrap());
        }
    }

    mod event_finished_runner {
        pub use super::*;
        use runner::TestReport;

        fn make_report(succes: u32, errors: u32) -> Result<TestReport, TestReport> {
            let mut report = TestReport::default();
            report.success_count = succes;
            report.error_count = errors;
            report.total_tests = succes + errors;

            if errors != 0 {
                Err(report)
            } else {
                Ok(report)
            }
        }

        macro_rules! test_and_compare_output {
            ($(
                $test_name:ident : (success: $succ:expr, errors: $err:expr) => $msg:expr
            ),+) => {

                $(
                    #[test]
                    fn $test_name() {
                        let mut sink = io::sink();
                        let res = {
                            let mut s = Simple::new(&mut sink);
                            s.write_summary(make_report($succ, $err))
                        };

                        assert_eq!($msg, res)
                    }
                )+
            }
        }

        test_and_compare_output! {
            no_test_is_ok: (success: 0, errors: 0) =>
                "\n\ntest result: ok. 0 examples; 0 passed; 0 failed;",
            one_test: (success: 1, errors: 0) =>
                "\n\ntest result: ok. 1 examples; 1 passed; 0 failed;",
            multiple_ok: (success: 42, errors: 0) =>
                "\n\ntest result: ok. 42 examples; 42 passed; 0 failed;",
            one_error: (success: 0, errors: 1) =>
              "\n\ntest result: FAILED. 1 examples; 0 passed; 1 failed;",
            multiple_errors: (success: 0, errors: 37) =>
              "\n\ntest result: FAILED. 37 examples; 0 passed; 37 failed;",
            one_of_each: (success: 1, errors: 1) =>
              "\n\ntest result: FAILED. 2 examples; 1 passed; 1 failed;",
            multiple_of_each: (success: 12, errors: 21) =>
              "\n\ntest result: FAILED. 33 examples; 12 passed; 21 failed;"
        }
    }

    mod event_end_test {
        pub use super::*;

        #[test]
        fn it_displays_a_dot_when_success() {
            let mut v = vec![];
            {
                let mut s = Simple::new(&mut v);
                s.trigger(&Event::EndTest(Ok(())));
            }

            assert_eq!(".", str::from_utf8(&v).unwrap());
        }

        #[test]
        #[allow(non_snake_case)]
        fn it_displays_a_F_when_error() {
            let mut v = vec![];
            {
                let mut s = Simple::new(&mut v);
                s.trigger(&Event::EndTest(Err(())));
            }

            assert_eq!("F", str::from_utf8(&v).unwrap());
        }
    }

    mod event_start_end_describe {
        pub use super::*;

        #[test]
        fn start_describe_event_push_the_name_stack() {
            let mut sink = &mut io::sink();
            let mut s = Simple::new(&mut sink);

            s.trigger(&Event::StartDescribe(String::from("Hey !")));
            assert_eq!(vec![String::from("Hey !")], s.name_stack);

            s.trigger(&Event::StartDescribe(String::from("Ho !")));
            assert_eq!(vec![String::from("Hey !"), String::from("Ho !")],
                       s.name_stack)
        }

        #[test]
        fn end_describe_event_pop_the_name_stack() {
            let mut sink = &mut io::sink();
            let mut s = Simple::new(&mut sink);

            s.trigger(&Event::StartDescribe(String::from("Hey !")));
            s.trigger(&Event::StartDescribe(String::from("Ho !")));

            s.trigger(&Event::EndDescribe);
            assert_eq!(vec![String::from("Hey !")], s.name_stack);

            s.trigger(&Event::EndDescribe);
            assert_eq!(0, s.name_stack.len());
        }
    }

    mod failures_pretty_printing {
        use super::*;

        #[test]
        fn it_register_failures() {
            let mut sink = &mut io::sink();
            let mut s = Simple::new(&mut sink);
            s.trigger(&Event::StartTest("hola".into()));
            s.trigger(&Event::EndTest(Err(())));
            assert_eq!(1, s.failures.len());
        }

        #[test]
        fn it_keep_track_of_the_failure_name() {
            let mut sink = &mut io::sink();
            let mut s = Simple::new(&mut sink);
            s.trigger(&Event::StartTest("hola".into()));
            s.trigger(&Event::EndTest(Err(())));
            assert_eq!(Some(&"hola".into()), s.failures.get(0));
        }

        #[test]
        fn it_has_a_nice_diplay_for_describes() {
            let mut sink = &mut io::sink();
            let mut s = Simple::new(&mut sink);
            s.trigger(&Event::StartDescribe("hola".into()));
            s.trigger(&Event::StartTest("holé".into()));
            s.trigger(&Event::EndTest(Err(())));
            assert_eq!(Some(&"hola | holé".into()), s.failures.get(0));

            s.trigger(&Event::StartDescribe("ohééé".into()));
            s.trigger(&Event::StartTest("holé".into()));
            s.trigger(&Event::EndTest(Err(())));
            assert_eq!(Some(&"hola | ohééé | holé".into()), s.failures.get(1));
        }

        #[test]
        fn it_works_with_multiple_describes() {
            let mut sink = &mut io::sink();
            let mut s = Simple::new(&mut sink);
            s.trigger(&Event::StartDescribe("hola".into()));
            s.trigger(&Event::StartTest("holé".into()));
            s.trigger(&Event::EndTest(Err(())));

            s.trigger(&Event::EndDescribe);
            s.trigger(&Event::StartDescribe("ok".into()));
            s.trigger(&Event::StartTest("cacao".into()));
            s.trigger(&Event::EndTest(Err(())));
            assert_eq!(Some(&"ok | cacao".into()), s.failures.get(1));
        }

        #[test]
        fn format_all_failures_one_error() {
            let mut buf = vec![];
            let res = {
                let mut s = Simple::new(&mut buf);
                s.trigger(&Event::StartDescribe("hola".into()));
                s.trigger(&Event::StartTest("holé".into()));
                s.trigger(&Event::EndTest(Err(())));
                s.failures_summary()
            };

            assert_eq!("  1) hola | holé\n", res);
        }

        #[test]
        fn format_all_failures() {
            let mut buf = vec![];
            let res = {
                let mut s = Simple::new(&mut buf);
                s.trigger(&Event::StartDescribe("hola".into()));
                s.trigger(&Event::StartTest("holé".into()));
                s.trigger(&Event::EndTest(Err(())));
                s.trigger(&Event::StartTest("hola".into()));
                s.trigger(&Event::EndTest(Err(())));
                s.failures_summary()
            };

            assert_eq!("  1) hola | holé\n  2) hola | hola\n", res);

            let res = {
                let mut s = Simple::new(&mut buf);
                s.trigger(&Event::StartDescribe("hola".into()));
                s.trigger(&Event::StartTest("holé".into()));
                s.trigger(&Event::EndTest(Err(())));
                s.trigger(&Event::EndDescribe);
                s.trigger(&Event::StartDescribe("second".into()));
                s.trigger(&Event::StartDescribe("third".into()));
                s.trigger(&Event::StartTest("hola".into()));
                s.trigger(&Event::EndTest(Err(())));
                s.failures_summary()
            };

            assert_eq!("  1) hola | holé\n  2) second | third | hola\n", res);
        }
    }
}
<|endoftext|>


<commit_before>/// Implement ncurses-compatible database discovery

use core::os::getenv;
use core::str;
use path = core::path::PosixPath;

/// Return path to database entry for `term`
pub fn get_dbpath_for_term(term: &str) -> Option<~path> {
    let mut dirs_to_search = ~[];
    let first_char = term.substr(0, 1);

    // Find search directory
    match getenv(~"TERMINFO") {
        Some(dir) => dirs_to_search.push(path(dir)),
        None => {
            match getenv(~"TERMINFO_DIRS") {
                Some(dirs) => for str::each_split_char(dirs, ':') |i| {
                    if i == ~"" {
                        dirs_to_search.push(path(~"/usr/share/terminfo"));
                    } else {
                        dirs_to_search.push(path(i.to_owned()));
                    }
                },
                // Found nothing, use the default path
                None => dirs_to_search.push(path(~"/usr/share/terminfo"))
            }
        }
    };

    // Look for the terminal in all of the search directories
    for dirs_to_search.each |p| {
        let newp = ~p.push_many(&[first_char.to_owned(), term.to_owned()]);
        if os::path_exists(p) && os::path_exists(newp) {
            return Some(newp);
        }
    }
    None
}

#[test]
fn test_get_dbpath_for_term() {
    // woefully inadequate test coverage
    use x = self::get_dbpath_for_term;
    assert!(x("screen").unwrap().to_str() == ~"/usr/share/terminfo/s/screen");
}
<commit_msg>More tests for the searcher<commit_after>/// Implement ncurses-compatible database discovery

use core::os::getenv;
use core::str;
use path = core::path::PosixPath;

/// Return path to database entry for `term`
pub fn get_dbpath_for_term(term: &str) -> Option<~path> {
    if term.len() == 0 {
        return None;
    }

    let mut dirs_to_search = ~[];
    let first_char = term.substr(0, 1);

    // Find search directory
    match getenv(~"TERMINFO") {
        Some(dir) => dirs_to_search.push(path(dir)),
        None => {
            match getenv(~"TERMINFO_DIRS") {
                Some(dirs) => for str::each_split_char(dirs, ':') |i| {
                    if i == ~"" {
                        dirs_to_search.push(path(~"/usr/share/terminfo"));
                    } else {
                        dirs_to_search.push(path(i.to_owned()));
                    }
                },
                // Found nothing, use the default path
                None => dirs_to_search.push(path(~"/usr/share/terminfo"))
            }
        }
    };

    // Look for the terminal in all of the search directories
    for dirs_to_search.each |p| {
        let newp = ~p.push_many(&[first_char.to_owned(), term.to_owned()]);
        if os::path_exists(p) && os::path_exists(newp) {
            return Some(newp);
        }
    }
    None
}

#[test]
fn test_get_dbpath_for_term() {
    // woefully inadequate test coverage
    use core::os::{setenv, unsetenv};
    fn x(t: &str) -> ~str { get_dbpath_for_term(t).expect("no terminfo entry found").to_str() };
    assert!(x("screen") == ~"/usr/share/terminfo/s/screen");
    assert!(get_dbpath_for_term("") == None);
    setenv("TERMINFO_DIRS", ":");
    assert!(x("screen") == ~"/usr/share/terminfo/s/screen");
    unsetenv("TERMINFO_DIRS");
}
<|endoftext|>