<commit_before>extern crate rand;

const ROWS: u8 = 9;
const COLS: u8 = 12;
const TILES: u8 = 108;
const PLAYERS: u8 = 4;

#[derive(RustcDecodable, RustcEncodable)]
pub struct Game {
    players: Vec<Player>,
    board: Board,
    turn: PlayerId,
    merge_decision: Option<PlayerId>
}

#[derive(RustcDecodable, RustcEncodable)]
struct Player {
    id: PlayerId,
    money: i32,
    shares: PlayerShares,
    tiles: Vec<Tile>
}

type PlayerId = u8;

#[derive(RustcDecodable, RustcEncodable)]
struct PlayerShares {
    luxor: u8,
    tower: u8,
    american: u8,
    festival: u8,
    worldwide: u8,
    continental: u8,
    imperial: u8
}

#[derive(RustcDecodable, RustcEncodable, Clone, Debug)]
struct Tile { row: u8, col: u8 }

#[derive(RustcDecodable, RustcEncodable)]
struct Board {
    slots: Vec<Slot>
}

#[derive(RustcDecodable, RustcEncodable)]
struct Slot {
    row: u8,
    col: u8,
    has_tile: bool,
    hotel: Option<Hotel>
}

enum Action {
    PlaceTile,
    HandleMergeStocks,
    BuyStocks,
    DrawTile,
    EndGame
}

pub struct PlaceTile {
    player: PlayerId,
    tile: Tile
}

pub struct HandleMergeStocks {
    hold: u8,
    sell: u8,
    trade: u8
}

type BuyStocks = PlayerShares;

#[derive(RustcDecodable, RustcEncodable)]
enum Hotel { Luxor, Tower, American, Festival, Worldwide, Continental, Imperial }

fn empty_shares() -> PlayerShares {
    PlayerShares { luxor: 0, tower: 0, american: 0, festival: 0, worldwide: 0, continental: 0, imperial: 0 }
}

fn new_player(id: PlayerId, tiles: Vec<Tile>) -> Player {
    Player { id: id, money: 6000, shares: empty_shares(), tiles: tiles }
}

fn choose_tiles(tiles: Vec<Tile>, count: u8) -> (Vec<Tile>, Vec<Tile>) {
    let mut remaining_tiles = tiles;
    let mut random_tiles = Vec::new();
    for _ in 0..count {
        let random_index = rand::random::<usize>() % remaining_tiles.len();
        random_tiles.push(remaining_tiles.remove(random_index));
    }
    (random_tiles, remaining_tiles)
}

fn new_players(tiles: Vec<Tile>) -> Vec<Player>{
    let init_players: Vec<Player> = Vec::new();
    let (players, _) = (0..PLAYERS)
        .fold( (init_players, tiles), | (mut v, remaining), i | {
            let (player_tiles, new_remaining) = choose_tiles(remaining, 6);
            let player = new_player(i, player_tiles);
            v.push(player);
            (v, new_remaining)
        });
    players
}

fn has_tile_on_slot(tiles: & Vec<Tile>, row: u8, col: u8) -> bool {
    tiles.iter().any(|t| t.row == row && t.col == col)
}

fn initial_slots(starting_tiles: Vec<Tile>) -> Vec<Slot> {
    (0..COLS).flat_map(|col| -> Vec<Slot> {
        (0..ROWS).map(|row| {
            Slot {
                row: row,
                col: col,
                hotel: None,
                has_tile: has_tile_on_slot(&starting_tiles, row, col)
            }
        }).collect()
    }).collect()
}

pub fn initial_state() -> Game {
    let all_tiles = (0..TILES).map(|i| Tile { row: i / COLS, col: i % ROWS }).collect();
    let (starting_tiles, remaining_tiles) = choose_tiles(all_tiles, PLAYERS);
    let players = new_players(remaining_tiles);
    let slots = initial_slots(starting_tiles);
    Game {
        board: Board { slots: slots },
        players: players,
        turn: 1,
        merge_decision: None
    }
}

#[test]
fn players_start_with_six_tiles() {
    let state = initial_state();
    for player in state.players {
        assert_eq!(player.tiles.len(), 6);
    }
}

#[test]
fn players_start_with_6000_in_cash() {
    let state = initial_state();
    for player in state.players {
        assert_eq!(player.money, 6000);
    }
}

#[test]
fn players_start_with_zero_shares() {
    let state = initial_state();
    for player in state.players {
        assert_eq!(player.shares.luxor, 0);
        assert_eq!(player.shares.tower, 0);
        assert_eq!(player.shares.american, 0);
        assert_eq!(player.shares.festival, 0);
        assert_eq!(player.shares.worldwide, 0);
        assert_eq!(player.shares.continental, 0);
        assert_eq!(player.shares.imperial, 0);
    }
}

#[test]
fn game_starts_with_four_placed_tiles() {
    let state = initial_state();
    let board_tiles = state.board.slots.iter().filter(|s| s.has_tile).count();
    assert_eq!(board_tiles, 4)
}
<commit_msg>Player can place a tile (no error checking)<commit_after>extern crate rand;

const ROWS: u8 = 9;
const COLS: u8 = 12;
const TILES: u8 = 108;
const PLAYERS: u8 = 4;

#[derive(RustcDecodable, RustcEncodable, Clone)]
pub struct Game {
    players: Vec<Player>,
    board: Board,
    turn: PlayerId,
    merge_decision: Option<PlayerId>
}

#[derive(RustcDecodable, RustcEncodable, Clone)]
struct Player {
    id: PlayerId,
    money: i32,
    shares: PlayerShares,
    tiles: Vec<Tile>
}

type PlayerId = u8;

#[derive(RustcDecodable, RustcEncodable, Clone)]
struct PlayerShares {
    luxor: u8,
    tower: u8,
    american: u8,
    festival: u8,
    worldwide: u8,
    continental: u8,
    imperial: u8
}

#[derive(RustcDecodable, RustcEncodable, Clone, Debug)]
struct Tile { row: u8, col: u8 }

#[derive(RustcDecodable, RustcEncodable, Clone)]
struct Board {
    slots: Vec<Slot>
}

#[derive(RustcDecodable, RustcEncodable, Clone, PartialEq)]
struct Slot {
    row: u8,
    col: u8,
    has_tile: bool,
    hotel: Option<Hotel>
}

#[derive(Debug)]
pub enum Action {
    PlaceTile { player: PlayerId, tile: Tile },
    HandleMergeStocks { hold: u8, sell: u8, trade: u8 },
    BuyStocks,
    DrawTile,
    EndGame
}

#[derive(RustcDecodable, RustcEncodable, Clone, PartialEq)]
enum Hotel { Luxor, Tower, American, Festival, Worldwide, Continental, Imperial }

fn empty_shares() -> PlayerShares {
    PlayerShares { luxor: 0, tower: 0, american: 0, festival: 0, worldwide: 0, continental: 0, imperial: 0 }
}

fn new_player(id: PlayerId, tiles: Vec<Tile>) -> Player {
    Player { id: id, money: 6000, shares: empty_shares(), tiles: tiles }
}

fn choose_tiles(tiles: Vec<Tile>, count: u8) -> (Vec<Tile>, Vec<Tile>) {
    let mut remaining_tiles = tiles;
    let mut random_tiles = Vec::new();
    for _ in 0..count {
        let random_index = rand::random::<usize>() % remaining_tiles.len();
        random_tiles.push(remaining_tiles.remove(random_index));
    }
    (random_tiles, remaining_tiles)
}

fn new_players(tiles: Vec<Tile>) -> Vec<Player>{
    let init_players: Vec<Player> = Vec::new();
    let (players, _) = (0..PLAYERS)
        .fold( (init_players, tiles), | (mut v, remaining), i | {
            let (player_tiles, new_remaining) = choose_tiles(remaining, 6);
            let player = new_player(i, player_tiles);
            v.push(player);
            (v, new_remaining)
        });
    players
}

fn has_tile_on_slot(tiles: & Vec<Tile>, row: u8, col: u8) -> bool {
    tiles.iter().any(|t| t.row == row && t.col == col)
}

fn initial_slots(starting_tiles: Vec<Tile>) -> Vec<Slot> {
    (0..ROWS).flat_map(|row| -> Vec<Slot> {
        (0..COLS).map(|col| {
            Slot {
                row: row,
                col: col,
                hotel: None,
                has_tile: has_tile_on_slot(&starting_tiles, row, col)
            }
        }).collect()
    }).collect()
}

pub fn initial_state() -> Game {
    let all_tiles = (0..TILES).map(|i| Tile { row: i / COLS, col: i % ROWS }).collect();
    let (starting_tiles, remaining_tiles) = choose_tiles(all_tiles, PLAYERS);
    let players = new_players(remaining_tiles);
    let slots = initial_slots(starting_tiles);
    Game {
        board: Board { slots: slots },
        players: players,
        turn: 1,
        merge_decision: None
    }
}

fn new_game_with_tiles(start_tiles: BoardTiles, player_tiles: PlayerTiles) -> Game {
    let (starting_tiles, remaining) = board_tiles_to_tiles(&start_tiles);
    let players = player_tiles
        .iter()
        .enumerate()
        .map(|(i, tiles)| {
            let _tiles = tiles
                .iter()
                .map(|&(r,c)| Tile { row: r as u8, col: c as u8 } )
                .collect();
            new_player(i as u8, _tiles)
        })
        .collect();
    let slots = initial_slots(starting_tiles);
    Game {
        board: Board { slots: slots },
        players: players,
        turn: 1,
        merge_decision: None
    }
}

fn board_tiles_to_tiles(tiles: &BoardTiles) -> (Vec<Tile>, Vec<Tile>) {
    let mut chosen = Vec::new();
    let mut others = Vec::new();
    for row in 0..tiles.len() {
        for col in 0..tiles[0].len() {
            let tile = Tile { row: row as u8, col: col as u8 };
            if tiles[row][col] == 1 {
                chosen.push(tile)
            } else {
                others.push(tile)
            }
        }
    }
    (chosen, others)
}

pub fn play_turn(game: &Game, action: Action) -> Game {
    match action {
        Action::PlaceTile { player: player, tile: tile } => {
            place_tile(game, player, &tile)
        }
        _ => panic!(format!("I don't know how to play a turn with action {:?}", action))
    }
}

fn place_tile(game: &Game, player: u8, tile: &Tile) -> Game {
    Game {
        board: place_tile_on_board(&game.board, &tile),
        players: game.players.clone(),
        turn: game.turn,
        merge_decision: game.merge_decision
    }
}

fn place_tile_on_board(board: &Board, tile: &Tile) -> Board {
    println!("Tile {:?}", tile);
    let slots = board.slots
        .iter()
        .map(|s| {
            if s.row == tile.row && s.col == tile.col {
                println!("Match! ({},{})", s.row, s.col);
                Slot { row: s.row, col: s.col, has_tile: true, hotel: s.hotel.clone() }
            } else {
                println!("No match! ({},{})", s.row, s.col);
                s.clone()
            }
        })
        .collect();
    Board { slots: slots }
}

#[test]
fn players_start_with_six_tiles() {
    let state = initial_state();
    for player in state.players {
        assert_eq!(player.tiles.len(), 6);
    }
}

#[test]
fn players_start_with_6000_in_cash() {
    let state = initial_state();
    for player in state.players {
        assert_eq!(player.money, 6000);
    }
}

#[test]
fn players_start_with_zero_shares() {
    let state = initial_state();
    for player in state.players {
        assert_eq!(player.shares.luxor, 0);
        assert_eq!(player.shares.tower, 0);
        assert_eq!(player.shares.american, 0);
        assert_eq!(player.shares.festival, 0);
        assert_eq!(player.shares.worldwide, 0);
        assert_eq!(player.shares.continental, 0);
        assert_eq!(player.shares.imperial, 0);
    }
}

#[test]
fn game_starts_with_four_placed_tiles() {
    let state = initial_state();
    let board_tiles = state.board.slots.iter().filter(|s| s.has_tile).count();
    assert_eq!(board_tiles, 4)
}

type BoardTiles = [[i32; COLS as usize]; ROWS as usize];
type PlayerTiles = [[(i32,i32); 6]; PLAYERS as usize];

#[test]
fn placing_a_tile_adds_tile_to_board() {
    let start_tiles = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                       [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                       [0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0],
                       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]];
    let end_tiles =   [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                       [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                       [0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1],
                       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]];
    let player_tiles = [[ (0,0), (0,1), (0,2), (0,3), (0,4), (0,5) ],
                        [ (1,0), (1,1), (1,2), (1,3), (1,4), (1,5) ],
                        [ (2,2), (2,1), (2,2), (2,3), (2,4), (2,5) ],
                        [ (3,3), (3,1), (3,2), (3,3), (3,4), (3,5) ]];
    let state = new_game_with_tiles(start_tiles, player_tiles);
    let tile_to_place = Tile { row: 5, col: 11 };
    let action = Action::PlaceTile { player: 1, tile: tile_to_place };
    let state_after = play_turn(&state, action);
    assert_board_has_tiles(end_tiles, &state_after.board);
}

fn assert_board_has_tiles(expected_tiles: BoardTiles, actual_board: &Board) {
    let expected_board = tiles_to_board(&expected_tiles);
    let are_equal = expected_board.slots
        .iter()
        .zip(actual_board.slots.iter())
        .all(|(left, right)| *left == *right );
    let error_msg = format!("\n\nBoard did not have expected tiles.\n\nExpected tiles:\n{}\n\nActual tiles:\n{}\n\n", print_board(&expected_board), print_board(&actual_board));
    assert!(are_equal, error_msg);
}

fn tiles_to_board(tiles: &BoardTiles) -> Board {
    let board_tiles = tiles
        .iter()
        .enumerate()
        .flat_map(|(row, row_tiles)| {
            let slots: Vec<Slot> = row_tiles
                .iter()
                .enumerate()
                .map(|(col, val): (usize, &i32)| {
                    let has_tile = *val == 1;
                    Slot { row: row as u8, col: col as u8, has_tile: has_tile, hotel: None }
                })
                .collect();
            slots
        }).collect();
    Board { slots: board_tiles }
}

fn row_to_char<'a>(row: u8) -> &'a str {
    let mapping = ["A", "B", "C", "D", "E", "F", "G", "H", "I"];
    mapping[row as usize]
}

fn print_tile(slot: &Slot) -> String{
    format!("{}{}", row_to_char(slot.row), slot.col + 1)
}

fn print_board(board: &Board) -> String {
    let mut string = String::new();
    string.push_str("   1  2  3  4  5  6  7  8  9  10 11 12\n");
    for row in board.slots.chunks(COLS as usize) {
        let row_char = row_to_char(row[0].row);
        string.push_str(&format!("{}  ", row_char));
        for slot in row {
            string.push_str(&format!("{:<2} ", if slot.has_tile { '\u{25FC}' } else { '\u{25FB}' }));
        }
        string.push_str(&format!("{}\n", row_char));
    }
    string.push_str("   1  2  3  4  5  6  7  8  9  10 11 12");
    string
}
<|endoftext|>


<commit_before>use std::char;
use std::collections::HashMap;
use std::convert::AsRef;
use std::fs::File;
use std::io::BufReader;
use std::io::BufRead;
use std::io::Result;
use std::path::Path;
use std::vec::Vec;

use state::Direction::*;

use matcher;
use util;
extern crate rand;

// Location represents a specific place in the execution space
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct Location {
    x: usize,
    y: usize,
}

impl Location {
    //step takes the location and moves in given a direction
    pub fn step(&self, direction: Direction) -> Location {
        let y = match direction {
            Up => self.y.wrapping_sub(1),
            Down => self.y.wrapping_add(1),
            _ => self.y,
        };

        let x = match direction {
            Right => self.x.wrapping_add(1),
            Left => self.x.wrapping_sub(1),
            _ => self.x,
        };

        Location { x: x, y: y }
    }

    //step_mut destructively moves this location in the given direction
    pub fn step_mut(&mut self, direction: Direction) -> Location {
        let next = self.step(direction);
        self.x = next.x;
        self.y = next.y;
        *self

    }

    // new creates a new Location object
    pub fn new(x: usize, y: usize) -> Location {
        Location { x: x, y: y }
    }
}

// Direction represents a specific direction for the interpreter to go
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Direction {
    Up,
    Down,
    Left,
    Right,
}

impl Direction {
    pub fn opposite(&self) -> Direction {
        match *self {
            Up => Down,
            Left => Right,
            Right => Left,
            Down => Up,
        }
    }

    pub fn up_or_down() -> Direction {
        if rand::random() { Up } else { Down }
    }

    pub fn right_or_left() -> Direction {
        if rand::random() { Right } else { Down }
    }
}

impl Default for Direction {
    fn default() -> Direction {
        Direction::Right
    }
}

impl rand::Rand for Direction {
    fn rand<R: rand::Rng>(rng: &mut R) -> Self {
        let choices = [Up, Down, Left, Right];
        rng.choose(&choices).unwrap().clone()

    }
}
// The current execution mode of this InterpreterState
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Mode {
    Normal, // This intepreter is in the middle of normal execution
    Exited, // This interpreter has reached a terminus for execution
    Quoted, // This interpreter is reading a quoted string
}

impl Default for Mode {
    fn default() -> Mode {
        Mode::Normal
    }
}

// A covenience wrapper around a Vec to produce a stack
#[derive(Default)]
struct Stack {
    stack: Vec<i64>,
}

impl Stack {
    // pop gets the top-most value from the stack, or 0
    pub fn pop(&mut self) -> i64 {
        self.stack.pop().unwrap_or(0)
    }

    // push adds a new number to the top of the stack
    pub fn push(&mut self, item: i64) {
        self.stack.push(item);
    }

    // duplicate_top takes the top most item on the stack (or 0) or pushes it on the stack
    pub fn duplicate_top(&mut self) {
        let value = self.pop();
        self.push(value);
        self.push(value);
    }

    // swap_top takes the top two elements from the stack and reverses them
    pub fn swap_top(&mut self) {
        let a = self.pop();
        let b = self.pop();
        self.push(a);
        self.push(b);
    }
}

// State represents the current state of the map
#[derive(Default)]
pub struct State {
    initial_grid: Vec<Vec<char>>, // the state of the grid when loaded from the file
    grid_updates: HashMap<Location, char>, // any updates to the grid from runtime
    stack: Stack, // the current stack of values pushed from execution
    cursor: Location, // the instruction pointer that shows where we are in the grid
    direction: Direction, // the direction in which the cursor is moving
    execution_mode: Mode, // what execution mode is the interpreter currently in
}

impl State {
    //empty state produces a fresh, empty state object
    pub fn empty_state() -> State {
        Default::default()
    }

    //new_from_file produces a state containing the contents of the file
    pub fn new_from_file<P: AsRef<Path>>(path: P) -> Result<State> {
        let file = File::open(path)?;
        let buf_reader = BufReader::new(file);
        let mut state = State::empty_state();
        for line in buf_reader.lines() {
            let l = line.unwrap_or_default();
            let mut vec = Vec::new();
            for ch in l.chars() {
                vec.push(ch);
            }
            state.initial_grid.push(vec)
        }
        Ok(state)
    }

    // value_at - returns the value at a given location
    pub fn value_at(&self, loc: Location) -> Option<char> {
        if self.grid_updates.contains_key(&loc) {
            return Some(self.grid_updates[&loc]);
        }

        if self.initial_grid.len() >= loc.y {
            return None;
        }

        if self.initial_grid[loc.y].len() >= loc.x {
            return None;
        }

        Some(self.initial_grid[loc.y][loc.x])
    }

    // current_value - gets the value at the current position
    pub fn current_value(&self) -> Option<char> {
        self.value_at(self.cursor.clone())
    }

    // set_value - sets the value at a given location
    pub fn set_value(&mut self, loc: Location, ch: char) {
        self.grid_updates.insert(loc, ch);
    }

    // increment_cursor moves our cursor to the next position - does not wrap
    fn increment_cursor(&mut self) -> Location {
        self.cursor.step_mut(self.direction)
    }

    // next_value increments the cursor and produces the next value if there is one
    fn next_value(&mut self) -> Option<char> {
        self.increment_cursor();
        self.current_value()
    }

    // step_cursor moves the cursor to the next valid space
    pub fn step_cursor(&mut self) -> bool {
        if self.execution_mode == Mode::Exited {
            return false;
        }

        let start = self.cursor;
        while self.next_value().is_none() {
            if start == self.cursor {
                return false;
            }
        }

        true
    }

    // process_quoted reads the current character and pushes it onto the stack if needed
    pub fn process_quoted(&mut self, ch: char) {
        if ch == '"' {
            self.execution_mode = Mode::Normal;
            return;
        }
        self.stack.push(util::char_to_i64(ch));
    }

    // process_normal reads the current character and process it according to normal rules
    pub fn process_normal(&mut self, ch: char) {
        match ch {
            // push digits to the stack
            '0'...'9' | 'a'...'f' => push_digit(self, ch),

            // modal operators
            '"' => self.execution_mode = Mode::Quoted,
            '#' => {self.step_cursor();},

            // arithmetic operators
            '+' => addition(self),
            '-' => subtraction(self),
            '*' => multiply(self),
            '/' => divide(self),
            '%' => modulo(self),

            // logical operators
            '!' => logical_negation(self),
            '`' => greater_than(self),

            // directional operations
            '>' => self.direction = Right,
            '<' => self.direction = Left,
            '^' => self.direction = Up,
            'v' => self.direction = Down,
            '?' => self.direction = rand::random::<Direction>(),

            // branching operators
            '|' => veritical_if(self),
            '_' => horizontal_if(self),

            // stack manipulation operators
            '$' => {self.stack.pop();},
            ':' => self.stack.duplicate_top(),
            '\\' => self.stack.swap_top(),

            // output operators
            '.' => print_digit(self),
            ',' => print_char(self),

            // end the program
            '@' => end_program(self),
            _ => (),
        };

    }
}

// put pops the values y, x, and v and stores value v at location {x,y}
fn put(state: &mut State) {
    let y = state.stack.pop();
    let x = state.stack.pop();
    let v = state.stack.pop();
    state.set_value(Location{x : x as usize, y : y as usize }, util::i64_to_char(v));
}

// get puts the value at {x, y} onto the stack
fn get(state: &mut State) {
    let y = state.stack.pop();
    let x = state.stack.pop();
    let v = util::char_to_i64(state.value_at(Location{x : x as usize, y : y as usize}).unwrap_or(0 as char));
}

// greater_than tests if b > a
fn greater_than(state : &mut State) {
    let a = state.stack.pop();
    let b = state.stack.pop();
    let mut result = 0;
    if b > a {
        result = 1;
    }
    state.stack.push(result);
}

// logical_negation tests if the top most value is 0
fn logical_negation(state : &mut State) {
    let mut negation = 0;
    if state.stack.pop() == 0 {
        negation = 1;
    }
    state.stack.push(negation);
}

// print_digit prints a number from the stack
fn print_digit(state: &mut State) {
    print!("{}", state.stack.pop());
}

// print_char prints the top value on the stack as a char
fn print_char(state: &mut State) {
    print!("{}", state.stack.pop() as char);
}

// push_digit takes a character and pushs it onto the stack as a digit
fn push_digit(state: &mut State, ch: char) {
    if let Some(v) = ch.to_digit(16) {
        state.stack.push(v as i64);
    }
}

// addition performs addition on the two top values from the stack
fn addition(state: &mut State) {
    let sum = state.stack.pop() + state.stack.pop();
    state.stack.push(sum);
}

// subtraction performs b - a where a is popped from the stack before b
fn subtraction(state: &mut State) {
    let a = state.stack.pop();
    let b = state.stack.pop();
    state.stack.push(b - a);
}

// multiply performs a * b by popping two values from the stack
fn multiply(state: &mut State) {
    let product = state.stack.pop() * state.stack.pop();
    state.stack.push(product);
}

// divide performs b / a => does NOT user prompt
fn divide(state: &mut State) {
    let a = state.stack.pop();
    let b = state.stack.pop();
    state.stack.push(b / a);
}

// modulo performs b % a
fn modulo(state: &mut State) {
    let a = state.stack.pop();
    let b = state.stack.pop();
    state.stack.push(b % a);
}

// end_program sets the program to a terminated state
fn end_program(state: &mut State) {
    state.execution_mode = Mode::Exited;
}

// horizontal_if calculates a vertical branch
fn horizontal_if(state: &mut State) {
    state.direction = Left;
    if state.stack.pop() == 0 {
        state.direction = Right;
    }
}

// veritical_if calculates a horizontal branch
fn veritical_if(state: &mut State) {
    state.direction = Up;
    if state.stack.pop() == 0 {
        state.direction = Down;
    }
}
<commit_msg>Added all befunge 93 operators<commit_after>use std::char;
use std::collections::HashMap;
use std::convert::AsRef;
use std::fs::File;
use std::io;
use std::io::BufReader;
use std::io::BufRead;
use std::io::Result;
use std::path::Path;
use std::vec::Vec;

use state::Direction::*;
use util;

extern crate rand;

// Location represents a specific place in the execution space
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct Location {
    x: usize,
    y: usize,
}

impl Location {
    //step takes the location and moves in given a direction
    pub fn step(&self, direction: Direction) -> Location {
        let y = match direction {
            Up => self.y.wrapping_sub(1),
            Down => self.y.wrapping_add(1),
            _ => self.y,
        };

        let x = match direction {
            Right => self.x.wrapping_add(1),
            Left => self.x.wrapping_sub(1),
            _ => self.x,
        };

        Location { x: x, y: y }
    }

    //step_mut destructively moves this location in the given direction
    pub fn step_mut(&mut self, direction: Direction) -> Location {
        let next = self.step(direction);
        self.x = next.x;
        self.y = next.y;
        *self

    }

    // new creates a new Location object
    pub fn new(x: usize, y: usize) -> Location {
        Location { x: x, y: y }
    }
}

// Direction represents a specific direction for the interpreter to go
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Direction {
    Up,
    Down,
    Left,
    Right,
}

impl Direction {
    pub fn opposite(&self) -> Direction {
        match *self {
            Up => Down,
            Left => Right,
            Right => Left,
            Down => Up,
        }
    }

    pub fn up_or_down() -> Direction {
        if rand::random() { Up } else { Down }
    }

    pub fn right_or_left() -> Direction {
        if rand::random() { Right } else { Down }
    }
}

impl Default for Direction {
    fn default() -> Direction {
        Direction::Right
    }
}

impl rand::Rand for Direction {
    fn rand<R: rand::Rng>(rng: &mut R) -> Self {
        let choices = [Up, Down, Left, Right];
        rng.choose(&choices).unwrap().clone()

    }
}
// The current execution mode of this InterpreterState
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Mode {
    Normal, // This intepreter is in the middle of normal execution
    Exited, // This interpreter has reached a terminus for execution
    Quoted, // This interpreter is reading a quoted string
}

impl Default for Mode {
    fn default() -> Mode {
        Mode::Normal
    }
}

// A covenience wrapper around a Vec to produce a stack
#[derive(Default)]
struct Stack {
    stack: Vec<i64>,
}

impl Stack {
    // pop gets the top-most value from the stack, or 0
    pub fn pop(&mut self) -> i64 {
        self.stack.pop().unwrap_or(0)
    }

    // push adds a new number to the top of the stack
    pub fn push(&mut self, item: i64) {
        self.stack.push(item);
    }

    // duplicate_top takes the top most item on the stack (or 0) or pushes it on the stack
    pub fn duplicate_top(&mut self) {
        let value = self.pop();
        self.push(value);
        self.push(value);
    }

    // swap_top takes the top two elements from the stack and reverses them
    pub fn swap_top(&mut self) {
        let a = self.pop();
        let b = self.pop();
        self.push(a);
        self.push(b);
    }
}

// State represents the current state of the map
#[derive(Default)]
pub struct State {
    initial_grid: Vec<Vec<char>>, // the state of the grid when loaded from the file
    grid_updates: HashMap<Location, char>, // any updates to the grid from runtime
    stack: Stack, // the current stack of values pushed from execution
    cursor: Location, // the instruction pointer that shows where we are in the grid
    direction: Direction, // the direction in which the cursor is moving
    execution_mode: Mode, // what execution mode is the interpreter currently in
}

impl State {
    //empty state produces a fresh, empty state object
    pub fn empty_state() -> State {
        Default::default()
    }

    //new_from_file produces a state containing the contents of the file
    pub fn new_from_file<P: AsRef<Path>>(path: P) -> Result<State> {
        let file = File::open(path)?;
        let buf_reader = BufReader::new(file);
        let mut state = State::empty_state();
        for line in buf_reader.lines() {
            let l = line.unwrap_or_default();
            let mut vec = Vec::new();
            for ch in l.chars() {
                vec.push(ch);
            }
            state.initial_grid.push(vec)
        }
        Ok(state)
    }

    // value_at - returns the value at a given location
    pub fn value_at(&self, loc: Location) -> Option<char> {
        if self.grid_updates.contains_key(&loc) {
            return Some(self.grid_updates[&loc]);
        }

        if self.initial_grid.len() >= loc.y {
            return None;
        }

        if self.initial_grid[loc.y].len() >= loc.x {
            return None;
        }

        Some(self.initial_grid[loc.y][loc.x])
    }

    // current_value - gets the value at the current position
    pub fn current_value(&self) -> Option<char> {
        self.value_at(self.cursor.clone())
    }

    // set_value - sets the value at a given location
    pub fn set_value(&mut self, loc: Location, ch: char) {
        self.grid_updates.insert(loc, ch);
    }

    // increment_cursor moves our cursor to the next position - does not wrap
    fn increment_cursor(&mut self) -> Location {
        self.cursor.step_mut(self.direction)
    }

    // next_value increments the cursor and produces the next value if there is one
    fn next_value(&mut self) -> Option<char> {
        self.increment_cursor();
        self.current_value()
    }

    // step_cursor moves the cursor to the next valid space
    pub fn step_cursor(&mut self) -> bool {
        if self.execution_mode == Mode::Exited {
            return false;
        }

        let start = self.cursor;
        while self.next_value().is_none() {
            if start == self.cursor {
                return false;
            }
        }

        true
    }

    // process_quoted reads the current character and pushes it onto the stack if needed
    pub fn process_quoted(&mut self, ch: char) {
        if ch == '"' {
            self.execution_mode = Mode::Normal;
            return;
        }
        self.stack.push(util::char_to_i64(ch));
    }

    // process_normal reads the current character and process it according to normal rules
    pub fn process_normal(&mut self, ch: char) {
        match ch {
            // push digits to the stack
            '0'...'9' | 'a'...'f' => push_digit(self, ch),

            // modal operators
            '"' => self.execution_mode = Mode::Quoted,
            '#' => {self.step_cursor();},

            // arithmetic operators
            '+' => addition(self),
            '-' => subtraction(self),
            '*' => multiply(self),
            '/' => divide(self),
            '%' => modulo(self),

            // logical operators
            '!' => logical_negation(self),
            '`' => greater_than(self),

            // directional operations
            '>' => self.direction = Right,
            '<' => self.direction = Left,
            '^' => self.direction = Up,
            'v' => self.direction = Down,
            '?' => self.direction = rand::random::<Direction>(),

            // branching operators
            '|' => veritical_if(self),
            '_' => horizontal_if(self),

            // stack manipulation operators
            '$' => {self.stack.pop();},
            ':' => self.stack.duplicate_top(),
            '\\' => self.stack.swap_top(),

            // input operators
            '&' => read_integer(self),
            '~' => read_char(self),

            // output operators
            '.' => print_digit(self),
            ',' => print_char(self),

            // load/store operations
            'p' => put(self),
            'g' => get(self),

            // end the program
            '@' => end_program(self),
            _ => (),
        };

    }
}

// read_char reads a character from the user
fn read_char(state : &mut State) {
    let mut input = String::new();
    let mut ch : char = 0 as char;
    if let Ok(_) = io::stdin().read_line(&mut input) {
        if let Some(c) = input.chars().next(){
            ch = c;
        }
    }
    state.stack.push(util::char_to_i64(ch));
}

// read_integer reads a number from the commandline
fn read_integer(state : &mut State) {
    let mut input = String::new();
    if let Ok(_) = io::stdin().read_line(&mut input) {
        if let Ok(value) = input.trim().parse::<i64>() {
            state.stack.push(value);
            return;
        }
    }
    state.stack.push(0);
}

// put pops the values y, x, and v and stores value v at location {x,y}
fn put(state: &mut State) {
    let y = state.stack.pop();
    let x = state.stack.pop();
    let v = state.stack.pop();
    state.set_value(Location{x : x as usize, y : y as usize }, util::i64_to_char(v));
}

// get puts the value at {x, y} onto the stack
fn get(state: &mut State) {
    let y = state.stack.pop();
    let x = state.stack.pop();
    let v = util::char_to_i64(state.value_at(Location{x : x as usize, y : y as usize}).unwrap_or(0 as char));
}

// greater_than tests if b > a
fn greater_than(state : &mut State) {
    let a = state.stack.pop();
    let b = state.stack.pop();
    let mut result = 0;
    if b > a {
        result = 1;
    }
    state.stack.push(result);
}

// logical_negation tests if the top most value is 0
fn logical_negation(state : &mut State) {
    let mut negation = 0;
    if state.stack.pop() == 0 {
        negation = 1;
    }
    state.stack.push(negation);
}

// print_digit prints a number from the stack
fn print_digit(state: &mut State) {
    print!("{}", state.stack.pop());
}

// print_char prints the top value on the stack as a char
fn print_char(state: &mut State) {
    print!("{}", util::i64_to_char(state.stack.pop()));
}

// push_digit takes a character and pushs it onto the stack as a digit
fn push_digit(state: &mut State, ch: char) {
    if let Some(v) = ch.to_digit(16) {
        state.stack.push(v as i64);
    }
}

// addition performs addition on the two top values from the stack
fn addition(state: &mut State) {
    let sum = state.stack.pop() + state.stack.pop();
    state.stack.push(sum);
}

// subtraction performs b - a where a is popped from the stack before b
fn subtraction(state: &mut State) {
    let a = state.stack.pop();
    let b = state.stack.pop();
    state.stack.push(b - a);
}

// multiply performs a * b by popping two values from the stack
fn multiply(state: &mut State) {
    let product = state.stack.pop() * state.stack.pop();
    state.stack.push(product);
}

// divide performs b / a => does NOT user prompt
fn divide(state: &mut State) {
    let a = state.stack.pop();
    let b = state.stack.pop();
    state.stack.push(b / a);
}

// modulo performs b % a
fn modulo(state: &mut State) {
    let a = state.stack.pop();
    let b = state.stack.pop();
    state.stack.push(b % a);
}

// end_program sets the program to a terminated state
fn end_program(state: &mut State) {
    state.execution_mode = Mode::Exited;
}

// horizontal_if calculates a vertical branch
fn horizontal_if(state: &mut State) {
    state.direction = Left;
    if state.stack.pop() == 0 {
        state.direction = Right;
    }
}

// veritical_if calculates a horizontal branch
fn veritical_if(state: &mut State) {
    state.direction = Up;
    if state.stack.pop() == 0 {
        state.direction = Down;
    }
}
<|endoftext|>


<commit_before>use libc::{c_int};

use super::*;

impl VTerm {

    pub fn state_get_default_colors(&self) -> (ColorRGB, ColorRGB) {
        let mut fg_rgb: ffi::VTermColor = Default::default();
        let mut bg_rgb: ffi::VTermColor = Default::default();
        unsafe { ffi::vterm_state_get_default_colors(self.state_ptr.get(), &mut fg_rgb, &mut bg_rgb) };

        (
            ColorRGB { red: fg_rgb.red, green: fg_rgb.green, blue: fg_rgb.blue },
            ColorRGB { red: bg_rgb.red, green: bg_rgb.green, blue: bg_rgb.blue },
        )
    }

    pub fn state_set_default_colors(&mut self, default_fg: ColorRGB, default_bg: ColorRGB) {
        let fg_rgb = ffi::VTermColor {
            red: default_fg.red,
            green: default_fg.green,
            blue: default_fg.blue
        };
        let bg_rgb = ffi::VTermColor {
            red: default_bg.red,
            green: default_bg.green,
            blue: default_bg.blue
        };

        unsafe { ffi::vterm_state_set_default_colors(self.state_ptr.get_mut(), &fg_rgb, &bg_rgb); };
    }

    pub fn state_get_rgb_color_from_palette(&self, index: u16) -> ColorRGB {
        let mut ffi_color: ffi::VTermColor = Default::default();
        unsafe { ffi::vterm_state_get_palette_color(self.state_ptr.get(), index as c_int, &mut ffi_color); }
        ColorRGB {
            red: ffi_color.red,
            green: ffi_color.green,
            blue: ffi_color.blue,
        }
    }

    pub fn state_get_palette_color_from_rgb(&self, target: &ColorRGB) -> u16 {
        for i in 0..256 {
            let color = self.state_get_rgb_color_from_palette(i);
            if color.red == target.red && color.green == target.green && color.blue == target.blue {
                return i as u16
            }
        }
        0
    }

    /// move this to ffi classes since it deals with the ffi color type
    pub fn state_get_palette_color_from_c_rgb(&self, target: &ffi::VTermColor) -> u16 {
        for i in 0..256 {
            let color = self.state_get_rgb_color_from_palette(i);
            if color.red == target.red && color.green == target.green && color.blue == target.blue {
                return i as u16
            }
        }
        0
    }

    pub fn state_reset(&mut self, hard: bool) {
      unsafe { ffi::vterm_state_reset(self.state_ptr.get_mut(), ::bool_to_int(hard)); }
    }
}

mod tests {
    #[test]
    fn state_can_get_and_set_default_colors() {
        let mut vterm: ::VTerm = ::VTerm::new(::ScreenSize { rows: 2, cols: 2 });
        vterm.state_set_default_colors(::ColorRGB { red: 200, green: 201, blue: 202 },
                                       ::ColorRGB { red: 0, green: 1, blue: 2 });
        let (fg_rgb, bg_rgb) = vterm.state_get_default_colors();

        assert_eq!(fg_rgb.red, 200);
        assert_eq!(fg_rgb.green, 201);
        assert_eq!(fg_rgb.blue, 202);

        assert_eq!(bg_rgb.red, 0);
        assert_eq!(bg_rgb.green, 1);
        assert_eq!(bg_rgb.blue, 2);
    }
}
<commit_msg>add comment<commit_after>use libc::{c_int};

use super::*;

impl VTerm {

    pub fn state_get_default_colors(&self) -> (ColorRGB, ColorRGB) {
        let mut fg_rgb: ffi::VTermColor = Default::default();
        let mut bg_rgb: ffi::VTermColor = Default::default();
        unsafe { ffi::vterm_state_get_default_colors(self.state_ptr.get(), &mut fg_rgb, &mut bg_rgb) };

        (
            ColorRGB { red: fg_rgb.red, green: fg_rgb.green, blue: fg_rgb.blue },
            ColorRGB { red: bg_rgb.red, green: bg_rgb.green, blue: bg_rgb.blue },
        )
    }

    pub fn state_set_default_colors(&mut self, default_fg: ColorRGB, default_bg: ColorRGB) {
        let fg_rgb = ffi::VTermColor {
            red: default_fg.red,
            green: default_fg.green,
            blue: default_fg.blue
        };
        let bg_rgb = ffi::VTermColor {
            red: default_bg.red,
            green: default_bg.green,
            blue: default_bg.blue
        };

        unsafe { ffi::vterm_state_set_default_colors(self.state_ptr.get_mut(), &fg_rgb, &bg_rgb); };
    }

    pub fn state_get_rgb_color_from_palette(&self, index: u16) -> ColorRGB {
        let mut ffi_color: ffi::VTermColor = Default::default();
        unsafe { ffi::vterm_state_get_palette_color(self.state_ptr.get(), index as c_int, &mut ffi_color); }
        ColorRGB {
            red: ffi_color.red,
            green: ffi_color.green,
            blue: ffi_color.blue,
        }
    }

    // TODO: use this c method instead I just found in pen.c
    // void vterm_state_get_palette_color(const VTermState *state, int index, VTermColor *col)
    pub fn state_get_palette_color_from_rgb(&self, target: &ColorRGB) -> u16 {
        for i in 0..256 {
            let color = self.state_get_rgb_color_from_palette(i);
            if color.red == target.red && color.green == target.green && color.blue == target.blue {
                return i as u16
            }
        }
        0
    }

    /// move this to ffi classes since it deals with the ffi color type
    pub fn state_get_palette_color_from_c_rgb(&self, target: &ffi::VTermColor) -> u16 {
        for i in 0..256 {
            let color = self.state_get_rgb_color_from_palette(i);
            if color.red == target.red && color.green == target.green && color.blue == target.blue {
                return i as u16
            }
        }
        0
    }

    pub fn state_reset(&mut self, hard: bool) {
      unsafe { ffi::vterm_state_reset(self.state_ptr.get_mut(), ::bool_to_int(hard)); }
    }
}

mod tests {
    #[test]
    fn state_can_get_and_set_default_colors() {
        let mut vterm: ::VTerm = ::VTerm::new(::ScreenSize { rows: 2, cols: 2 });
        vterm.state_set_default_colors(::ColorRGB { red: 200, green: 201, blue: 202 },
                                       ::ColorRGB { red: 0, green: 1, blue: 2 });
        let (fg_rgb, bg_rgb) = vterm.state_get_default_colors();

        assert_eq!(fg_rgb.red, 200);
        assert_eq!(fg_rgb.green, 201);
        assert_eq!(fg_rgb.blue, 202);

        assert_eq!(bg_rgb.red, 0);
        assert_eq!(bg_rgb.green, 1);
        assert_eq!(bg_rgb.blue, 2);
    }
}
<|endoftext|>


<commit_before>use dom::{Node, ElementData, pretty_print, NodeType};
use css::{Selector};

use std::collections::HashMap;
use std::fmt;

type PropertyMap = HashMap<String, String>;

pub struct StyledNode<'a> {
    node: &'a Node,
    styles: PropertyMap,
    children: Vec<StyledNode<'a>>
}

impl<'a> StyledNode<'a> {
    pub fn new(node: &Node) -> StyledNode {
        // recursively make a styletree without any styles
        // then apply rules to the tree
        let mut style_children = Vec::new();

        for child in &node.children {
            match child.node_type {
                NodeType::Element(ref e) => style_children.push(StyledNode::new(&child)),
                _ => {}
            }
        }

        StyledNode {
            node: node,
            styles: PropertyMap::new(),
            children: style_children
        }
    }
}

impl<'a> fmt::Debug for StyledNode<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        pretty_print(self.node, 0);
        write!(f, "styles of {:?}: {:?}", self.node, self.styles)
    }
}

pub fn selector_matches(elem: &ElementData, sel: &Selector) -> bool {
    let mut sel_match = true;

    for simple in &sel.simple {
        sel_match |= match simple.tag_name {
            Some(ref t) => *t == elem.tag_name,
            None => true
        };

        sel_match |= match simple.id {
            Some(ref i) => i == elem.get_id().unwrap_or(i),
            None => true
        };

        let elem_classes = elem.get_classes();

        for class in &simple.classes {
            sel_match |= elem_classes.contains::<str>(class);
        }
    }

    sel_match
}<commit_msg>midway through style tree<commit_after>use dom::{Node, ElementData, pretty_print, NodeType};
use css::{Selector};

use std::collections::HashMap;
use std::fmt;

type PropertyMap = HashMap<String, String>;

pub struct StyledNode<'a> {
    node: &'a Node,
    styles: PropertyMap,
    children: Vec<StyledNode<'a>>
}

impl<'a> StyledNode<'a> {
    pub fn new(node: &Node) -> StyledNode {
        // recursively make a styletree without any styles
        // then apply rules to the tree
        let mut style_children = Vec::new();

        for child in &node.children {
            match child.node_type {
                NodeType::Element(ref e) => style_children.push(StyledNode::new(&child)),
                _ => {}
            }
        }

        StyledNode {
            node: node,
            styles: match node.node_type {
                NodeType::Element(e) => , //do the thing
                _ => PropertyMap::new()            }
            children: style_children
        }
    }
}

impl<'a> fmt::Debug for StyledNode<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        pretty_print(self.node, 0);
        write!(f, "styles of {:?}: {:?}", self.node, self.styles)
    }
}

pub fn selector_matches(elem: &ElementData, sel: &Selector) -> bool {
    let mut sel_match = true;

    for simple in &sel.simple {
        sel_match |= match simple.tag_name {
            Some(ref t) => *t == elem.tag_name,
            None => true
        };

        sel_match |= match simple.id {
            Some(ref i) => i == elem.get_id().unwrap_or(i),
            None => true
        };

        let elem_classes = elem.get_classes();

        for class in &simple.classes {
            sel_match |= elem_classes.contains::<str>(class);
        }
    }

    sel_match
}<|endoftext|>


<commit_before>use crate::array_of_tables::ArrayOfTables;
use crate::decor::{Decor, InternalString, Repr};
use crate::formatted::{decorated, key_repr};
use crate::key::Key;
use crate::value::{sort_key_value_pairs, Array, DateTime, InlineTable, Value};
use linked_hash_map::LinkedHashMap;

// TODO: add method to convert a table into inline table

/// Type representing a TOML non-inline table
#[derive(Clone, Debug, Default)]
pub struct Table {
    pub(crate) items: KeyValuePairs,
    // comments/spaces before and after the header
    pub(crate) decor: Decor,
    // whether to hide an empty table
    pub(crate) implicit: bool,
    // used for putting tables back in their original order when serialising.
    // Will be None when the Table wasn't parsed from a file.
    pub(crate) position: Option<usize>,
}

pub(crate) type KeyValuePairs = LinkedHashMap<InternalString, TableKeyValue>;

/// Type representing either a value, a table, an array of tables, or none.
#[derive(Debug, Clone)]
pub enum Item {
    /// Type representing none.
    None,
    /// Type representing value.
    Value(Value),
    /// Type representing table.
    Table(Table),
    /// Type representing array of tables.
    ArrayOfTables(ArrayOfTables),
}

impl Default for Item {
    fn default() -> Self {
        Item::None
    }
}

// TODO: make pub(crate)
#[doc(hidden)]
#[derive(Debug, Clone)]
pub struct TableKeyValue {
    pub(crate) key: Repr,
    pub(crate) value: Item,
}

impl TableKeyValue {
    pub(crate) fn new(key: Repr, value: Item) -> Self {
        TableKeyValue { key, value }
    }
}

/// An iterator type over `Table`'s key/value pairs.
pub type Iter<'a> = Box<dyn Iterator<Item = (&'a str, &'a Item)> + 'a>;

impl Table {
    /// Creates an empty table.
    pub fn new() -> Self {
        Self::with_decor_and_pos(Decor::new("\n", ""), None)
    }

    pub(crate) fn with_pos(position: Option<usize>) -> Self {
        Self {
            position,
            ..Default::default()
        }
    }

    pub(crate) fn with_decor_and_pos(decor: Decor, position: Option<usize>) -> Self {
        Self {
            decor,
            position,
            ..Default::default()
        }
    }

    /// Returns true iff the table contains an item with the given key.
    pub fn contains_key(&self, key: &str) -> bool {
        if let Some(kv) = self.items.get(key) {
            !kv.value.is_none()
        } else {
            false
        }
    }

    /// Returns true iff the table contains a table with the given key.
    pub fn contains_table(&self, key: &str) -> bool {
        if let Some(kv) = self.items.get(key) {
            kv.value.is_table()
        } else {
            false
        }
    }

    /// Returns true iff the table contains a value with the given key.
    pub fn contains_value(&self, key: &str) -> bool {
        if let Some(kv) = self.items.get(key) {
            kv.value.is_value()
        } else {
            false
        }
    }

    /// Returns true iff the table contains an array of tables with the given key.
    pub fn contains_array_of_tables(&self, key: &str) -> bool {
        if let Some(kv) = self.items.get(key) {
            kv.value.is_array_of_tables()
        } else {
            false
        }
    }

    /// Returns an iterator over all key/value pairs, including empty.
    pub fn iter(&self) -> Iter<'_> {
        Box::new(self.items.iter().map(|(key, kv)| (&key[..], &kv.value)))
    }

    /// Removes an item given the key.
    pub fn remove(&mut self, key: &str) -> Option<Item> {
        self.items.remove(key).map(|kv| kv.value)
    }

    /// Sorts Key/Value Pairs of the table,
    /// doesn't affect subtables or subarrays.
    pub fn sort_values(&mut self) {
        sort_key_value_pairs(&mut self.items);
    }

    /// Returns the number of non-empty items in the table.
    pub fn len(&self) -> usize {
        self.items.iter().filter(|i| !(i.1).value.is_none()).count()
    }

    /// Returns the number of key/value pairs in the table.
    pub fn values_len(&self) -> usize {
        self.items.iter().filter(|i| (i.1).value.is_value()).count()
    }

    /// Returns true iff the table is empty.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Given the `key`, return a mutable reference to the value.
    /// If there is no entry associated with the given key in the table,
    /// a `Item::None` value will be inserted.
    ///
    /// To insert to table, use `entry` to return a mutable reference
    /// and set it to the appropriate value.
    pub fn entry<'a>(&'a mut self, key: &str) -> &'a mut Item {
        let parsed_key = key.parse::<Key>().expect("invalid key");
        &mut self
            .items
            .entry(parsed_key.get().to_owned())
            .or_insert(TableKeyValue::new(key_repr(parsed_key.raw()), Item::None))
            .value
    }

    /// Returns an optional reference to an item given the key.
    pub fn get<'a>(&'a self, key: &str) -> Option<&'a Item> {
        self.items.get(key).map(|kv| &kv.value)
    }

    /// If a table has no key/value pairs and implicit, it will not be displayed.
    ///
    /// # Examples
    ///
    /// ```notrust
    /// [target."x86_64/windows.json".dependencies]
    /// ```
    ///
    /// In the document above, tables `target` and `target."x86_64/windows.json"` are implicit.
    ///
    /// ```
    /// use toml_edit::Document;
    /// let mut doc = "[a]\n[a.b]\n".parse::<Document>().expect("invalid toml");
    ///
    /// doc["a"].as_table_mut().unwrap().set_implicit(true);
    /// assert_eq!(doc.to_string(), "[a.b]\n");
    /// ```
    pub fn set_implicit(&mut self, implicit: bool) {
        self.implicit = implicit;
    }
}

impl Item {
    /// Sets `self` to the given item iff `self` is none and
    /// returns a mutable reference to `self`.
    pub fn or_insert(&mut self, item: Item) -> &mut Item {
        if self.is_none() {
            *self = item
        }
        self
    }
}
// TODO: This should be generated by macro or derive
/// Downcasting
impl Item {
    /// Casts `self` to value.
    pub fn as_value(&self) -> Option<&Value> {
        match *self {
            Item::Value(ref v) => Some(v),
            _ => None,
        }
    }
    /// Casts `self` to table.
    pub fn as_table(&self) -> Option<&Table> {
        match *self {
            Item::Table(ref t) => Some(t),
            _ => None,
        }
    }
    /// Casts `self` to array of tables.
    pub fn as_array_of_tables(&self) -> Option<&ArrayOfTables> {
        match *self {
            Item::ArrayOfTables(ref a) => Some(a),
            _ => None,
        }
    }
    /// Casts `self` to mutable value.
    pub fn as_value_mut(&mut self) -> Option<&mut Value> {
        match *self {
            Item::Value(ref mut v) => Some(v),
            _ => None,
        }
    }
    /// Casts `self` to mutable table.
    pub fn as_table_mut(&mut self) -> Option<&mut Table> {
        match *self {
            Item::Table(ref mut t) => Some(t),
            _ => None,
        }
    }
    /// Casts `self` to mutable array of tables.
    pub fn as_array_of_tables_mut(&mut self) -> Option<&mut ArrayOfTables> {
        match *self {
            Item::ArrayOfTables(ref mut a) => Some(a),
            _ => None,
        }
    }
    /// Returns true iff `self` is a value.
    pub fn is_value(&self) -> bool {
        self.as_value().is_some()
    }
    /// Returns true iff `self` is a table.
    pub fn is_table(&self) -> bool {
        self.as_table().is_some()
    }
    /// Returns true iff `self` is an array of tables.
    pub fn is_array_of_tables(&self) -> bool {
        self.as_array_of_tables().is_some()
    }
    /// Returns true iff `self` is `None`.
    pub fn is_none(&self) -> bool {
        match *self {
            Item::None => true,
            _ => false,
        }
    }

    // Duplicate Value downcasting API

    /// Casts `self` to integer.
    pub fn as_integer(&self) -> Option<i64> {
        self.as_value().and_then(Value::as_integer)
    }

    /// Returns true iff `self` is an integer.
    pub fn is_integer(&self) -> bool {
        self.as_integer().is_some()
    }

    /// Casts `self` to float.
    pub fn as_float(&self) -> Option<f64> {
        self.as_value().and_then(Value::as_float)
    }

    /// Returns true iff `self` is a float.
    pub fn is_float(&self) -> bool {
        self.as_float().is_some()
    }

    /// Casts `self` to boolean.
    pub fn as_bool(&self) -> Option<bool> {
        self.as_value().and_then(Value::as_bool)
    }

    /// Returns true iff `self` is a boolean.
    pub fn is_bool(&self) -> bool {
        self.as_bool().is_some()
    }

    /// Casts `self` to str.
    pub fn as_str(&self) -> Option<&str> {
        self.as_value().and_then(Value::as_str)
    }

    /// Returns true iff `self` is a string.
    pub fn is_str(&self) -> bool {
        self.as_str().is_some()
    }

    /// Casts `self` to date-time.
    pub fn as_date_time(&self) -> Option<&DateTime> {
        self.as_value().and_then(Value::as_date_time)
    }

    /// Returns true iff `self` is a date-time.
    pub fn is_date_time(&self) -> bool {
        self.as_date_time().is_some()
    }

    /// Casts `self` to array.
    pub fn as_array(&self) -> Option<&Array> {
        self.as_value().and_then(Value::as_array)
    }

    /// Casts `self` to mutable array.
    pub fn as_array_mut(&mut self) -> Option<&mut Array> {
        self.as_value_mut().and_then(Value::as_array_mut)
    }

    /// Returns true iff `self` is an array.
    pub fn is_array(&self) -> bool {
        self.as_array().is_some()
    }

    /// Casts `self` to inline table.
    pub fn as_inline_table(&self) -> Option<&InlineTable> {
        self.as_value().and_then(Value::as_inline_table)
    }

    /// Casts `self` to mutable inline table.
    pub fn as_inline_table_mut(&mut self) -> Option<&mut InlineTable> {
        self.as_value_mut().and_then(Value::as_inline_table_mut)
    }

    /// Returns true iff `self` is an inline table.
    pub fn is_inline_table(&self) -> bool {
        self.as_inline_table().is_some()
    }

    /// Casts `self` to either a table or an inline table.
    pub fn as_table_like(&self) -> Option<&dyn TableLike> {
        self.as_table()
            .map(|t| t as &dyn TableLike)
            .or_else(|| self.as_inline_table().map(|t| t as &dyn TableLike))
    }

    /// Returns true iff `self` is either a table, or an inline table.
    pub fn is_table_like(&self) -> bool {
        self.as_table_like().is_some()
    }
}

/// This trait represents either a `Table`, or an `InlineTable`.
pub trait TableLike {
    /// Returns an iterator over key/value pairs.
    fn iter(&self) -> Iter<'_>;
    /// Returns the number of nonempty items.
    fn len(&self) -> usize {
        self.iter().filter(|&(_, v)| !v.is_none()).count()
    }
    /// Returns true iff the table is empty.
    fn is_empty(&self) -> bool {
        self.len() == 0
    }
    /// Returns an optional reference to an item given the key.
    fn get<'s>(&'s self, key: &str) -> Option<&'s Item>;
}

impl TableLike for Table {
    /// Returns an iterator over all subitems, including `Item::None`.
    fn iter(&self) -> Iter<'_> {
        self.iter()
    }
    fn get<'s>(&'s self, key: &str) -> Option<&'s Item> {
        self.get(key)
    }
}

/// Returns a formatted value.
///
/// Since formatting is part of a `Value`, the right hand side of the
/// assignment needs to be decorated with a space before the value.
/// The `value` function does just that.
///
/// # Examples
/// ```rust
/// # use pretty_assertions::assert_eq;
/// # use toml_edit::*;
/// let mut table = Table::default();
/// let mut array = Array::default();
/// array.push("hello");
/// array.push("\\, world"); // \ is only allowed in a literal string
/// table["key1"] = value("value1");
/// table["key2"] = value(42);
/// table["key3"] = value(array);
/// assert_eq!(table.to_string(),
/// r#"key1 = "value1"
/// key2 = 42
/// key3 = ["hello", '\, world']
/// "#);
/// ```
pub fn value<V: Into<Value>>(v: V) -> Item {
    Item::Value(decorated(v.into(), " ", ""))
}

/// Returns an empty table.
pub fn table() -> Item {
    Item::Table(Table::new())
}

/// Returns an empty array of tables.
pub fn array() -> Item {
    Item::ArrayOfTables(ArrayOfTables::new())
}
<commit_msg>table: add decor() for retrieving the decor of a key rather than a value (#97)<commit_after>use crate::array_of_tables::ArrayOfTables;
use crate::decor::{Decor, InternalString, Repr};
use crate::formatted::{decorated, key_repr};
use crate::key::Key;
use crate::value::{sort_key_value_pairs, Array, DateTime, InlineTable, Value};
use linked_hash_map::LinkedHashMap;

// TODO: add method to convert a table into inline table

/// Type representing a TOML non-inline table
#[derive(Clone, Debug, Default)]
pub struct Table {
    pub(crate) items: KeyValuePairs,
    // comments/spaces before and after the header
    pub(crate) decor: Decor,
    // whether to hide an empty table
    pub(crate) implicit: bool,
    // used for putting tables back in their original order when serialising.
    // Will be None when the Table wasn't parsed from a file.
    pub(crate) position: Option<usize>,
}

pub(crate) type KeyValuePairs = LinkedHashMap<InternalString, TableKeyValue>;

/// Type representing either a value, a table, an array of tables, or none.
#[derive(Debug, Clone)]
pub enum Item {
    /// Type representing none.
    None,
    /// Type representing value.
    Value(Value),
    /// Type representing table.
    Table(Table),
    /// Type representing array of tables.
    ArrayOfTables(ArrayOfTables),
}

impl Default for Item {
    fn default() -> Self {
        Item::None
    }
}

// TODO: make pub(crate)
#[doc(hidden)]
#[derive(Debug, Clone)]
pub struct TableKeyValue {
    pub(crate) key: Repr,
    pub(crate) value: Item,
}

impl TableKeyValue {
    pub(crate) fn new(key: Repr, value: Item) -> Self {
        TableKeyValue { key, value }
    }
}

/// An iterator type over `Table`'s key/value pairs.
pub type Iter<'a> = Box<dyn Iterator<Item = (&'a str, &'a Item)> + 'a>;

impl Table {
    /// Creates an empty table.
    pub fn new() -> Self {
        Self::with_decor_and_pos(Decor::new("\n", ""), None)
    }

    pub(crate) fn with_pos(position: Option<usize>) -> Self {
        Self {
            position,
            ..Default::default()
        }
    }

    pub(crate) fn with_decor_and_pos(decor: Decor, position: Option<usize>) -> Self {
        Self {
            decor,
            position,
            ..Default::default()
        }
    }

    /// Returns true iff the table contains an item with the given key.
    pub fn contains_key(&self, key: &str) -> bool {
        if let Some(kv) = self.items.get(key) {
            !kv.value.is_none()
        } else {
            false
        }
    }

    /// Returns true iff the table contains a table with the given key.
    pub fn contains_table(&self, key: &str) -> bool {
        if let Some(kv) = self.items.get(key) {
            kv.value.is_table()
        } else {
            false
        }
    }

    /// Returns true iff the table contains a value with the given key.
    pub fn contains_value(&self, key: &str) -> bool {
        if let Some(kv) = self.items.get(key) {
            kv.value.is_value()
        } else {
            false
        }
    }

    /// Returns true iff the table contains an array of tables with the given key.
    pub fn contains_array_of_tables(&self, key: &str) -> bool {
        if let Some(kv) = self.items.get(key) {
            kv.value.is_array_of_tables()
        } else {
            false
        }
    }

    /// Returns an iterator over all key/value pairs, including empty.
    pub fn iter(&self) -> Iter<'_> {
        Box::new(self.items.iter().map(|(key, kv)| (&key[..], &kv.value)))
    }

    /// Removes an item given the key.
    pub fn remove(&mut self, key: &str) -> Option<Item> {
        self.items.remove(key).map(|kv| kv.value)
    }

    /// Sorts Key/Value Pairs of the table,
    /// doesn't affect subtables or subarrays.
    pub fn sort_values(&mut self) {
        sort_key_value_pairs(&mut self.items);
    }

    /// Returns the number of non-empty items in the table.
    pub fn len(&self) -> usize {
        self.items.iter().filter(|i| !(i.1).value.is_none()).count()
    }

    /// Returns the number of key/value pairs in the table.
    pub fn values_len(&self) -> usize {
        self.items.iter().filter(|i| (i.1).value.is_value()).count()
    }

    /// Returns true iff the table is empty.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Given the `key`, return a mutable reference to the value.
    /// If there is no entry associated with the given key in the table,
    /// a `Item::None` value will be inserted.
    ///
    /// To insert to table, use `entry` to return a mutable reference
    /// and set it to the appropriate value.
    pub fn entry<'a>(&'a mut self, key: &str) -> &'a mut Item {
        let parsed_key = key.parse::<Key>().expect("invalid key");
        &mut self
            .items
            .entry(parsed_key.get().to_owned())
            .or_insert(TableKeyValue::new(key_repr(parsed_key.raw()), Item::None))
            .value
    }

    /// Returns an optional reference to an item given the key.
    pub fn get<'a>(&'a self, key: &str) -> Option<&'a Item> {
        self.items.get(key).map(|kv| &kv.value)
    }

    /// If a table has no key/value pairs and implicit, it will not be displayed.
    ///
    /// # Examples
    ///
    /// ```notrust
    /// [target."x86_64/windows.json".dependencies]
    /// ```
    ///
    /// In the document above, tables `target` and `target."x86_64/windows.json"` are implicit.
    ///
    /// ```
    /// use toml_edit::Document;
    /// let mut doc = "[a]\n[a.b]\n".parse::<Document>().expect("invalid toml");
    ///
    /// doc["a"].as_table_mut().unwrap().set_implicit(true);
    /// assert_eq!(doc.to_string(), "[a.b]\n");
    /// ```
    pub fn set_implicit(&mut self, implicit: bool) {
        self.implicit = implicit;
    }

    /// Returns the decor associated with a given key of the table.
    pub fn decor(&self, key: &str) -> Option<&Decor> {
        self.items.get(key).map(|kv| &kv.key.decor)
    }
}

impl Item {
    /// Sets `self` to the given item iff `self` is none and
    /// returns a mutable reference to `self`.
    pub fn or_insert(&mut self, item: Item) -> &mut Item {
        if self.is_none() {
            *self = item
        }
        self
    }
}
// TODO: This should be generated by macro or derive
/// Downcasting
impl Item {
    /// Casts `self` to value.
    pub fn as_value(&self) -> Option<&Value> {
        match *self {
            Item::Value(ref v) => Some(v),
            _ => None,
        }
    }
    /// Casts `self` to table.
    pub fn as_table(&self) -> Option<&Table> {
        match *self {
            Item::Table(ref t) => Some(t),
            _ => None,
        }
    }
    /// Casts `self` to array of tables.
    pub fn as_array_of_tables(&self) -> Option<&ArrayOfTables> {
        match *self {
            Item::ArrayOfTables(ref a) => Some(a),
            _ => None,
        }
    }
    /// Casts `self` to mutable value.
    pub fn as_value_mut(&mut self) -> Option<&mut Value> {
        match *self {
            Item::Value(ref mut v) => Some(v),
            _ => None,
        }
    }
    /// Casts `self` to mutable table.
    pub fn as_table_mut(&mut self) -> Option<&mut Table> {
        match *self {
            Item::Table(ref mut t) => Some(t),
            _ => None,
        }
    }
    /// Casts `self` to mutable array of tables.
    pub fn as_array_of_tables_mut(&mut self) -> Option<&mut ArrayOfTables> {
        match *self {
            Item::ArrayOfTables(ref mut a) => Some(a),
            _ => None,
        }
    }
    /// Returns true iff `self` is a value.
    pub fn is_value(&self) -> bool {
        self.as_value().is_some()
    }
    /// Returns true iff `self` is a table.
    pub fn is_table(&self) -> bool {
        self.as_table().is_some()
    }
    /// Returns true iff `self` is an array of tables.
    pub fn is_array_of_tables(&self) -> bool {
        self.as_array_of_tables().is_some()
    }
    /// Returns true iff `self` is `None`.
    pub fn is_none(&self) -> bool {
        match *self {
            Item::None => true,
            _ => false,
        }
    }

    // Duplicate Value downcasting API

    /// Casts `self` to integer.
    pub fn as_integer(&self) -> Option<i64> {
        self.as_value().and_then(Value::as_integer)
    }

    /// Returns true iff `self` is an integer.
    pub fn is_integer(&self) -> bool {
        self.as_integer().is_some()
    }

    /// Casts `self` to float.
    pub fn as_float(&self) -> Option<f64> {
        self.as_value().and_then(Value::as_float)
    }

    /// Returns true iff `self` is a float.
    pub fn is_float(&self) -> bool {
        self.as_float().is_some()
    }

    /// Casts `self` to boolean.
    pub fn as_bool(&self) -> Option<bool> {
        self.as_value().and_then(Value::as_bool)
    }

    /// Returns true iff `self` is a boolean.
    pub fn is_bool(&self) -> bool {
        self.as_bool().is_some()
    }

    /// Casts `self` to str.
    pub fn as_str(&self) -> Option<&str> {
        self.as_value().and_then(Value::as_str)
    }

    /// Returns true iff `self` is a string.
    pub fn is_str(&self) -> bool {
        self.as_str().is_some()
    }

    /// Casts `self` to date-time.
    pub fn as_date_time(&self) -> Option<&DateTime> {
        self.as_value().and_then(Value::as_date_time)
    }

    /// Returns true iff `self` is a date-time.
    pub fn is_date_time(&self) -> bool {
        self.as_date_time().is_some()
    }

    /// Casts `self` to array.
    pub fn as_array(&self) -> Option<&Array> {
        self.as_value().and_then(Value::as_array)
    }

    /// Casts `self` to mutable array.
    pub fn as_array_mut(&mut self) -> Option<&mut Array> {
        self.as_value_mut().and_then(Value::as_array_mut)
    }

    /// Returns true iff `self` is an array.
    pub fn is_array(&self) -> bool {
        self.as_array().is_some()
    }

    /// Casts `self` to inline table.
    pub fn as_inline_table(&self) -> Option<&InlineTable> {
        self.as_value().and_then(Value::as_inline_table)
    }

    /// Casts `self` to mutable inline table.
    pub fn as_inline_table_mut(&mut self) -> Option<&mut InlineTable> {
        self.as_value_mut().and_then(Value::as_inline_table_mut)
    }

    /// Returns true iff `self` is an inline table.
    pub fn is_inline_table(&self) -> bool {
        self.as_inline_table().is_some()
    }

    /// Casts `self` to either a table or an inline table.
    pub fn as_table_like(&self) -> Option<&dyn TableLike> {
        self.as_table()
            .map(|t| t as &dyn TableLike)
            .or_else(|| self.as_inline_table().map(|t| t as &dyn TableLike))
    }

    /// Returns true iff `self` is either a table, or an inline table.
    pub fn is_table_like(&self) -> bool {
        self.as_table_like().is_some()
    }
}

/// This trait represents either a `Table`, or an `InlineTable`.
pub trait TableLike {
    /// Returns an iterator over key/value pairs.
    fn iter(&self) -> Iter<'_>;
    /// Returns the number of nonempty items.
    fn len(&self) -> usize {
        self.iter().filter(|&(_, v)| !v.is_none()).count()
    }
    /// Returns true iff the table is empty.
    fn is_empty(&self) -> bool {
        self.len() == 0
    }
    /// Returns an optional reference to an item given the key.
    fn get<'s>(&'s self, key: &str) -> Option<&'s Item>;
}

impl TableLike for Table {
    /// Returns an iterator over all subitems, including `Item::None`.
    fn iter(&self) -> Iter<'_> {
        self.iter()
    }
    fn get<'s>(&'s self, key: &str) -> Option<&'s Item> {
        self.get(key)
    }
}

/// Returns a formatted value.
///
/// Since formatting is part of a `Value`, the right hand side of the
/// assignment needs to be decorated with a space before the value.
/// The `value` function does just that.
///
/// # Examples
/// ```rust
/// # use pretty_assertions::assert_eq;
/// # use toml_edit::*;
/// let mut table = Table::default();
/// let mut array = Array::default();
/// array.push("hello");
/// array.push("\\, world"); // \ is only allowed in a literal string
/// table["key1"] = value("value1");
/// table["key2"] = value(42);
/// table["key3"] = value(array);
/// assert_eq!(table.to_string(),
/// r#"key1 = "value1"
/// key2 = 42
/// key3 = ["hello", '\, world']
/// "#);
/// ```
pub fn value<V: Into<Value>>(v: V) -> Item {
    Item::Value(decorated(v.into(), " ", ""))
}

/// Returns an empty table.
pub fn table() -> Item {
    Item::Table(Table::new())
}

/// Returns an empty array of tables.
pub fn array() -> Item {
    Item::ArrayOfTables(ArrayOfTables::new())
}
<|endoftext|>


<commit_before>#![cfg(test)]

#[cfg(feature = "serialization-serde")]
extern crate serde_json;

use ring::digest::{Algorithm, Context, SHA512};

use hashutils::{HashUtils, Hashable};
use merkletree::MerkleTree;
use proof::Positioned;

#[allow(non_upper_case_globals)]
static digest: &'static Algorithm = &SHA512;

#[test]
fn test_from_str_vec() {
    let values = vec!["one", "two", "three", "four"];

    let hashes = vec![
        digest.hash_leaf(&values[0].as_bytes()),
        digest.hash_leaf(&values[1].as_bytes()),
        digest.hash_leaf(&values[2].as_bytes()),
        digest.hash_leaf(&values[3].as_bytes()),
    ];

    let count = values.len();
    let tree = MerkleTree::from_vec(digest, values);

    let h01 = digest.hash_nodes(&hashes[0], &hashes[1]);
    let h23 = digest.hash_nodes(&hashes[2], &hashes[3]);

    let root_hash = digest.hash_nodes(&h01, &h23);

    assert_eq!(tree.count(), count);
    assert_eq!(tree.height(), 2);
    assert_eq!(tree.root_hash().as_slice(), root_hash.as_ref());
}

#[test]
fn test_from_vec_empty() {
    let values: Vec<Vec<u8>> = vec![];
    let tree = MerkleTree::from_vec(digest, values);
    let empty_hash: Vec<u8> = digest.hash_empty().as_ref().into();
    let root_hash = tree.root_hash().clone();

    assert_eq!(root_hash, empty_hash);
}

#[test]
fn test_from_vec1() {
    let values = vec!["hello, world".to_string()];
    let tree = MerkleTree::from_vec(digest, values);

    let root_hash = &digest.hash_leaf(&"hello, world".as_bytes());

    assert_eq!(tree.count(), 1);
    assert_eq!(tree.height(), 0);
    assert_eq!(tree.root_hash().as_slice(), root_hash.as_ref());
}

#[test]
fn test_from_vec3() {
    let values = vec![vec![1], vec![2], vec![3]];
    let tree = MerkleTree::from_vec(digest, values);

    let hashes = vec![
        digest.hash_leaf(&vec![1]),
        digest.hash_leaf(&vec![2]),
        digest.hash_leaf(&vec![3]),
    ];

    let h01 = digest.hash_nodes(&hashes[0], &hashes[1]);
    let h2 = &hashes[2];
    let root_hash = &digest.hash_nodes(&h01, h2);

    assert_eq!(tree.count(), 3);
    assert_eq!(tree.height(), 2);
    assert_eq!(tree.root_hash().as_slice(), root_hash.as_ref());
}

#[test]
fn test_from_vec9() {
    let values = (1..10).map(|x| vec![x]).collect::<Vec<_>>();
    let tree = MerkleTree::from_vec(digest, values.clone());

    let hashes = values
        .iter()
        .map(|v| digest.hash_leaf(v))
        .collect::<Vec<_>>();

    let h01 = digest.hash_nodes(&hashes[0], &hashes[1]);
    let h23 = digest.hash_nodes(&hashes[2], &hashes[3]);
    let h45 = digest.hash_nodes(&hashes[4], &hashes[5]);
    let h67 = digest.hash_nodes(&hashes[6], &hashes[7]);
    let h8 = &hashes[8];
    let h0123 = digest.hash_nodes(&h01, &h23);
    let h4567 = digest.hash_nodes(&h45, &h67);
    let h1to7 = digest.hash_nodes(&h0123, &h4567);

    let root_hash = &digest.hash_nodes(&h1to7, h8);

    assert_eq!(tree.count(), 9);
    assert_eq!(tree.height(), 4);
    assert_eq!(tree.root_hash().as_slice(), root_hash.as_ref());
}

#[test]
fn test_valid_proof() {
    let values = (1..10).map(|x| vec![x]).collect::<Vec<_>>();
    let tree = MerkleTree::from_vec(digest, values.clone());
    let root_hash = tree.root_hash();

    for value in values {
        let proof = tree.gen_proof(value);
        let is_valid = proof.map(|p| p.validate(&root_hash)).unwrap_or(false);

        assert!(is_valid);
    }
}

#[test]
fn test_valid_proof_str() {
    let values = vec!["Hello", "my", "name", "is", "Rusty"];
    let tree = MerkleTree::from_vec(digest, values);
    let root_hash = tree.root_hash();

    let value = "Rusty";

    let proof = tree.gen_proof(&value);
    let is_valid = proof.map(|p| p.validate(&root_hash)).unwrap_or(false);

    assert!(is_valid);
}

#[test]
fn test_wrong_proof() {
    let values1 = vec![vec![1], vec![2], vec![3], vec![4]];
    let tree1 = MerkleTree::from_vec(digest, values1.clone());

    let values2 = vec![vec![4], vec![5], vec![6], vec![7]];
    let tree2 = MerkleTree::from_vec(digest, values2.clone());

    let root_hash = tree2.root_hash();

    for value in values1 {
        let proof = tree1.gen_proof(value);
        let is_valid = proof.map(|p| p.validate(root_hash)).unwrap_or(false);

        assert_eq!(is_valid, false);
    }
}

#[test]
fn test_mutate_proof_first_lemma() {
    let values = (1..10).map(|x| vec![x]).collect::<Vec<_>>();
    let tree = MerkleTree::from_vec(digest, values.clone());
    let root_hash = tree.root_hash();

    let mut i = 0;

    for value in values {
        let mut proof = tree.gen_proof(value).unwrap();

        match i % 3 {
            0 => {
                proof.lemma.node_hash = vec![1, 2, 3];
            }
            1 => {
                proof.lemma.sibling_hash = Some(Positioned::Left(vec![1, 2, 3]));
            }
            _ => {
                proof.lemma.sibling_hash = Some(Positioned::Right(vec![1, 2, 3]));
            }
        }

        let is_valid = proof.validate(root_hash);
        assert_eq!(is_valid, false);

        i += 1;
    }
}

#[test]
fn test_tree_iter() {
    let values = (1..10).map(|x| vec![x]).collect::<Vec<_>>();
    let tree = MerkleTree::from_vec(digest, values.clone());
    let iter = tree.iter().map(|x| x.clone()).collect::<Vec<_>>();

    assert_eq!(values, iter);
}

#[test]
fn test_tree_into_iter() {
    let values = (1..10).map(|x| vec![x]).collect::<Vec<_>>();
    let tree = MerkleTree::from_vec(digest, values.clone());
    let iter = tree.into_iter().map(|x| x.clone()).collect::<Vec<_>>();

    assert_eq!(values, iter);
}

#[test]
fn test_tree_into_iter_loop() {
    let values = (1..10).map(|x| vec![x]).collect::<Vec<_>>();
    let tree = MerkleTree::from_vec(digest, values.clone());

    let mut collected = Vec::new();

    for value in tree {
        collected.push(value);
    }

    assert_eq!(values, collected);
}

#[test]
fn test_tree_into_iter_loop_borrow() {
    let values = (1..10).map(|x| vec![x]).collect::<Vec<_>>();
    let tree = MerkleTree::from_vec(digest, values.clone());

    let mut collected = Vec::new();

    for value in &tree {
        collected.push(value);
    }

    let refs = values.iter().collect::<Vec<_>>();

    assert_eq!(refs, collected);
}

pub struct PublicKey {
    zero_values: Vec<Vec<u8>>,
    one_values: Vec<Vec<u8>>,
}

impl PublicKey {
    pub fn new(zero_values: Vec<Vec<u8>>, one_values: Vec<Vec<u8>>) -> Self {
        PublicKey {
            zero_values: zero_values,
            one_values: one_values,
        }
    }

    pub fn to_bytes(&self) -> Vec<u8> {
        self.zero_values
            .iter()
            .chain(self.one_values.iter())
            .fold(Vec::new(), |mut acc, i| {
                acc.append(&mut i.clone());
                acc
            })
    }
}

impl Hashable for PublicKey {
    fn update_context(&self, context: &mut Context) {
        context.update(&self.to_bytes());
    }
}

#[test]
fn test_custom_hashable_impl() {
    let keys = (0..10)
        .map(|i| {
            let zero_values = vec![vec![i], vec![i + 1], vec![i + 2]];
            let one_values = vec![vec![i + 3], vec![i + 4], vec![i + 5]];

            PublicKey::new(zero_values, one_values)
        })
        .collect::<Vec<_>>();

    let tree = MerkleTree::from_vec(digest, keys);

    assert_eq!(tree.count(), 10);
    assert_eq!(tree.height(), 4);
}

#[cfg(feature = "serialization-serde")]
#[test]
fn test_serialize_proof_with_serde() {
    let values = (1..10).map(|x| vec![x]).collect::<Vec<_>>();
    let tree = MerkleTree::from_vec(digest, values);
    let proof = tree.gen_proof(vec![5]);

    let serialized = serde_json::to_string(&proof).expect("serialize proof");

    assert_eq!(
        proof,
        serde_json::from_str(&serialized).expect("deserialize proof")
    );
}
<commit_msg>Fix clippy warnings in tests<commit_after>#![cfg(test)]

#[cfg(feature = "serialization-serde")]
extern crate serde_json;

use ring::digest::{Algorithm, Context, SHA512};

use hashutils::{HashUtils, Hashable};
use merkletree::MerkleTree;
use proof::Positioned;

#[allow(non_upper_case_globals)]
static digest: &'static Algorithm = &SHA512;

#[test]
fn test_from_str_vec() {
    let values = vec!["one", "two", "three", "four"];

    let hashes = vec![
        digest.hash_leaf(&values[0].as_bytes()),
        digest.hash_leaf(&values[1].as_bytes()),
        digest.hash_leaf(&values[2].as_bytes()),
        digest.hash_leaf(&values[3].as_bytes()),
    ];

    let count = values.len();
    let tree = MerkleTree::from_vec(digest, values);

    let h01 = digest.hash_nodes(&hashes[0], &hashes[1]);
    let h23 = digest.hash_nodes(&hashes[2], &hashes[3]);

    let root_hash = digest.hash_nodes(&h01, &h23);

    assert_eq!(tree.count(), count);
    assert_eq!(tree.height(), 2);
    assert_eq!(tree.root_hash().as_slice(), root_hash.as_ref());
}

#[test]
fn test_from_vec_empty() {
    let values: Vec<Vec<u8>> = vec![];
    let tree = MerkleTree::from_vec(digest, values);
    let empty_hash: Vec<u8> = digest.hash_empty().as_ref().into();
    let root_hash = tree.root_hash().clone();

    assert_eq!(root_hash, empty_hash);
}

#[test]
fn test_from_vec1() {
    let values = vec!["hello, world".to_string()];
    let tree = MerkleTree::from_vec(digest, values);

    let root_hash = &digest.hash_leaf(b"hello, world");

    assert_eq!(tree.count(), 1);
    assert_eq!(tree.height(), 0);
    assert_eq!(tree.root_hash().as_slice(), root_hash.as_ref());
}

#[test]
fn test_from_vec3() {
    let values = vec![vec![1], vec![2], vec![3]];
    let tree = MerkleTree::from_vec(digest, values);

    let hashes = vec![
        digest.hash_leaf(&vec![1]),
        digest.hash_leaf(&vec![2]),
        digest.hash_leaf(&vec![3]),
    ];

    let h01 = digest.hash_nodes(&hashes[0], &hashes[1]);
    let h2 = &hashes[2];
    let root_hash = &digest.hash_nodes(&h01, h2);

    assert_eq!(tree.count(), 3);
    assert_eq!(tree.height(), 2);
    assert_eq!(tree.root_hash().as_slice(), root_hash.as_ref());
}

#[test]
fn test_from_vec9() {
    let values = (1..10).map(|x| vec![x]).collect::<Vec<_>>();
    let tree = MerkleTree::from_vec(digest, values.clone());

    let hashes = values
        .iter()
        .map(|v| digest.hash_leaf(v))
        .collect::<Vec<_>>();

    let h01 = digest.hash_nodes(&hashes[0], &hashes[1]);
    let h23 = digest.hash_nodes(&hashes[2], &hashes[3]);
    let h45 = digest.hash_nodes(&hashes[4], &hashes[5]);
    let h67 = digest.hash_nodes(&hashes[6], &hashes[7]);
    let h8 = &hashes[8];
    let h0123 = digest.hash_nodes(&h01, &h23);
    let h4567 = digest.hash_nodes(&h45, &h67);
    let h1to7 = digest.hash_nodes(&h0123, &h4567);

    let root_hash = &digest.hash_nodes(&h1to7, h8);

    assert_eq!(tree.count(), 9);
    assert_eq!(tree.height(), 4);
    assert_eq!(tree.root_hash().as_slice(), root_hash.as_ref());
}

#[test]
fn test_valid_proof() {
    let values = (1..10).map(|x| vec![x]).collect::<Vec<_>>();
    let tree = MerkleTree::from_vec(digest, values.clone());
    let root_hash = tree.root_hash();

    for value in values {
        let proof = tree.gen_proof(value);
        let is_valid = proof.map(|p| p.validate(&root_hash)).unwrap_or(false);

        assert!(is_valid);
    }
}

#[test]
fn test_valid_proof_str() {
    let values = vec!["Hello", "my", "name", "is", "Rusty"];
    let tree = MerkleTree::from_vec(digest, values);
    let root_hash = tree.root_hash();

    let value = "Rusty";

    let proof = tree.gen_proof(&value);
    let is_valid = proof.map(|p| p.validate(&root_hash)).unwrap_or(false);

    assert!(is_valid);
}

#[test]
fn test_wrong_proof() {
    let values1 = vec![vec![1], vec![2], vec![3], vec![4]];
    let tree1 = MerkleTree::from_vec(digest, values1.clone());

    let values2 = vec![vec![4], vec![5], vec![6], vec![7]];
    let tree2 = MerkleTree::from_vec(digest, values2.clone());

    let root_hash = tree2.root_hash();

    for value in values1 {
        let proof = tree1.gen_proof(value);
        let is_valid = proof.map(|p| p.validate(root_hash)).unwrap_or(false);

        assert_eq!(is_valid, false);
    }
}

#[test]
fn test_mutate_proof_first_lemma() {
    let values = (1..10).map(|x| vec![x]).collect::<Vec<_>>();
    let tree = MerkleTree::from_vec(digest, values.clone());
    let root_hash = tree.root_hash();

    for (i, value) in values.into_iter().enumerate() {
        let mut proof = tree.gen_proof(value).unwrap();

        match i % 3 {
            0 => {
                proof.lemma.node_hash = vec![1, 2, 3];
            }
            1 => {
                proof.lemma.sibling_hash = Some(Positioned::Left(vec![1, 2, 3]));
            }
            _ => {
                proof.lemma.sibling_hash = Some(Positioned::Right(vec![1, 2, 3]));
            }
        }

        let is_valid = proof.validate(root_hash);
        assert_eq!(is_valid, false);
    }
}

#[test]
fn test_tree_iter() {
    let values = (1..10).map(|x| vec![x]).collect::<Vec<_>>();
    let tree = MerkleTree::from_vec(digest, values.clone());
    let iter = tree.iter().cloned().collect::<Vec<_>>();

    assert_eq!(values, iter);
}

#[test]
fn test_tree_into_iter() {
    let values = (1..10).map(|x| vec![x]).collect::<Vec<_>>();
    let tree = MerkleTree::from_vec(digest, values.clone());
    let iter = tree.iter().cloned().collect::<Vec<_>>();

    assert_eq!(values, iter);
}

#[test]
fn test_tree_into_iter_loop() {
    let values = (1..10).map(|x| vec![x]).collect::<Vec<_>>();
    let tree = MerkleTree::from_vec(digest, values.clone());

    let mut collected = Vec::new();

    for value in tree {
        collected.push(value);
    }

    assert_eq!(values, collected);
}

#[test]
fn test_tree_into_iter_loop_borrow() {
    let values = (1..10).map(|x| vec![x]).collect::<Vec<_>>();
    let tree = MerkleTree::from_vec(digest, values.clone());

    let mut collected = Vec::new();

    for value in &tree {
        collected.push(value);
    }

    let refs = values.iter().collect::<Vec<_>>();

    assert_eq!(refs, collected);
}

pub struct PublicKey {
    zero_values: Vec<Vec<u8>>,
    one_values: Vec<Vec<u8>>,
}

impl PublicKey {
    pub fn new(zero_values: Vec<Vec<u8>>, one_values: Vec<Vec<u8>>) -> Self {
        PublicKey {
            zero_values,
            one_values,
        }
    }

    pub fn to_bytes(&self) -> Vec<u8> {
        self.zero_values
            .iter()
            .chain(self.one_values.iter())
            .fold(Vec::new(), |mut acc, i| {
                acc.append(&mut i.clone());
                acc
            })
    }
}

impl Hashable for PublicKey {
    fn update_context(&self, context: &mut Context) {
        context.update(&self.to_bytes());
    }
}

#[test]
fn test_custom_hashable_impl() {
    let keys = (0..10)
        .map(|i| {
            let zero_values = vec![vec![i], vec![i + 1], vec![i + 2]];
            let one_values = vec![vec![i + 3], vec![i + 4], vec![i + 5]];

            PublicKey::new(zero_values, one_values)
        })
        .collect::<Vec<_>>();

    let tree = MerkleTree::from_vec(digest, keys);

    assert_eq!(tree.count(), 10);
    assert_eq!(tree.height(), 4);
}

#[cfg(feature = "serialization-serde")]
#[test]
fn test_serialize_proof_with_serde() {
    let values = (1..10).map(|x| vec![x]).collect::<Vec<_>>();
    let tree = MerkleTree::from_vec(digest, values);
    let proof = tree.gen_proof(vec![5]);

    let serialized = serde_json::to_string(&proof).expect("serialize proof");

    assert_eq!(
        proof,
        serde_json::from_str(&serialized).expect("deserialize proof")
    );
}
<|endoftext|>