<commit_before>use std::cmp;
use rand::{
    Rng,
    seq::SliceRandom,
    thread_rng,
};
use crate::{
    game::GameState,
    ship::{
        Ship,
        ShipDirection,
    },
    space::Space,
};

pub struct Player {
    pub is_cpu: bool,
    spaces: Vec<Space>,
    ships: Vec<Ship>,
    grid_size: [u8; 2],
    grid_cursor: [u8; 2],
    pub temp_ship_pos: Vec<[u8; 2]>,
    pub temp_ship_dir: ShipDirection,
}

impl Player {
    pub fn new(grid_size: [u8; 2], is_cpu: bool) -> Player {
        let spaces_x = grid_size[0] as usize;
        let spaces_y = grid_size[1] as usize;
        let mut spaces = Vec::with_capacity(spaces_x * spaces_y);

        for col in 0..grid_size[0] {
            for row in 0..grid_size[1] {
                spaces.push(Space::new([col, row]));
            }
        }

        Player {
            is_cpu: is_cpu,
            spaces: spaces,
            ships: vec![],
            grid_size: grid_size,
            grid_cursor: [0, 0],
            temp_ship_pos: vec![[0, 0], [1, 0]],
            temp_ship_dir: ShipDirection::West,
        }
    }

    /// Selects a space and checks the status of ships if there's a hit.
    pub fn select_space(&mut self, pos: &[u8; 2]) -> GameState {
        let mut game_state = GameState::Active;
        let ship_hit = self.ships.iter().position(|s| s.pos().contains(pos));

        let space_index = self.space_index(pos);
        self.spaces[space_index].set_checked(ship_hit.is_some());

        if let Some(ship) = ship_hit {
            let ship_sunk = self.ships[ship].pos().iter()
                .all(|p| self.space(p).is_hit());

            if ship_sunk {
                self.ships[ship].sink();
            }

            let all_sunk = self.ships.iter().all(|s| !s.is_active());
            if all_sunk {
                game_state = GameState::Over;
            }
        }

        game_state
    }

    /// Determines the next space a CPU player will select.
    pub fn cpu_select_space(&self) -> [u8; 2] {
        let mut rng = thread_rng();
        let mut select = Vec::new();
        let mut directions = [
            ShipDirection::North,
            ShipDirection::East,
            ShipDirection::South,
            ShipDirection::West
        ];

        directions.shuffle(&mut rng);

        let mut hit_spaces = self.spaces.iter()
            .filter(|s| s.is_hit() && self.ship(s.pos()).unwrap().is_active())
            .collect::<Vec<&Space>>();

        hit_spaces.shuffle(&mut rng);

        // Check for a line of hit spaces.
        for space in &hit_spaces {
            for direction in &directions {
                let unchecked = self.find_unchecked_space(
                    space.pos(),
                    *direction,
                    true
                );

                if let Some(pos) = unchecked {
                    if !select.contains(&pos) {
                        select.push(pos);
                    }
                }
            }
        }

        // If a hit space was found, but no hit spaces next to it, find any
        // unchecked spaces next to it.
        if hit_spaces.len() > 0 && select.is_empty() {
            for direction in &directions {
                let unchecked = self.find_unchecked_space(
                    hit_spaces[0].pos(),
                    *direction,
                    false
                );

                if let Some(pos) = unchecked {
                    select.push(pos);
                }
            }
        }

        // If no spaces have been selected, just select any available space.
        if select.is_empty() {
            let pos: [u8; 2] = loop {
                let space = self.rng_pos();

                if self.space(&space).is_unchecked() {
                    break space;
                }
            };

            select.push(pos);
        }

        if select.len() > 1 {
            select.shuffle(&mut rng);
        }

        select[0]
    }

    fn rng_pos(&self) -> [u8; 2] {
        let mut rng = thread_rng();

        [
            rng.gen_range(0, self.grid_size[0]),
            rng.gen_range(0, self.grid_size[1]),
        ]
    }

    pub fn move_temp_ship(&mut self, direction: ShipDirection) {
        let old_head = self.temp_ship_pos[0];

        if let Some(new_head) = self.movement(&old_head, direction) {
            if let Some(ship) = self.get_ship_position(
                new_head,
                self.temp_ship_dir,
                self.temp_ship_pos.len() as u8
            ) {
                self.temp_ship_pos = ship;
            }
        }
    }

    pub fn place_temp_ship(&mut self) {
        let ship = self.temp_ship_pos.clone();

        if self.valid_ship_position(&ship) {
            self.ships.push(Ship::new(ship));

            self.temp_ship_dir = ShipDirection::West;
            self.temp_ship_pos = self.get_ship_position(
                [0, 0],
                self.temp_ship_dir,
                self.temp_ship_pos.len() as u8 + 1
            ).unwrap();
        }
    }

    /// Rotates a ship during the ship placement game state.
    pub fn rotate_temp_ship(&mut self) {
        let ship_len = self.temp_ship_pos.len() as u8;
        let dir = match self.temp_ship_dir {
            ShipDirection::North => ShipDirection::East,
            ShipDirection::East => ShipDirection::South,
            ShipDirection::South => ShipDirection::West,
            ShipDirection::West => ShipDirection::North,
        };

        // If the current starting position would cause the rotation to position
        // the ship partially out of bounds, adjust the starting position such
        // that the ship will be entirely within bounds.
        let old_start_pos = self.temp_ship_pos[0];
        let start_pos = match dir {
            ShipDirection::North => [
                self.temp_ship_pos[0][0],
                cmp::min(old_start_pos[1], self.grid_size[1] - ship_len),
            ],
            ShipDirection::East => [
                cmp::max(old_start_pos[0], ship_len - 1),
                self.temp_ship_pos[0][1],
            ],
            ShipDirection::South => [
                self.temp_ship_pos[0][0],
                cmp::max(old_start_pos[1], ship_len - 1),
            ],
            ShipDirection::West => [
                cmp::min(old_start_pos[0], self.grid_size[0] - ship_len),
                self.temp_ship_pos[0][1],
            ],
        };

        if let Some(ship) = self.get_ship_position(start_pos, dir, ship_len) {
            self.temp_ship_pos = ship;
            self.temp_ship_dir = dir;
        }
    }

    pub fn cpu_place_ships(&mut self) {
        for length in 2..6 {
            let ship_pos = self.cpu_place_ship(length);
            self.ships.push(Ship::new(ship_pos));
        }
    }

    /// RNGs ship locations for CPU players.
    fn cpu_place_ship(&self, length: u8) -> Vec<[u8; 2]> {
        let mut rng = thread_rng();

        // RNG a position and direction, then make sure it's valid.
        loop {
            let pos = self.rng_pos();
            let direction = match rng.gen_range(0, 4) {
                0 => ShipDirection::North,
                1 => ShipDirection::East,
                2 => ShipDirection::South,
                3 => ShipDirection::West,
                _ => unreachable!()
            };

            if let Some(s) = self.get_ship_position(pos, direction, length) {
                let valid = self.valid_ship_position(&s);

                if valid {
                    break s;
                }
            }
        }
    }

    /// Returns a ship position, given its head position, direction and length.
    ///
    /// `direction` refers to the direction the ship is facing, not the
    /// direction in which positions are generated.
    /// Returns `None` if the resulting ship position would not be contained
    /// within the grid.
    pub fn get_ship_position(
        &self,
        head: [u8; 2],
        direction: ShipDirection,
        length: u8
    ) -> Option<Vec<[u8; 2]>> {
        let valid = match direction {
            ShipDirection::North => head[1] + length <= self.grid_size[1],
            ShipDirection::East => head[0] >= length - 1,
            ShipDirection::South => head[1] >= length - 1,
            ShipDirection::West => head[0] + length <= self.grid_size[0],
        };

        let ship_opt = if valid {
            let mut ship = vec![head];

            for pos in 1..length {
                let pos_u8 = pos as u8;
                let space = match direction {
                    ShipDirection::North => [head[0], head[1] + pos_u8],
                    ShipDirection::East => [head[0] - pos_u8, head[1]],
                    ShipDirection::South => [head[0], head[1] - pos_u8],
                    ShipDirection::West => [head[0] + pos_u8, head[1]],
                };
                ship.push(space);
            }
            Some(ship)
        } else {
            None
        };

        ship_opt
    }

    /// Checks that the given ship position is valid.
    ///
    /// If the player is CPU-controlled, a ship in a space next to another ship
    /// will be considered invalid.
    pub fn valid_ship_position(&self, new_ship: &[[u8; 2]]) -> bool {
        new_ship.iter()
            .all(|s| self.valid_space(s) && !self.ship_is_in_space(s)
                 && !(self.ship_is_next_to(s) && self.is_cpu))
    }

    /// Gets a reference to the ships.
    pub fn ships(&self) -> &[Ship] {
        &self.ships
    }

    /// Gets a reference to a ship if it is in the given position.
    fn ship(&self, pos: &[u8; 2]) -> Option<&Ship> {
        self.ships.iter().find(|s| s.pos().contains(pos))
    }

    /// Returns whether a ship occupies the specified grid coordinates.
    pub fn ship_is_in_space(&self, pos: &[u8; 2]) -> bool {
        self.ships.iter().any(|s| s.pos().contains(pos))
    }

    /// Returns whether there is a ship next to the specified grid coordinates.
    fn ship_is_next_to(&self, pos: &[u8; 2]) -> bool {
        let mut result = false;
        let x = pos[0];
        let y = pos[1];

        // Left
        if x > 0 {
            result = self.ship_is_in_space(&[x - 1, y]);
        }

        // Right
        if x < self.grid_size[0] - 1 && !result {
            result = self.ship_is_in_space(&[x + 1, y]);
        }

        // Above
        if y > 0 && !result {
            result = self.ship_is_in_space(&[x, y - 1]);
        }

        // Below
        if y < self.grid_size[1] - 1 && !result {
            result = self.ship_is_in_space(&[x, y + 1]);
        }

        result
    }

    /// Gets a reference to the spaces.
    pub fn spaces(&self) -> &[Space] {
        &self.spaces
    }

    /// Returns whether the given position is valid.
    fn valid_space(&self, pos: &[u8; 2]) -> bool {
        pos[0] < self.grid_size[0] && pos[1] < self.grid_size[1]
    }

    /// Gets a reference to the space with the given position.
    pub fn space(&self, pos: &[u8; 2]) -> &Space {
        self.spaces.get(self.space_index(pos)).unwrap()
    }

    /// Calculates the index of the given position in the spaces vector.
    fn space_index(&self, pos: &[u8; 2]) -> usize {
        self.grid_size[0] as usize * pos[0] as usize + pos[1] as usize
    }

    /// Returns the coordinates of the player's grid cursor.
    pub fn get_grid_cursor(&self) -> [u8; 2] {
        self.grid_cursor.clone()
    }

    /// Returns the coordinates of a movement from `pos` in a `direction`.
    /// Returns `None` if the movement is not possible.
    pub fn movement(&self, pos: &[u8; 2], direction: ShipDirection) -> Option<[u8; 2]> {
        let valid = match direction {
            ShipDirection::North => pos[1] > 0,
            ShipDirection::East => pos[0] < self.grid_size[0] - 1,
            ShipDirection::South => pos[1] < self.grid_size[1] - 1,
            ShipDirection::West => pos[0] > 0,
        };

        if valid {
            let movement = match direction {
                ShipDirection::North => [pos[0], pos[1] - 1],
                ShipDirection::East => [pos[0] + 1, pos[1]],
                ShipDirection::South => [pos[0], pos[1] + 1],
                ShipDirection::West => [pos[0] - 1, pos[1]],
            };
            Some(movement)
        } else {
            None
        }
    }

    /// Finds the first non-hit, unchecked space in a `direction` from `pos`.
    /// Can also make sure the space is at the end of a `line` of hit spaces.
    /// Returns `None` if the first non-hit space has been checked or if a grid
    /// boundary is reached.
    fn find_unchecked_space(
        &self,
        pos: &[u8; 2],
        direction: ShipDirection,
        check_for_line: bool
    ) -> Option<[u8; 2]> {
        let mut check_pos = self.movement(pos, direction);

        while let Some(next_pos) = check_pos {
            let next_space = self.space(&next_pos);

            match next_space.is_hit() {
                true => check_pos = self.movement(&next_pos, direction),
                false => {
                    if !next_space.is_unchecked() {
                        check_pos = None;
                    }
                    break;
                }
            };
        }

        if check_for_line && check_pos.is_some() {
            let unchecked = check_pos.unwrap();
            let opposite_dir = direction.opposite();
            let prev_pos = self.movement(&unchecked, opposite_dir).unwrap();

            if &prev_pos == pos {
                check_pos = None;
            }
        }

        check_pos
    }

    /// Moves the player's grid cursor in the given `direction` if possible.
    pub fn move_grid_cursor(&mut self, direction: ShipDirection) {
        if let Some(new_cursor) = self.movement(&self.grid_cursor, direction) {
            self.set_grid_cursor(&new_cursor);
        }
    }

    /// Sets the player's grid cursor coordinates.
    pub fn set_grid_cursor(&mut self, new_cursor: &[u8; 2]) {
        self.grid_cursor = *new_cursor;
    }
}

<commit_msg>movement() doesn't need to be public<commit_after>use std::cmp;
use rand::{
    Rng,
    seq::SliceRandom,
    thread_rng,
};
use crate::{
    game::GameState,
    ship::{
        Ship,
        ShipDirection,
    },
    space::Space,
};

pub struct Player {
    pub is_cpu: bool,
    spaces: Vec<Space>,
    ships: Vec<Ship>,
    grid_size: [u8; 2],
    grid_cursor: [u8; 2],
    pub temp_ship_pos: Vec<[u8; 2]>,
    pub temp_ship_dir: ShipDirection,
}

impl Player {
    pub fn new(grid_size: [u8; 2], is_cpu: bool) -> Player {
        let spaces_x = grid_size[0] as usize;
        let spaces_y = grid_size[1] as usize;
        let mut spaces = Vec::with_capacity(spaces_x * spaces_y);

        for col in 0..grid_size[0] {
            for row in 0..grid_size[1] {
                spaces.push(Space::new([col, row]));
            }
        }

        Player {
            is_cpu: is_cpu,
            spaces: spaces,
            ships: vec![],
            grid_size: grid_size,
            grid_cursor: [0, 0],
            temp_ship_pos: vec![[0, 0], [1, 0]],
            temp_ship_dir: ShipDirection::West,
        }
    }

    /// Selects a space and checks the status of ships if there's a hit.
    pub fn select_space(&mut self, pos: &[u8; 2]) -> GameState {
        let mut game_state = GameState::Active;
        let ship_hit = self.ships.iter().position(|s| s.pos().contains(pos));

        let space_index = self.space_index(pos);
        self.spaces[space_index].set_checked(ship_hit.is_some());

        if let Some(ship) = ship_hit {
            let ship_sunk = self.ships[ship].pos().iter()
                .all(|p| self.space(p).is_hit());

            if ship_sunk {
                self.ships[ship].sink();
            }

            let all_sunk = self.ships.iter().all(|s| !s.is_active());
            if all_sunk {
                game_state = GameState::Over;
            }
        }

        game_state
    }

    /// Determines the next space a CPU player will select.
    pub fn cpu_select_space(&self) -> [u8; 2] {
        let mut rng = thread_rng();
        let mut select = Vec::new();
        let mut directions = [
            ShipDirection::North,
            ShipDirection::East,
            ShipDirection::South,
            ShipDirection::West
        ];

        directions.shuffle(&mut rng);

        let mut hit_spaces = self.spaces.iter()
            .filter(|s| s.is_hit() && self.ship(s.pos()).unwrap().is_active())
            .collect::<Vec<&Space>>();

        hit_spaces.shuffle(&mut rng);

        // Check for a line of hit spaces.
        for space in &hit_spaces {
            for direction in &directions {
                let unchecked = self.find_unchecked_space(
                    space.pos(),
                    *direction,
                    true
                );

                if let Some(pos) = unchecked {
                    if !select.contains(&pos) {
                        select.push(pos);
                    }
                }
            }
        }

        // If a hit space was found, but no hit spaces next to it, find any
        // unchecked spaces next to it.
        if hit_spaces.len() > 0 && select.is_empty() {
            for direction in &directions {
                let unchecked = self.find_unchecked_space(
                    hit_spaces[0].pos(),
                    *direction,
                    false
                );

                if let Some(pos) = unchecked {
                    select.push(pos);
                }
            }
        }

        // If no spaces have been selected, just select any available space.
        if select.is_empty() {
            let pos: [u8; 2] = loop {
                let space = self.rng_pos();

                if self.space(&space).is_unchecked() {
                    break space;
                }
            };

            select.push(pos);
        }

        if select.len() > 1 {
            select.shuffle(&mut rng);
        }

        select[0]
    }

    fn rng_pos(&self) -> [u8; 2] {
        let mut rng = thread_rng();

        [
            rng.gen_range(0, self.grid_size[0]),
            rng.gen_range(0, self.grid_size[1]),
        ]
    }

    pub fn move_temp_ship(&mut self, direction: ShipDirection) {
        let old_head = self.temp_ship_pos[0];

        if let Some(new_head) = self.movement(&old_head, direction) {
            if let Some(ship) = self.get_ship_position(
                new_head,
                self.temp_ship_dir,
                self.temp_ship_pos.len() as u8
            ) {
                self.temp_ship_pos = ship;
            }
        }
    }

    pub fn place_temp_ship(&mut self) {
        let ship = self.temp_ship_pos.clone();

        if self.valid_ship_position(&ship) {
            self.ships.push(Ship::new(ship));

            self.temp_ship_dir = ShipDirection::West;
            self.temp_ship_pos = self.get_ship_position(
                [0, 0],
                self.temp_ship_dir,
                self.temp_ship_pos.len() as u8 + 1
            ).unwrap();
        }
    }

    /// Rotates a ship during the ship placement game state.
    pub fn rotate_temp_ship(&mut self) {
        let ship_len = self.temp_ship_pos.len() as u8;
        let dir = match self.temp_ship_dir {
            ShipDirection::North => ShipDirection::East,
            ShipDirection::East => ShipDirection::South,
            ShipDirection::South => ShipDirection::West,
            ShipDirection::West => ShipDirection::North,
        };

        // If the current starting position would cause the rotation to position
        // the ship partially out of bounds, adjust the starting position such
        // that the ship will be entirely within bounds.
        let old_start_pos = self.temp_ship_pos[0];
        let start_pos = match dir {
            ShipDirection::North => [
                self.temp_ship_pos[0][0],
                cmp::min(old_start_pos[1], self.grid_size[1] - ship_len),
            ],
            ShipDirection::East => [
                cmp::max(old_start_pos[0], ship_len - 1),
                self.temp_ship_pos[0][1],
            ],
            ShipDirection::South => [
                self.temp_ship_pos[0][0],
                cmp::max(old_start_pos[1], ship_len - 1),
            ],
            ShipDirection::West => [
                cmp::min(old_start_pos[0], self.grid_size[0] - ship_len),
                self.temp_ship_pos[0][1],
            ],
        };

        if let Some(ship) = self.get_ship_position(start_pos, dir, ship_len) {
            self.temp_ship_pos = ship;
            self.temp_ship_dir = dir;
        }
    }

    pub fn cpu_place_ships(&mut self) {
        for length in 2..6 {
            let ship_pos = self.cpu_place_ship(length);
            self.ships.push(Ship::new(ship_pos));
        }
    }

    /// RNGs ship locations for CPU players.
    fn cpu_place_ship(&self, length: u8) -> Vec<[u8; 2]> {
        let mut rng = thread_rng();

        // RNG a position and direction, then make sure it's valid.
        loop {
            let pos = self.rng_pos();
            let direction = match rng.gen_range(0, 4) {
                0 => ShipDirection::North,
                1 => ShipDirection::East,
                2 => ShipDirection::South,
                3 => ShipDirection::West,
                _ => unreachable!()
            };

            if let Some(s) = self.get_ship_position(pos, direction, length) {
                let valid = self.valid_ship_position(&s);

                if valid {
                    break s;
                }
            }
        }
    }

    /// Returns a ship position, given its head position, direction and length.
    ///
    /// `direction` refers to the direction the ship is facing, not the
    /// direction in which positions are generated.
    /// Returns `None` if the resulting ship position would not be contained
    /// within the grid.
    pub fn get_ship_position(
        &self,
        head: [u8; 2],
        direction: ShipDirection,
        length: u8
    ) -> Option<Vec<[u8; 2]>> {
        let valid = match direction {
            ShipDirection::North => head[1] + length <= self.grid_size[1],
            ShipDirection::East => head[0] >= length - 1,
            ShipDirection::South => head[1] >= length - 1,
            ShipDirection::West => head[0] + length <= self.grid_size[0],
        };

        let ship_opt = if valid {
            let mut ship = vec![head];

            for pos in 1..length {
                let pos_u8 = pos as u8;
                let space = match direction {
                    ShipDirection::North => [head[0], head[1] + pos_u8],
                    ShipDirection::East => [head[0] - pos_u8, head[1]],
                    ShipDirection::South => [head[0], head[1] - pos_u8],
                    ShipDirection::West => [head[0] + pos_u8, head[1]],
                };
                ship.push(space);
            }
            Some(ship)
        } else {
            None
        };

        ship_opt
    }

    /// Checks that the given ship position is valid.
    ///
    /// If the player is CPU-controlled, a ship in a space next to another ship
    /// will be considered invalid.
    pub fn valid_ship_position(&self, new_ship: &[[u8; 2]]) -> bool {
        new_ship.iter()
            .all(|s| self.valid_space(s) && !self.ship_is_in_space(s)
                 && !(self.ship_is_next_to(s) && self.is_cpu))
    }

    /// Gets a reference to the ships.
    pub fn ships(&self) -> &[Ship] {
        &self.ships
    }

    /// Gets a reference to a ship if it is in the given position.
    fn ship(&self, pos: &[u8; 2]) -> Option<&Ship> {
        self.ships.iter().find(|s| s.pos().contains(pos))
    }

    /// Returns whether a ship occupies the specified grid coordinates.
    pub fn ship_is_in_space(&self, pos: &[u8; 2]) -> bool {
        self.ships.iter().any(|s| s.pos().contains(pos))
    }

    /// Returns whether there is a ship next to the specified grid coordinates.
    fn ship_is_next_to(&self, pos: &[u8; 2]) -> bool {
        let mut result = false;
        let x = pos[0];
        let y = pos[1];

        // Left
        if x > 0 {
            result = self.ship_is_in_space(&[x - 1, y]);
        }

        // Right
        if x < self.grid_size[0] - 1 && !result {
            result = self.ship_is_in_space(&[x + 1, y]);
        }

        // Above
        if y > 0 && !result {
            result = self.ship_is_in_space(&[x, y - 1]);
        }

        // Below
        if y < self.grid_size[1] - 1 && !result {
            result = self.ship_is_in_space(&[x, y + 1]);
        }

        result
    }

    /// Gets a reference to the spaces.
    pub fn spaces(&self) -> &[Space] {
        &self.spaces
    }

    /// Returns whether the given position is valid.
    fn valid_space(&self, pos: &[u8; 2]) -> bool {
        pos[0] < self.grid_size[0] && pos[1] < self.grid_size[1]
    }

    /// Gets a reference to the space with the given position.
    pub fn space(&self, pos: &[u8; 2]) -> &Space {
        self.spaces.get(self.space_index(pos)).unwrap()
    }

    /// Calculates the index of the given position in the spaces vector.
    fn space_index(&self, pos: &[u8; 2]) -> usize {
        self.grid_size[0] as usize * pos[0] as usize + pos[1] as usize
    }

    /// Returns the coordinates of the player's grid cursor.
    pub fn get_grid_cursor(&self) -> [u8; 2] {
        self.grid_cursor.clone()
    }

    /// Returns the coordinates of a movement from `pos` in a `direction`.
    /// Returns `None` if the movement is not possible.
    fn movement(&self, pos: &[u8; 2], direction: ShipDirection) -> Option<[u8; 2]> {
        let valid = match direction {
            ShipDirection::North => pos[1] > 0,
            ShipDirection::East => pos[0] < self.grid_size[0] - 1,
            ShipDirection::South => pos[1] < self.grid_size[1] - 1,
            ShipDirection::West => pos[0] > 0,
        };

        if valid {
            let movement = match direction {
                ShipDirection::North => [pos[0], pos[1] - 1],
                ShipDirection::East => [pos[0] + 1, pos[1]],
                ShipDirection::South => [pos[0], pos[1] + 1],
                ShipDirection::West => [pos[0] - 1, pos[1]],
            };
            Some(movement)
        } else {
            None
        }
    }

    /// Finds the first non-hit, unchecked space in a `direction` from `pos`.
    /// Can also make sure the space is at the end of a `line` of hit spaces.
    /// Returns `None` if the first non-hit space has been checked or if a grid
    /// boundary is reached.
    fn find_unchecked_space(
        &self,
        pos: &[u8; 2],
        direction: ShipDirection,
        check_for_line: bool
    ) -> Option<[u8; 2]> {
        let mut check_pos = self.movement(pos, direction);

        while let Some(next_pos) = check_pos {
            let next_space = self.space(&next_pos);

            match next_space.is_hit() {
                true => check_pos = self.movement(&next_pos, direction),
                false => {
                    if !next_space.is_unchecked() {
                        check_pos = None;
                    }
                    break;
                }
            };
        }

        if check_for_line && check_pos.is_some() {
            let unchecked = check_pos.unwrap();
            let opposite_dir = direction.opposite();
            let prev_pos = self.movement(&unchecked, opposite_dir).unwrap();

            if &prev_pos == pos {
                check_pos = None;
            }
        }

        check_pos
    }

    /// Moves the player's grid cursor in the given `direction` if possible.
    pub fn move_grid_cursor(&mut self, direction: ShipDirection) {
        if let Some(new_cursor) = self.movement(&self.grid_cursor, direction) {
            self.set_grid_cursor(&new_cursor);
        }
    }

    /// Sets the player's grid cursor coordinates.
    pub fn set_grid_cursor(&mut self, new_cursor: &[u8; 2]) {
        self.grid_cursor = *new_cursor;
    }
}

<|endoftext|>


<commit_before>//! Utilities for formatting macro expanded nodes until we get a proper formatter.
use syntax::{
    ast::make,
    ted::{self, Position},
    NodeOrToken,
    SyntaxKind::{self, *},
    SyntaxNode, SyntaxToken, WalkEvent, T,
};

// FIXME: It would also be cool to share logic here and in the mbe tests,
// which are pretty unreadable at the moment.
/// Renders a [`SyntaxNode`] with whitespace inserted between tokens that require them.
pub fn insert_ws_into(syn: SyntaxNode) -> SyntaxNode {
    let mut indent = 0;
    let mut last: Option<SyntaxKind> = None;
    let mut mods = Vec::new();
    let syn = syn.clone_subtree().clone_for_update();

    let before = Position::before;
    let after = Position::after;

    let do_indent = |pos: fn(_) -> Position, token: &SyntaxToken, indent| {
        (pos(token.clone()), make::tokens::whitespace(&" ".repeat(2 * indent)))
    };
    let do_ws = |pos: fn(_) -> Position, token: &SyntaxToken| {
        (pos(token.clone()), make::tokens::single_space())
    };
    let do_nl = |pos: fn(_) -> Position, token: &SyntaxToken| {
        (pos(token.clone()), make::tokens::single_newline())
    };

    for event in syn.preorder_with_tokens() {
        let token = match event {
            WalkEvent::Enter(NodeOrToken::Token(token)) => token,
            WalkEvent::Leave(NodeOrToken::Node(node))
                if matches!(node.kind(), ATTR | MATCH_ARM | STRUCT | ENUM | UNION | FN | IMPL) =>
            {
                if indent > 0 {
                    mods.push((
                        Position::after(node.clone()),
                        make::tokens::whitespace(&" ".repeat(2 * indent)),
                    ));
                }
                if node.parent().is_some() {
                    mods.push((Position::after(node), make::tokens::single_newline()));
                }
                continue;
            }
            _ => continue,
        };
        let tok = &token;

        let is_next = |f: fn(SyntaxKind) -> bool, default| -> bool {
            tok.next_token().map(|it| f(it.kind())).unwrap_or(default)
        };
        let is_last =
            |f: fn(SyntaxKind) -> bool, default| -> bool { last.map(f).unwrap_or(default) };

        match tok.kind() {
            k if is_text(k) && is_next(|it| !it.is_punct(), true) => {
                mods.push(do_ws(after, tok));
            }
            L_CURLY if is_next(|it| it != R_CURLY, true) => {
                indent += 1;
                if is_last(is_text, false) {
                    mods.push(do_ws(before, tok));
                }

                if indent > 0 {
                    mods.push(do_indent(after, tok, indent));
                }
                mods.push(do_nl(after, tok));
            }
            R_CURLY if is_last(|it| it != L_CURLY, true) => {
                indent = indent.saturating_sub(1);

                if indent > 0 {
                    mods.push(do_indent(before, tok, indent));
                }
                mods.push(do_nl(before, tok));
            }
            R_CURLY => {
                if indent > 0 {
                    mods.push(do_indent(after, tok, indent));
                }
                mods.push(do_nl(after, tok));
            }
            LIFETIME_IDENT if is_next(is_text, true) => {
                mods.push(do_ws(after, tok));
            }
            AS_KW | DYN_KW | IMPL_KW => {
                mods.push(do_ws(after, tok));
            }
            T![;] => {
                if indent > 0 {
                    mods.push(do_indent(after, tok, indent));
                }
                mods.push(do_nl(after, tok));
            }
            T![->] | T![=] | T![=>] => {
                mods.push(do_ws(before, tok));
                mods.push(do_ws(after, tok));
            }
            _ => (),
        }

        last = Some(tok.kind());
    }

    for (pos, insert) in mods {
        ted::insert(pos, insert);
    }

    syn
}

fn is_text(k: SyntaxKind) -> bool {
    k.is_keyword() || k.is_literal() || k == IDENT
}
<commit_msg>Auto merge of #12117 - Veykril:mexpand, r=Veykril<commit_after>//! Utilities for formatting macro expanded nodes until we get a proper formatter.
use syntax::{
    ast::make,
    ted::{self, Position},
    NodeOrToken,
    SyntaxKind::{self, *},
    SyntaxNode, SyntaxToken, WalkEvent, T,
};

// FIXME: It would also be cool to share logic here and in the mbe tests,
// which are pretty unreadable at the moment.
/// Renders a [`SyntaxNode`] with whitespace inserted between tokens that require them.
pub fn insert_ws_into(syn: SyntaxNode) -> SyntaxNode {
    let mut indent = 0;
    let mut last: Option<SyntaxKind> = None;
    let mut mods = Vec::new();
    let syn = syn.clone_subtree().clone_for_update();

    let before = Position::before;
    let after = Position::after;

    let do_indent = |pos: fn(_) -> Position, token: &SyntaxToken, indent| {
        (pos(token.clone()), make::tokens::whitespace(&" ".repeat(2 * indent)))
    };
    let do_ws = |pos: fn(_) -> Position, token: &SyntaxToken| {
        (pos(token.clone()), make::tokens::single_space())
    };
    let do_nl = |pos: fn(_) -> Position, token: &SyntaxToken| {
        (pos(token.clone()), make::tokens::single_newline())
    };

    for event in syn.preorder_with_tokens() {
        let token = match event {
            WalkEvent::Enter(NodeOrToken::Token(token)) => token,
            WalkEvent::Leave(NodeOrToken::Node(node))
                if matches!(node.kind(), ATTR | MATCH_ARM | STRUCT | ENUM | UNION | FN | IMPL) =>
            {
                if indent > 0 {
                    mods.push((
                        Position::after(node.clone()),
                        make::tokens::whitespace(&" ".repeat(2 * indent)),
                    ));
                }
                if node.parent().is_some() {
                    mods.push((Position::after(node), make::tokens::single_newline()));
                }
                continue;
            }
            _ => continue,
        };
        let tok = &token;

        let is_next = |f: fn(SyntaxKind) -> bool, default| -> bool {
            tok.next_token().map(|it| f(it.kind())).unwrap_or(default)
        };
        let is_last =
            |f: fn(SyntaxKind) -> bool, default| -> bool { last.map(f).unwrap_or(default) };

        match tok.kind() {
            k if is_text(k) && is_next(|it| !it.is_punct(), true) => {
                mods.push(do_ws(after, tok));
            }
            L_CURLY if is_next(|it| it != R_CURLY, true) => {
                indent += 1;
                if is_last(is_text, false) {
                    mods.push(do_ws(before, tok));
                }

                if indent > 0 {
                    mods.push(do_indent(after, tok, indent));
                }
                mods.push(do_nl(after, tok));
            }
            R_CURLY if is_last(|it| it != L_CURLY, true) => {
                indent = indent.saturating_sub(1);

                if indent > 0 {
                    mods.push(do_indent(before, tok, indent));
                }
                mods.push(do_nl(before, tok));
            }
            R_CURLY => {
                if indent > 0 {
                    mods.push(do_indent(after, tok, indent));
                }
                mods.push(do_nl(after, tok));
            }
            LIFETIME_IDENT if is_next(is_text, true) => {
                mods.push(do_ws(after, tok));
            }
            AS_KW | DYN_KW | IMPL_KW | CONST_KW => {
                mods.push(do_ws(after, tok));
            }
            T![;] => {
                if indent > 0 {
                    mods.push(do_indent(after, tok, indent));
                }
                mods.push(do_nl(after, tok));
            }
            T![->] | T![=] | T![=>] => {
                mods.push(do_ws(before, tok));
                mods.push(do_ws(after, tok));
            }
            _ => (),
        }

        last = Some(tok.kind());
    }

    for (pos, insert) in mods {
        ted::insert(pos, insert);
    }

    syn
}

fn is_text(k: SyntaxKind) -> bool {
    k.is_keyword() || k.is_literal() || k == IDENT
}
<|endoftext|>


<commit_before>use std::collections::HashSet;
use std::fmt;
use std::from_str::FromStr;
use std::iter;
use std::slice;

use serialize::{Decodable, Decoder};

use csv;

#[deriving(Clone)]
pub struct SelectColumns {
    selectors: Vec<Selector>,
    invert: bool,
}

// This parser is super basic at the moment. Field names cannot contain [-,].
impl SelectColumns {
    pub fn selection(&self, first_record: &[csv::ByteString], use_names: bool)
                    -> Result<Selection, String> {
        if self.selectors.is_empty() {
            return Ok(Selection(Vec::from_fn(first_record.len(), |i| i)));
        }

        let mut map = vec![];
        for sel in self.selectors.iter() {
            let idxs = sel.indices(first_record, use_names);
            map.extend(try!(idxs).into_iter());
        }
        if self.invert {
            let set: HashSet<_> = map.into_iter().collect();
            let mut map = vec![];
            for i in range(0, first_record.len()) {
                if !set.contains(&i) {
                    map.push(i);
                }
            }
            return Ok(Selection(map));
        }
        Ok(Selection(map))
    }

    fn parse(mut s: &str) -> Result<SelectColumns, String> {
        let mut scols = SelectColumns { selectors: vec![], invert: false };
        if s.is_empty() { return Ok(scols); }
        if s.as_bytes()[0] == b'!' {
            scols.invert = true;
            s = s[1..];
        }
        for sel in s.split(',') {
            scols.selectors.push(try!(SelectColumns::parse_selector(sel)));
        }
        Ok(scols)
    }

    fn parse_selector(sel: &str) -> Result<Selector, String> {
        if sel.contains_char('-') {
            let pieces: Vec<&str> = sel.splitn(1, '-').collect();
            let start =
                if pieces[0].is_empty() {
                    SelStart
                } else {
                    try!(SelectColumns::parse_one_selector(pieces[0]))
                };
            let end =
                if pieces[1].is_empty() {
                    SelEnd
                } else {
                    try!(SelectColumns::parse_one_selector(pieces[1]))
                };
            Ok(SelRange(start, end))
        } else {
            SelectColumns::parse_one_selector(sel).map(SelOne)
        }
    }

    fn parse_one_selector(sel: &str) -> Result<OneSelector, String> {
        if sel.contains_char('-') {
            return Err(format!("Illegal '-' in selector '{}'.", sel))
        }
        let idx: Option<uint> = FromStr::from_str(sel);
        Ok(match idx {
            None => SelName(sel.to_string()),
            Some(idx) => SelIndex(idx),
        })
    }
}

impl fmt::Show for SelectColumns {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.selectors.is_empty() {
            write!(f, "<All>")
        } else {
            let strs: Vec<_> =
                self.selectors.iter().map(|sel| sel.to_string()).collect();
            write!(f, "{}", strs.connect(", "))
        }
    }
}

impl <E, D: Decoder<E>> Decodable<D, E> for SelectColumns {
    fn decode(d: &mut D) -> Result<SelectColumns, E> {
        SelectColumns::parse(try!(d.read_str()).as_slice())
                      .map_err(|e| d.error(e.as_slice()))
    }
}

#[deriving(Clone)]
enum Selector {
    SelOne(OneSelector),
    SelRange(OneSelector, OneSelector),
}

#[deriving(Clone)]
enum OneSelector {
    SelStart,
    SelEnd,
    SelIndex(uint),
    SelName(String),
    SelIndexedName(String, uint),
}

impl Selector {
    fn indices(&self, first_record: &[csv::ByteString], use_names: bool)
              -> Result<Vec<uint>, String> {
        match self {
            &SelOne(ref sel) => {
                sel.index(first_record, use_names).map(|i| vec![i])
            }
            &SelRange(ref sel1, ref sel2) => {
                let i1 = try!(sel1.index(first_record, use_names));
                let i2 = try!(sel2.index(first_record, use_names));
                Ok(match i1.cmp(&i2) {
                    Equal => vec!(i1),
                    Less => iter::range_inclusive(i1, i2).collect(),
                    Greater => {
                        iter::range_step_inclusive(i1 as int, i2 as int, -1)
                             .map(|i| i as uint).collect()
                    }
                })
            }
        }
    }
}

impl OneSelector {
    fn index(&self, first_record: &[csv::ByteString], use_names: bool)
            -> Result<uint, String> {
        match self {
            &SelStart => Ok(0),
            &SelEnd => Ok(first_record.len()),
            &SelIndex(i) => {
                if i < 1 || i > first_record.len() {
                    Err(format!("Selector index {} is out of \
                                 bounds. Index must be >= 1 \
                                 and <= {}.", i, first_record.len()))
                } else {
                    // Indices given by user are 1-offset. Convert them here!
                    Ok(i-1)
                }
            }
            &SelName(ref s) => {
                if !use_names {
                    return Err(format!("Cannot use names ('{}') in selection \
                                        with --no-headers set.", s));
                }
                match first_record.iter().position(|h| h.equiv(s)) {
                    None => Err(format!("Selector name '{}' does not exist \
                                         as a named header in the given CSV \
                                         data.", s)),
                    Some(i) => Ok(i),
                }
            }
            &SelIndexedName(ref s, sidx) => {
                if !use_names {
                    return Err(format!("Cannot use names ('{}') in selection \
                                        with --no-headers set.", s));
                }
                let mut num_found = 0;
                for (i, field) in first_record.iter().enumerate() {
                    if field.equiv(s) {
                        if num_found == sidx {
                            return Ok(i);
                        }
                        num_found += 1;
                    }
                }
                if num_found == 0 {
                    return Err(format!("Selector name '{}' does not exist \
                                        as a named header in the given CSV \
                                        data.", s));
                }
                Err(format!("Selector index '{}' for name '{}' is \
                             out of bounds. Must be >= 0 and <= {}.",
                             sidx, s, num_found - 1))
            }
        }
    }
}

impl fmt::Show for Selector {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &SelOne(ref sel) => sel.fmt(f),
            &SelRange(ref s, ref e) => write!(f, "Range({}, {})", s, e),
        }
    }
}

impl fmt::Show for OneSelector {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &SelStart => write!(f, "Start"),
            &SelEnd => write!(f, "End"),
            &SelIndex(idx) => write!(f, "Index({:u})", idx),
            &SelName(ref s) => write!(f, "Name({})", s),
            &SelIndexedName(ref s, idx) => write!(f, "IndexedName({}[{}])",
                                                  s, idx),
        }
    }
}

#[deriving(Clone, Show)]
pub struct Selection(Vec<uint>);

impl Selection {
    pub fn select<'a, 'b>(&'a self, row: &'b [csv::ByteString])
                 -> iter::Scan<&'a uint,
                               &'b [u8],
                               slice::Items<'a, uint>,
                               &'b [csv::ByteString]> {
        // This is horrifying.
        // Help me closure reform, you're my only hope.
        self.as_slice().iter().scan(row, |row, &idx| Some(row[idx].as_slice()))
    }

    pub fn normal(&self) -> NormalSelection {
        let &Selection(ref inds) = self;
        let mut normal = inds.clone();
        normal.sort();
        normal.dedup();
        let mut set = Vec::from_elem(normal[normal.len()-1] + 1, false);
        for i in normal.into_iter() {
            *set.get_mut(i) = true;
        }
        NormalSelection(set)
    }
}

impl AsSlice<uint> for Selection {
    fn as_slice(&self) -> &[uint] { self.0[] }
}

impl Collection for Selection {
    fn len(&self) -> uint {
        self.0.len()
    }
}

#[deriving(Clone, Show)]
pub struct NormalSelection(Vec<bool>);

impl NormalSelection {
    pub fn select<'a, 'b, T, I: Iterator<T>>(&'a self, row: I)
                 -> iter::FilterMap<Option<T>, T,
                                    iter::Scan<(uint, T),
                                               Option<T>,
                                               iter::Enumerate<I>,
                                               &'a [bool]>> {
        let set = self.as_slice();
        row.enumerate().scan(set, |set, (i, v)| {
            if i < set.len() && set[i] { Some(Some(v)) } else { Some(None) }
        }).filter_map(|v| v)
    }
}

impl AsSlice<bool> for NormalSelection {
    fn as_slice(&self) -> &[bool] { self.0[] }
}

impl Collection for NormalSelection {
    fn len(&self) -> uint {
        self.as_slice().iter().filter(|b| **b).count()
    }
}
<commit_msg>SelName is redundant with SelIndexedName({anything}, 0), so remove it.<commit_after>use std::collections::HashSet;
use std::fmt;
use std::from_str::FromStr;
use std::iter;
use std::slice;

use serialize::{Decodable, Decoder};

use csv;

#[deriving(Clone)]
pub struct SelectColumns {
    selectors: Vec<Selector>,
    invert: bool,
}

// This parser is super basic at the moment. Field names cannot contain [-,].
impl SelectColumns {
    pub fn selection(&self, first_record: &[csv::ByteString], use_names: bool)
                    -> Result<Selection, String> {
        if self.selectors.is_empty() {
            return Ok(Selection(Vec::from_fn(first_record.len(), |i| i)));
        }

        let mut map = vec![];
        for sel in self.selectors.iter() {
            let idxs = sel.indices(first_record, use_names);
            map.extend(try!(idxs).into_iter());
        }
        if self.invert {
            let set: HashSet<_> = map.into_iter().collect();
            let mut map = vec![];
            for i in range(0, first_record.len()) {
                if !set.contains(&i) {
                    map.push(i);
                }
            }
            return Ok(Selection(map));
        }
        Ok(Selection(map))
    }

    fn parse(mut s: &str) -> Result<SelectColumns, String> {
        let mut scols = SelectColumns { selectors: vec![], invert: false };
        if s.is_empty() { return Ok(scols); }
        if s.as_bytes()[0] == b'!' {
            scols.invert = true;
            s = s[1..];
        }
        for sel in s.split(',') {
            scols.selectors.push(try!(SelectColumns::parse_selector(sel)));
        }
        Ok(scols)
    }

    fn parse_selector(sel: &str) -> Result<Selector, String> {
        if sel.contains_char('-') {
            let pieces: Vec<&str> = sel.splitn(1, '-').collect();
            let start =
                if pieces[0].is_empty() {
                    SelStart
                } else {
                    try!(SelectColumns::parse_one_selector(pieces[0]))
                };
            let end =
                if pieces[1].is_empty() {
                    SelEnd
                } else {
                    try!(SelectColumns::parse_one_selector(pieces[1]))
                };
            Ok(SelRange(start, end))
        } else {
            SelectColumns::parse_one_selector(sel).map(SelOne)
        }
    }

    fn parse_one_selector(sel: &str) -> Result<OneSelector, String> {
        if sel.contains_char('-') {
            return Err(format!("Illegal '-' in selector '{}'.", sel))
        }
        let idx: Option<uint> = FromStr::from_str(sel);
        Ok(match idx {
            None => SelIndexedName(sel.to_string(), 0),
            Some(idx) => SelIndex(idx),
        })
    }
}

impl fmt::Show for SelectColumns {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.selectors.is_empty() {
            write!(f, "<All>")
        } else {
            let strs: Vec<_> =
                self.selectors.iter().map(|sel| sel.to_string()).collect();
            write!(f, "{}", strs.connect(", "))
        }
    }
}

impl <E, D: Decoder<E>> Decodable<D, E> for SelectColumns {
    fn decode(d: &mut D) -> Result<SelectColumns, E> {
        SelectColumns::parse(try!(d.read_str()).as_slice())
                      .map_err(|e| d.error(e.as_slice()))
    }
}

#[deriving(Clone)]
enum Selector {
    SelOne(OneSelector),
    SelRange(OneSelector, OneSelector),
}

#[deriving(Clone)]
enum OneSelector {
    SelStart,
    SelEnd,
    SelIndex(uint),
    SelIndexedName(String, uint),
}

impl Selector {
    fn indices(&self, first_record: &[csv::ByteString], use_names: bool)
              -> Result<Vec<uint>, String> {
        match self {
            &SelOne(ref sel) => {
                sel.index(first_record, use_names).map(|i| vec![i])
            }
            &SelRange(ref sel1, ref sel2) => {
                let i1 = try!(sel1.index(first_record, use_names));
                let i2 = try!(sel2.index(first_record, use_names));
                Ok(match i1.cmp(&i2) {
                    Equal => vec!(i1),
                    Less => iter::range_inclusive(i1, i2).collect(),
                    Greater => {
                        iter::range_step_inclusive(i1 as int, i2 as int, -1)
                             .map(|i| i as uint).collect()
                    }
                })
            }
        }
    }
}

impl OneSelector {
    fn index(&self, first_record: &[csv::ByteString], use_names: bool)
            -> Result<uint, String> {
        match self {
            &SelStart => Ok(0),
            &SelEnd => Ok(first_record.len()),
            &SelIndex(i) => {
                if i < 1 || i > first_record.len() {
                    Err(format!("Selector index {} is out of \
                                 bounds. Index must be >= 1 \
                                 and <= {}.", i, first_record.len()))
                } else {
                    // Indices given by user are 1-offset. Convert them here!
                    Ok(i-1)
                }
            }
            &SelIndexedName(ref s, sidx) => {
                if !use_names {
                    return Err(format!("Cannot use names ('{}') in selection \
                                        with --no-headers set.", s));
                }
                let mut num_found = 0;
                for (i, field) in first_record.iter().enumerate() {
                    if field.equiv(s) {
                        if num_found == sidx {
                            return Ok(i);
                        }
                        num_found += 1;
                    }
                }
                if num_found == 0 {
                    return Err(format!("Selector name '{}' does not exist \
                                        as a named header in the given CSV \
                                        data.", s));
                }
                Err(format!("Selector index '{}' for name '{}' is \
                             out of bounds. Must be >= 0 and <= {}.",
                             sidx, s, num_found - 1))
            }
        }
    }
}

impl fmt::Show for Selector {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &SelOne(ref sel) => sel.fmt(f),
            &SelRange(ref s, ref e) => write!(f, "Range({}, {})", s, e),
        }
    }
}

impl fmt::Show for OneSelector {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &SelStart => write!(f, "Start"),
            &SelEnd => write!(f, "End"),
            &SelIndex(idx) => write!(f, "Index({:u})", idx),
            &SelIndexedName(ref s, idx) => write!(f, "IndexedName({}[{}])",
                                                  s, idx),
        }
    }
}

#[deriving(Clone, Show)]
pub struct Selection(Vec<uint>);

impl Selection {
    pub fn select<'a, 'b>(&'a self, row: &'b [csv::ByteString])
                 -> iter::Scan<&'a uint,
                               &'b [u8],
                               slice::Items<'a, uint>,
                               &'b [csv::ByteString]> {
        // This is horrifying.
        // Help me closure reform, you're my only hope.
        self.as_slice().iter().scan(row, |row, &idx| Some(row[idx].as_slice()))
    }

    pub fn normal(&self) -> NormalSelection {
        let &Selection(ref inds) = self;
        let mut normal = inds.clone();
        normal.sort();
        normal.dedup();
        let mut set = Vec::from_elem(normal[normal.len()-1] + 1, false);
        for i in normal.into_iter() {
            *set.get_mut(i) = true;
        }
        NormalSelection(set)
    }
}

impl AsSlice<uint> for Selection {
    fn as_slice(&self) -> &[uint] { self.0[] }
}

impl Collection for Selection {
    fn len(&self) -> uint {
        self.0.len()
    }
}

#[deriving(Clone, Show)]
pub struct NormalSelection(Vec<bool>);

impl NormalSelection {
    pub fn select<'a, 'b, T, I: Iterator<T>>(&'a self, row: I)
                 -> iter::FilterMap<Option<T>, T,
                                    iter::Scan<(uint, T),
                                               Option<T>,
                                               iter::Enumerate<I>,
                                               &'a [bool]>> {
        let set = self.as_slice();
        row.enumerate().scan(set, |set, (i, v)| {
            if i < set.len() && set[i] { Some(Some(v)) } else { Some(None) }
        }).filter_map(|v| v)
    }
}

impl AsSlice<bool> for NormalSelection {
    fn as_slice(&self) -> &[bool] { self.0[] }
}

impl Collection for NormalSelection {
    fn len(&self) -> uint {
        self.as_slice().iter().filter(|b| **b).count()
    }
}
<|endoftext|>


<commit_before>/**
 * What we want:
 * Server sits and loops about. Has a send/receive buffer
 * Has a broadcast method?
 * Has a send method
 * Has a read method, to pump items out of the receive buffer
 * Has a read iterator?
 */

struct ServerManager<T> {
    receiver: (Sender<T>, Receiver<T>)
}

impl<T> ServerManager<T> {
    pub fn new() -> ServerManager<T> {
        ServerManager {
            receiver: channel()
        }
    }
}

fn main () {
}
<commit_msg>Started working on server code<commit_after>/**
 * What we want:
 * Server sits and loops about. Has a send/receive buffer
 * Has a broadcast method?
 * Has a send method
 * Has a read method, to pump items out of the receive buffer
 * Has a read iterator?
 */
use packet::{Packet, Command};

struct ServerManager {
    pub addr: SocketAddr,

    protocol_id: u32,
    reader_send: Sender<Command>,
    reader_receive: Receiver<Packet>,
}

impl ServerManager {
    pub fn new(protocol_id: u32) -> ServerManager {

        ServerManager {protocol_id: protocol_id}
    }
}
<|endoftext|>


<commit_before>// Single-byte XOR cipher
// The hex encoded string:

// 1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736
// ... has been XOR'd against a single character. Find the key, decrypt the message.

// You can do this by hand. But don't: write code to do it for you.

// How? Devise some method for "scoring" a piece of English plaintext.
// Character frequency is a good metric. Evaluate each output and choose the one with the best score.

#![feature(core)]

#[macro_use]
extern crate log;

use std::ascii::AsciiExt;
use std::num::Int;
use std::str;

#[cfg(not(test))]
fn main() {
	println!("Set 1, Challenge 3");
	let input = "1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736";
	println!("input: {:?}", input);
	let output = decode_single_byte_xor(input);
	println!("output string: {:?}", output);
}

fn decode_single_byte_xor(input: &str) -> String {
	if input.len() % 2 != 0 {
		panic!("Hex string length should be even.");
	}

	// make vector of hex-decoded values
	// for each value from 0 to 255
	//    for each char in vector, xor it and add it to a temp vector
	//    turn vector into string
	//    score string
	//    if string score better than best_string
	//       update best_string, best_string_score

	let mut decimal_values = vec!();

	let input_lower = input.to_ascii_lowercase();
	let bytes = input_lower.as_bytes();

	let mut tick = 1;
	let mut current_byte = 0;

	for &x in bytes.iter() {
		current_byte += convert_hex_char_to_decimal(x) * 16.pow(tick);
		tick = tick ^ 1;
		if tick == 1 {
			decimal_values.push(current_byte);
			current_byte = 0;
		}
	}

	let mut best_string = String::new();
	let mut best_string_score = 0;

	// starting with 0, test the current string just in case
	for test_val in 0..255 {
		debug!("{:?}", test_val);
		let mut decoded_values = vec!();
		for &x in decimal_values.iter() {
			decoded_values.push(x ^ test_val);
		}

		// turn the byte vector into a string
		match str::from_utf8(decoded_values.as_slice()) {
		    Ok(v) => {
		        let score = score_text(v);
		        if score > best_string_score {
		        	best_string = v.to_string();
		        	best_string_score = score;
		        }
		    }
		    Err(_) => { }
		}
	}

	best_string
}

fn convert_hex_char_to_decimal(character: u8) -> u8 {
	// if x is in the ascii range for numbers, subtract 48,
	// which is '0' in ascii. Otherwise, it should be a lowercase letter.
	// 'a' is 97, so subtract 87.
	match character < 58 {
		true => character - 48,
		false => character - 87
	}
}

// these are strings so that they can be used in StrExt.replace.
// this seemed easier than converting chars to strings every time.
// characters are taken from relative frequency of letters in the english language:
// https://en.wikipedia.org/wiki/Letter_frequency
static VALUED_CHARS: &'static[&'static str] = &["e", "t", "a", "o", "n"];

// this scoring function is extremely simple/fragile. that said,
// it completes this challenge
fn score_text(text: &str) -> usize {
	let mut score: usize = 0;
	let lowercase = text.to_ascii_lowercase();
	for &test_char in VALUED_CHARS {
		let test_str = lowercase.replace(test_char, "");
		score += text.len() - test_str.len();
		debug!("input: {:?}, test: {:?}, score increase: {:?}", text, test_str, text.len() - test_str.len());
	}
	return score;
}

#[cfg(test)]
mod set1challenge3 {

	#[test]
	fn challenge() {
		let output = super::decode_single_byte_xor("4574626531626563787f76");
		assert_eq!(output, "Test string");
	}

}
<commit_msg>Updated challenge 3 to latest Rust<commit_after>// Single-byte XOR cipher
// The hex encoded string:

// 1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736
// ... has been XOR'd against a single character. Find the key, decrypt the message.

// You can do this by hand. But don't: write code to do it for you.

// How? Devise some method for "scoring" a piece of English plaintext.
// Character frequency is a good metric. Evaluate each output and choose the one with the best score.

#[macro_use]
extern crate log;

use std::ascii::AsciiExt;
use std::str;

#[cfg(not(test))]
fn main() {
	println!("Set 1, Challenge 3");
	let input = "1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736";
	println!("input: {:?}", input);
	let output = decode_single_byte_xor(input);
	println!("output string: {:?}", output);
}

fn decode_single_byte_xor(input: &str) -> String {
	if input.len() % 2 != 0 {
		panic!("Hex string length should be even.");
	}

	// make vector of hex-decoded values
	// for each value from 0 to 255
	//    for each char in vector, xor it and add it to a temp vector
	//    turn vector into string
	//    score string
	//    if string score better than best_string
	//       update best_string, best_string_score

	let mut decimal_values = vec!();

	let input_lower = input.to_ascii_lowercase();
	let bytes = input_lower.as_bytes();

	let mut tick = 1;
	let mut current_byte = 0;

	for &x in bytes.iter() {
		current_byte += convert_hex_char_to_decimal(x) * 16u8.pow(tick);
		tick = tick ^ 1;
		if tick == 1 {
			decimal_values.push(current_byte);
			current_byte = 0;
		}
	}

	let mut best_string = String::new();
	let mut best_string_score = 0;

	// starting with 0, test the current string just in case
	for test_val in 0..255 {
		debug!("{:?}", test_val);
		let mut decoded_values = vec!();
		for &x in decimal_values.iter() {
			decoded_values.push(x ^ test_val);
		}

		// turn the byte vector into a string
		match str::from_utf8(&decoded_values) {
		    Ok(v) => {
		        let score = score_text(v);
		        if score > best_string_score {
		        	best_string = v.to_string();
		        	best_string_score = score;
		        }
		    }
		    Err(_) => { }
		}
	}

	best_string
}

fn convert_hex_char_to_decimal(character: u8) -> u8 {
	// if x is in the ascii range for numbers, subtract 48,
	// which is '0' in ascii. Otherwise, it should be a lowercase letter.
	// 'a' is 97, so subtract 87.
	match character < 58 {
		true => character - 48,
		false => character - 87
	}
}

// these are strings so that they can be used in StrExt.replace.
// this seemed easier than converting chars to strings every time.
// characters are taken from relative frequency of letters in the english language:
// https://en.wikipedia.org/wiki/Letter_frequency
static VALUED_CHARS: &'static[&'static str] = &["e", "t", "a", "o", "n"];

// this scoring function is extremely simple/fragile. that said,
// it completes this challenge
fn score_text(text: &str) -> usize {
	let mut score: usize = 0;
	let lowercase = text.to_ascii_lowercase();
	for &test_char in VALUED_CHARS {
		let test_str = lowercase.replace(test_char, "");
		score += text.len() - test_str.len();
		debug!("input: {:?}, test: {:?}, score increase: {:?}", text, test_str, text.len() - test_str.len());
	}
	return score;
}

#[cfg(test)]
mod set1challenge3 {

	#[test]
	fn challenge() {
		let output = super::decode_single_byte_xor("4574626531626563787f76");
		assert_eq!(output, "Test string");
	}

}
<|endoftext|>


<commit_before>// Single-byte XOR cipher
// The hex encoded string:

// 1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736
// ... has been XOR'd against a single character. Find the key, decrypt the message.

// You can do this by hand. But don't: write code to do it for you.

// How? Devise some method for "scoring" a piece of English plaintext.
// Character frequency is a good metric. Evaluate each output and choose the one with the best score.

// i/o isn't tested right now, so let's silence that warning
#![allow(unused_features)]

#![feature(core)]
#![feature(env)]
#![feature(io)]
#![feature(old_io)]
#![feature(old_path)]
#![feature(os)]
#![feature(path)]
#![feature(std_misc)]

#[macro_use]
extern crate log;

use std::ascii::AsciiExt;
use std::num::Int;

use std::str;

#[cfg(not(test))]
use std::env;
#[cfg(not(test))]
use std::old_io::BufferedReader;
#[cfg(not(test))]
use std::old_io::File;

#[cfg(not(test))]
fn main() {
	if env::args().count() < 2 {
		panic!("Must pass a file to decode")
	}

	let arg = match env::args().nth(1) {
		Some(s) => s,
		None => panic!("No input argument given")
	};
	println!("input: {:?}", arg);
	let output = detect_xor_in_file(arg.as_slice());
	println!("output string: {:?}", output);
}

#[cfg(not(test))]
fn detect_xor_in_file(path: &str) -> String {
	let path = Path::new(path);
	let mut file = BufferedReader::new(File::open(&path));
	let lines = file.lines().map(|x| x.unwrap()).collect();

	detect_xor_in_lines(lines)

}

fn detect_xor_in_lines(lines: Vec<String>) -> String {
	let mut best_string_score = 0;
	let mut best_string = String::new();

	for line in lines.iter() {
	    let pairs = convert_hex_string_to_decimal_pairs(line);
	    match score_and_xor(pairs) {
	    	(score, string) => {
	    		if score > best_string_score {
	    			best_string_score = score;
	    			best_string = string;
	    		}
	    	}
	    };
	}

	best_string
}

fn score_and_xor(decimal_values: Vec<u8>) -> (usize, String) {
	let mut best_string = String::new();
	let mut best_string_score = 0;

	// starting with 0, test the current string just in case
	for test_val in 0..255 {
		debug!("{:?}", test_val);
		let mut decoded_values = vec!();
		for &x in decimal_values.iter() {
			decoded_values.push(x ^ test_val);
		}

		// turn the byte vector into a string
		match str::from_utf8(decoded_values.as_slice()) {
		    Ok(v) => {
		        let score = score_text(v);
		        if score > best_string_score {
		        	best_string = v.to_string();
		        	best_string_score = score;
		        }
		    }
		    Err(_) => { }
		}
	}
	(best_string_score, best_string)
}

fn convert_hex_string_to_decimal_pairs(string: &String) -> Vec<u8> {
	let string_lower = string.to_ascii_lowercase();
	let bytes = string_lower.as_bytes();

	let mut decimal_values = vec!();
	let mut tick = 1;
	let mut current_byte = 0;

	for &x in bytes.iter() {
		current_byte += convert_hex_char_to_decimal(x) * 16.pow(tick);
		tick = tick ^ 1;
		if tick == 1 {
			decimal_values.push(current_byte);
			current_byte = 0;
		}
	}

	decimal_values
}

fn convert_hex_char_to_decimal(character: u8) -> u8 {
	// if x is in the ascii range for numbers, subtract 48,
	// which is '0' in ascii. Otherwise, it should be a lowercase letter.
	// 'a' is 97, so subtract 87.
	match character < 58 {
		true => character - 48,
		false => character - 87
	}
}

// these are strings so that they can be used in StrExt.replace.
// this seemed easier than converting chars to strings every time.
// characters are taken from relative frequency of letters in the english language:
// https://en.wikipedia.org/wiki/Letter_frequency
static VALUED_CHARS: &'static[&'static str] = &["e", "t", "a", "o", "n"];

// this scoring function is extremely simple/fragile. that said,
// it completes this challenge
fn score_text(text: &str) -> usize {
	let mut score: usize = 0;
	// if we have \u{0} in the output, the text is probably the opposite
	// of what it needs to be, so throw this string out.
	// (the xor-opposite of \u{0} is a space)
	if text.len() != text.replace("\u{0}", "").len() {
		return 0;
	}
	let lowercase = text.to_ascii_lowercase();
	for &test_char in VALUED_CHARS {
		let test_str = lowercase.replace(test_char, "");
		score += text.len() - test_str.len();
		debug!("input: {:?}, test: {:?}, score increase: {:?}", text, test_str, text.len() - test_str.len());
	}
	return score;
}

#[cfg(test)]
mod set1challenge4 {

	#[test]
	fn test() {
		let output = super::detect_xor_in_lines(vec!("1234567890ABCDEF123456".to_string(), "4574626531626563787f76".to_string(), "FEDCBA0987654321FEDCBA".to_string()));
		assert_eq!(output, "Test string");
	}

}
<commit_msg>Clean up a comment<commit_after>// Single-byte XOR cipher
// The hex encoded string:

// 1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736
// ... has been XOR'd against a single character. Find the key, decrypt the message.

// You can do this by hand. But don't: write code to do it for you.

// How? Devise some method for "scoring" a piece of English plaintext.
// Character frequency is a good metric. Evaluate each output and choose the one with the best score.

// i/o is undergoing an overhaul, so let's silence that warning
#![allow(unused_features)]

#![feature(core)]
#![feature(env)]
#![feature(io)]
#![feature(old_io)]
#![feature(old_path)]
#![feature(os)]
#![feature(path)]
#![feature(std_misc)]

#[macro_use]
extern crate log;

use std::ascii::AsciiExt;
use std::num::Int;

use std::str;

#[cfg(not(test))]
use std::env;
#[cfg(not(test))]
use std::old_io::BufferedReader;
#[cfg(not(test))]
use std::old_io::File;

#[cfg(not(test))]
fn main() {
	if env::args().count() < 2 {
		panic!("Must pass a file to decode")
	}

	let arg = match env::args().nth(1) {
		Some(s) => s,
		None => panic!("No input argument given")
	};
	println!("input: {:?}", arg);
	let output = detect_xor_in_file(arg.as_slice());
	println!("output string: {:?}", output);
}

#[cfg(not(test))]
fn detect_xor_in_file(path: &str) -> String {
	let path = Path::new(path);
	let mut file = BufferedReader::new(File::open(&path));
	let lines = file.lines().map(|x| x.unwrap()).collect();

	detect_xor_in_lines(lines)

}

fn detect_xor_in_lines(lines: Vec<String>) -> String {
	let mut best_string_score = 0;
	let mut best_string = String::new();

	for line in lines.iter() {
	    let pairs = convert_hex_string_to_decimal_pairs(line);
	    match score_and_xor(pairs) {
	    	(score, string) => {
	    		if score > best_string_score {
	    			best_string_score = score;
	    			best_string = string;
	    		}
	    	}
	    };
	}

	best_string
}

fn score_and_xor(decimal_values: Vec<u8>) -> (usize, String) {
	let mut best_string = String::new();
	let mut best_string_score = 0;

	// starting with 0, test the current string just in case
	for test_val in 0..255 {
		debug!("{:?}", test_val);
		let mut decoded_values = vec!();
		for &x in decimal_values.iter() {
			decoded_values.push(x ^ test_val);
		}

		// turn the byte vector into a string
		match str::from_utf8(decoded_values.as_slice()) {
		    Ok(v) => {
		        let score = score_text(v);
		        if score > best_string_score {
		        	best_string = v.to_string();
		        	best_string_score = score;
		        }
		    }
		    Err(_) => { }
		}
	}
	(best_string_score, best_string)
}

fn convert_hex_string_to_decimal_pairs(string: &String) -> Vec<u8> {
	let string_lower = string.to_ascii_lowercase();
	let bytes = string_lower.as_bytes();

	let mut decimal_values = vec!();
	let mut tick = 1;
	let mut current_byte = 0;

	for &x in bytes.iter() {
		current_byte += convert_hex_char_to_decimal(x) * 16.pow(tick);
		tick = tick ^ 1;
		if tick == 1 {
			decimal_values.push(current_byte);
			current_byte = 0;
		}
	}

	decimal_values
}

fn convert_hex_char_to_decimal(character: u8) -> u8 {
	// if x is in the ascii range for numbers, subtract 48,
	// which is '0' in ascii. Otherwise, it should be a lowercase letter.
	// 'a' is 97, so subtract 87.
	match character < 58 {
		true => character - 48,
		false => character - 87
	}
}

// these are strings so that they can be used in StrExt.replace.
// this seemed easier than converting chars to strings every time.
// characters are taken from relative frequency of letters in the english language:
// https://en.wikipedia.org/wiki/Letter_frequency
static VALUED_CHARS: &'static[&'static str] = &["e", "t", "a", "o", "n"];

// this scoring function is extremely simple/fragile. that said,
// it completes this challenge
fn score_text(text: &str) -> usize {
	let mut score: usize = 0;
	// if we have \u{0} in the output, the text is probably the opposite
	// of what it needs to be, so throw this string out.
	// (the xor-opposite of \u{0} is a space)
	if text.len() != text.replace("\u{0}", "").len() {
		return 0;
	}
	let lowercase = text.to_ascii_lowercase();
	for &test_char in VALUED_CHARS {
		let test_str = lowercase.replace(test_char, "");
		score += text.len() - test_str.len();
		debug!("input: {:?}, test: {:?}, score increase: {:?}", text, test_str, text.len() - test_str.len());
	}
	return score;
}

#[cfg(test)]
mod set1challenge4 {

	#[test]
	fn test() {
		let output = super::detect_xor_in_lines(vec!("1234567890ABCDEF123456".to_string(), "4574626531626563787f76".to_string(), "FEDCBA0987654321FEDCBA".to_string()));
		assert_eq!(output, "Test string");
	}

}
<|endoftext|>


<commit_before>use glium::{Display, Program};
use glium::uniforms::{Uniforms, UniformValue, AsUniformValue};
use texture::TextureRef;
use mesh::{Vertex, VertexType};

pub trait Shader {
    type Vertex: VertexType;
    type Uniforms: Uniforms;

    fn program(&Display) -> Program;
}

pub struct Default;

impl Shader for Default {
    type Vertex = Vertex;
    type Uniforms = DefaultUniforms;

    fn program(display: &Display) -> Program {
        let vert = include_str!("shader/default.vert");
        let frag = include_str!("shader/default.frag");
        program!(display,
            140 => {
                vertex: vert,
                fragment: frag,
            },
        ).unwrap()
    }
}

#[macro_export]
macro_rules! uniforms_define {
    ($struct_name:ident {$($field:ident: $t:ty),*}) => {
        pub struct $struct_name {
            $(
                pub $field: $t,
            )*
        }

        impl $crate::glium::uniforms::Uniforms for $struct_name {
            fn visit_values<'a, F>(&'a self, mut output: F)
                where F: FnMut(&str, UniformValue<'a>)
            {
                $(
                    output(stringify!($field), self.$field.as_uniform_value());
                )*
            }
        }
    };
    ($struct_name:ident {$($field:ident: $t:ty),*,}) => {
        uniforms_define! { $struct_name {$($field: $t),*} }
    }
}

uniforms_define! {
    DefaultUniforms {
        tex: TextureRef,
        matrix: [[f32; 4]; 4],
    }
}

<commit_msg>Fix macro bug<commit_after>use glium::{Display, Program};
pub use glium::uniforms::{Uniforms, UniformValue, AsUniformValue};
use texture::TextureRef;
use mesh::{Vertex, VertexType};

pub trait Shader {
    type Vertex: VertexType;
    type Uniforms: Uniforms;

    fn program(&Display) -> Program;
}

pub struct Default;

impl Shader for Default {
    type Vertex = Vertex;
    type Uniforms = DefaultUniforms;

    fn program(display: &Display) -> Program {
        let vert = include_str!("shader/default.vert");
        let frag = include_str!("shader/default.frag");
        program!(display,
            140 => {
                vertex: vert,
                fragment: frag,
            },
        ).unwrap()
    }
}

#[macro_export]
macro_rules! uniforms_define {
    ($struct_name:ident {$($field:ident: $t:ty),*}) => {
        pub struct $struct_name {
            $(
                pub $field: $t,
            )*
        }

        impl $crate::shader::Uniforms for $struct_name {
            fn visit_values<'a, F>(&'a self, mut output: F)
                where F: FnMut(&str, $crate::shader::UniformValue<'a>)
            {
                use $crate::shader::AsUniformValue;
                $(
                    output(stringify!($field), self.$field.as_uniform_value());
                )*
            }
        }
    };
    ($struct_name:ident {$($field:ident: $t:ty),*,}) => {
        uniforms_define! { $struct_name {$($field: $t),*} }
    }
}

uniforms_define! {
    DefaultUniforms {
        tex: TextureRef,
        matrix: [[f32; 4]; 4],
    }
}

<|endoftext|>


<commit_before>use metadata;
use frame;
use subframe;

use metadata::{Metadata, StreamInfo};
use frame::frame_parser;
use utility::{
  ErrorKind, ByteStream, ReadStream, Sample, StreamProducer, many_metadata,
};

use std::io;
use std::usize;
use std::fs::File;

/// FLAC stream that decodes and hold file information.
pub struct Stream
 {
  info: StreamInfo,
  metadata: Vec<Metadata>,
  producer: P,
}

/// Alias for a FLAC stream produced from `Read`.
pub type StreamReader<R>  = Stream<ReadStream<R>>;

/// Alias for a FLAC stream produced from a byte stream buffer.
pub type StreamBuffer<'a> = Stream<ByteStream<'a>>;

impl
 Stream
 where P: StreamProducer {
  /// Constructor for the default state of a FLAC stream.
  #[inline]
  pub fn new<R: io::Read>(reader: R) -> Result<StreamReader<R>, ErrorKind> {
    let producer = ReadStream::new(reader);

    Stream::from_stream_producer(producer)
  }

  /// Returns information for the current stream.
  #[inline]
  pub fn info(&self) -> StreamInfo {
    self.info
  }

  /// Returns a slice of `Metadata`
  ///
  /// This slice excludes `StreamInfo`, which is located in `Stream::info`.
  /// Everything else is related to metadata for the FLAC stream is in the
  /// slice.
  #[inline]
  pub fn metadata(&self) -> &[Metadata] {
    &self.metadata
  }

  /// Constructs a decoder with the given file name.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::IO(io::ErrorKind::NotFound)` is returned when the given
  ///   filename isn't found.
  /// * `ErrorKind::IO(io::ErrorKind::InvalidData)` is returned when the data
  ///   within the file isn't valid FLAC data.
  /// * Several different parser specific errors that are structured as
  ///   `ErrorKind::<parser_name>Parser`.
  /// * Several different invalidation specific errors that are
  ///   structured as `ErrorKind::Invalid<invalidation_name>`.
  #[inline]
  pub fn from_file(filename: &str) -> Result<StreamReader<File>, ErrorKind> {
    File::open(filename).map_err(|e| ErrorKind::IO(e.kind()))
                        .and_then(|file| {
      let producer = ReadStream::new(file);

      Stream::from_stream_producer(producer)
    })
  }

  /// Constructs a decoder with the given buffer.
  ///
  /// This constructor assumes that an entire FLAC file is in the buffer.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::IO(io::ErrorKind::InvalidData)` is returned when the data
  ///   within the file isn't valid FLAC data.
  /// * Several different parser specific errors that are structured as
  ///   `ErrorKind::<parser_name>Parser`.
  /// * Several different invalidation specific errors that are
  ///   structured as `ErrorKind::Invalid<invalidation_name>`.
  #[inline]
  pub fn from_buffer(buffer: &[u8]) -> Result<StreamBuffer, ErrorKind> {
    let producer = ByteStream::new(buffer);

    Stream::from_stream_producer(producer)
  }

  fn from_stream_producer(mut producer: P) -> Result<Self, ErrorKind> {
    let mut stream_info = StreamInfo::new();
    let mut metadata    = Vec::new();

    many_metadata(&mut producer, |block| {
      if let metadata::Data::StreamInfo(info) = block.data {
        stream_info = info;
      } else {
        metadata.push(block);
      }
    }).map(|_| {
      Stream {
        info: stream_info,
        metadata: metadata,
        producer: producer,
      }
    })
  }

  /// Returns an iterator over the decoded samples.
  #[inline]
  pub fn iter<S: Sample>(&mut self) -> Iter
 {
    let samples_left = self.info.total_samples;
    let channels     = self.info.channels as usize;
    let block_size   = self.info.max_block_size as usize;
    let buffer_size  = block_size * channels;

    Iter {
      stream: self,
      channel: 0,
      block_size: 0,
      sample_index: 0,
      samples_left: samples_left,
      buffer: vec![S::from_i8(0); buffer_size]
    }
  }

  fn next_frame<S>(&mut self, buffer: &mut [S]) -> Option<usize>
   where S: Sample {
    let stream_info = &self.info;

    loop {
      match self.producer.parse(|i| frame_parser(i, stream_info, buffer)) {
        Ok(frame)                  => {
          let channels    = frame.header.channels as usize;
          let block_size  = frame.header.block_size as usize;
          let mut channel = 0;

          for subframe in &frame.subframes[0..channels] {
            let start  = channel * block_size;
            let end    = (channel + 1) * block_size;
            let output = &mut buffer[start..end];

            subframe::decode(&subframe, block_size, output);

            channel += 1;
          }

          frame::decode(frame.header.channel_assignment, buffer);

          return Some(block_size);
        }
        Err(ErrorKind::EndOfInput) => return None,
        Err(ErrorKind::Continue)   => continue,
        Err(_)                     => return None,
      }
    }
  }
}

/// An iterator over a reference of the decoded FLAC stream.
pub struct Iter<'a, P, S>
 where P: 'a + StreamProducer,
       S: Sample{
  stream: &'a mut Stream
,
  channel: usize,
  block_size: usize,
  sample_index: usize,
  samples_left: u64,
  buffer: Vec<S>,
}

impl<'a, P, S> Iterator for Iter<'a, P, S>
 where P: StreamProducer,
       S: Sample {
  type Item = S::Normal;

  fn next(&mut self) -> Option<Self::Item> {
    if self.sample_index == self.block_size {
      let buffer = &mut self.buffer;

      if let Some(block_size) = self.stream.next_frame(buffer) {
        self.sample_index = 0;
        self.block_size   = block_size;
      } else {
        return None;
      }
    }

    let channels = self.stream.info.channels as usize;
    let index    = self.sample_index + (self.channel * self.block_size);
    let sample   = self.buffer[index];

    self.channel += 1;

    // Reset current channel
    if self.channel == channels {
      self.channel       = 0;
      self.sample_index += 1;
      self.samples_left -= 1;
    }

    S::to_normal(sample)
  }

  fn size_hint(&self) -> (usize, Option<usize>) {
    let samples_left = self.samples_left as usize;
    let max_value    = usize::max_value() as u64;

    // There is a chance that samples_left will be larger than a usize since
    // it is a u64. Make the upper bound None when it is.
    if self.samples_left > max_value {
      (samples_left, None)
    } else {
      (samples_left, Some(samples_left))
    }
  }
}

//impl<'a, P, S> IntoIterator for &'a mut Stream

// where P: StreamProducer,
//       S: Sample {
//  type Item     = S::Normal;
//  type IntoIter = Iter<'a, P, S>;
//
//  #[inline]
//  fn into_iter(self) -> Self::IntoIter {
//    self.iter()
//  }
//}
<commit_msg>Use SampleSize in `Stream::iter`<commit_after>use metadata;
use frame;
use subframe;

use metadata::{Metadata, StreamInfo};
use frame::frame_parser;
use utility::{
  ErrorKind, ByteStream, ReadStream, Sample, SampleSize, StreamProducer,
  many_metadata,
};

use std::io;
use std::usize;
use std::fs::File;

/// FLAC stream that decodes and hold file information.
pub struct Stream
 {
  info: StreamInfo,
  metadata: Vec<Metadata>,
  producer: P,
}

/// Alias for a FLAC stream produced from `Read`.
pub type StreamReader<R>  = Stream<ReadStream<R>>;

/// Alias for a FLAC stream produced from a byte stream buffer.
pub type StreamBuffer<'a> = Stream<ByteStream<'a>>;

impl
 Stream
 where P: StreamProducer {
  /// Constructor for the default state of a FLAC stream.
  #[inline]
  pub fn new<R: io::Read>(reader: R) -> Result<StreamReader<R>, ErrorKind> {
    let producer = ReadStream::new(reader);

    Stream::from_stream_producer(producer)
  }

  /// Returns information for the current stream.
  #[inline]
  pub fn info(&self) -> StreamInfo {
    self.info
  }

  /// Returns a slice of `Metadata`
  ///
  /// This slice excludes `StreamInfo`, which is located in `Stream::info`.
  /// Everything else is related to metadata for the FLAC stream is in the
  /// slice.
  #[inline]
  pub fn metadata(&self) -> &[Metadata] {
    &self.metadata
  }

  /// Constructs a decoder with the given file name.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::IO(io::ErrorKind::NotFound)` is returned when the given
  ///   filename isn't found.
  /// * `ErrorKind::IO(io::ErrorKind::InvalidData)` is returned when the data
  ///   within the file isn't valid FLAC data.
  /// * Several different parser specific errors that are structured as
  ///   `ErrorKind::<parser_name>Parser`.
  /// * Several different invalidation specific errors that are
  ///   structured as `ErrorKind::Invalid<invalidation_name>`.
  #[inline]
  pub fn from_file(filename: &str) -> Result<StreamReader<File>, ErrorKind> {
    File::open(filename).map_err(|e| ErrorKind::IO(e.kind()))
                        .and_then(|file| {
      let producer = ReadStream::new(file);

      Stream::from_stream_producer(producer)
    })
  }

  /// Constructs a decoder with the given buffer.
  ///
  /// This constructor assumes that an entire FLAC file is in the buffer.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::IO(io::ErrorKind::InvalidData)` is returned when the data
  ///   within the file isn't valid FLAC data.
  /// * Several different parser specific errors that are structured as
  ///   `ErrorKind::<parser_name>Parser`.
  /// * Several different invalidation specific errors that are
  ///   structured as `ErrorKind::Invalid<invalidation_name>`.
  #[inline]
  pub fn from_buffer(buffer: &[u8]) -> Result<StreamBuffer, ErrorKind> {
    let producer = ByteStream::new(buffer);

    Stream::from_stream_producer(producer)
  }

  fn from_stream_producer(mut producer: P) -> Result<Self, ErrorKind> {
    let mut stream_info = StreamInfo::new();
    let mut metadata    = Vec::new();

    many_metadata(&mut producer, |block| {
      if let metadata::Data::StreamInfo(info) = block.data {
        stream_info = info;
      } else {
        metadata.push(block);
      }
    }).map(|_| {
      Stream {
        info: stream_info,
        metadata: metadata,
        producer: producer,
      }
    })
  }

  /// Returns an iterator over the decoded samples.
  #[inline]
  pub fn iter<S: SampleSize>(&mut self) -> Iter
 {
    let samples_left = self.info.total_samples;
    let channels     = self.info.channels as usize;
    let block_size   = self.info.max_block_size as usize;
    let buffer_size  = block_size * channels;

    Iter {
      stream: self,
      channel: 0,
      block_size: 0,
      sample_index: 0,
      samples_left: samples_left,
      buffer: vec![S::Extended::from_i8(0); buffer_size]
    }
  }

  fn next_frame<S>(&mut self, buffer: &mut [S]) -> Option<usize>
   where S: Sample {
    let stream_info = &self.info;

    loop {
      match self.producer.parse(|i| frame_parser(i, stream_info, buffer)) {
        Ok(frame)                  => {
          let channels    = frame.header.channels as usize;
          let block_size  = frame.header.block_size as usize;
          let mut channel = 0;

          for subframe in &frame.subframes[0..channels] {
            let start  = channel * block_size;
            let end    = (channel + 1) * block_size;
            let output = &mut buffer[start..end];

            subframe::decode(&subframe, block_size, output);

            channel += 1;
          }

          frame::decode(frame.header.channel_assignment, buffer);

          return Some(block_size);
        }
        Err(ErrorKind::EndOfInput) => return None,
        Err(ErrorKind::Continue)   => continue,
        Err(_)                     => return None,
      }
    }
  }
}

/// An iterator over a reference of the decoded FLAC stream.
pub struct Iter<'a, P, S>
 where P: 'a + StreamProducer,
       S: Sample{
  stream: &'a mut Stream
,
  channel: usize,
  block_size: usize,
  sample_index: usize,
  samples_left: u64,
  buffer: Vec<S>,
}

impl<'a, P, S> Iterator for Iter<'a, P, S>
 where P: StreamProducer,
       S: Sample {
  type Item = S::Normal;

  fn next(&mut self) -> Option<Self::Item> {
    if self.sample_index == self.block_size {
      let buffer = &mut self.buffer;

      if let Some(block_size) = self.stream.next_frame(buffer) {
        self.sample_index = 0;
        self.block_size   = block_size;
      } else {
        return None;
      }
    }

    let channels = self.stream.info.channels as usize;
    let index    = self.sample_index + (self.channel * self.block_size);
    let sample   = self.buffer[index];

    self.channel += 1;

    // Reset current channel
    if self.channel == channels {
      self.channel       = 0;
      self.sample_index += 1;
      self.samples_left -= 1;
    }

    S::to_normal(sample)
  }

  fn size_hint(&self) -> (usize, Option<usize>) {
    let samples_left = self.samples_left as usize;
    let max_value    = usize::max_value() as u64;

    // There is a chance that samples_left will be larger than a usize since
    // it is a u64. Make the upper bound None when it is.
    if self.samples_left > max_value {
      (samples_left, None)
    } else {
      (samples_left, Some(samples_left))
    }
  }
}

//impl<'a, P, S> IntoIterator for &'a mut Stream

// where P: StreamProducer,
//       S: Sample {
//  type Item     = S::Normal;
//  type IntoIter = Iter<'a, P, S>;
//
//  #[inline]
//  fn into_iter(self) -> Self::IntoIter {
//    self.iter()
//  }
//}
<|endoftext|>