<commit_before>//! Owned and borrowed OS sockets.

#![unstable(feature = "io_safety", issue = "87074")]

use super::raw::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
use crate::fmt;
use crate::marker::PhantomData;
use crate::mem::forget;
use crate::sys::c;

/// A borrowed socket.
///
/// This has a lifetime parameter to tie it to the lifetime of something that
/// owns the socket.
///
/// This uses `repr(transparent)` and has the representation of a host socket,
/// so it can be used in FFI in places where a socket is passed as an argument,
/// it is not captured or consumed, and it never has the value
/// `INVALID_SOCKET`.
#[derive(Copy, Clone)]
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(0)]
// This is -2, in two's complement. -1 is `INVALID_SOCKET`.
#[cfg_attr(target_pointer_width = "32", rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE))]
#[cfg_attr(
    target_pointer_width = "64",
    rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FF_FF_FF_FF_FE)
)]
#[unstable(feature = "io_safety", issue = "87074")]
pub struct BorrowedSocket<'socket> {
    raw: RawSocket,
    _phantom: PhantomData<&'socket OwnedSocket>,
}

/// An owned socket.
///
/// This closes the socket on drop.
///
/// This uses `repr(transparent)` and has the representation of a host socket,
/// so it can be used in FFI in places where a socket is passed as a consumed
/// argument or returned as an owned value, and it never has the value
/// `INVALID_SOCKET`.
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(0)]
// This is -2, in two's complement. -1 is `INVALID_SOCKET`.
#[cfg_attr(target_pointer_width = "32", rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE))]
#[cfg_attr(
    target_pointer_width = "64",
    rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FF_FF_FF_FF_FE)
)]
#[unstable(feature = "io_safety", issue = "87074")]
pub struct OwnedSocket {
    raw: RawSocket,
}

impl BorrowedSocket<'_> {
    /// Return a `BorrowedSocket` holding the given raw socket.
    ///
    /// # Safety
    ///
    /// The resource pointed to by `raw` must remain open for the duration of
    /// the returned `BorrowedSocket`, and it must not have the value
    /// `INVALID_SOCKET`.
    #[inline]
    #[unstable(feature = "io_safety", issue = "87074")]
    pub unsafe fn borrow_raw_socket(raw: RawSocket) -> Self {
        debug_assert_ne!(raw, c::INVALID_SOCKET as RawSocket);
        Self { raw, _phantom: PhantomData }
    }
}

impl AsRawSocket for BorrowedSocket<'_> {
    #[inline]
    fn as_raw_socket(&self) -> RawSocket {
        self.raw
    }
}

impl AsRawSocket for OwnedSocket {
    #[inline]
    fn as_raw_socket(&self) -> RawSocket {
        self.raw
    }
}

impl IntoRawSocket for OwnedSocket {
    #[inline]
    fn into_raw_socket(self) -> RawSocket {
        let raw = self.raw;
        forget(self);
        raw
    }
}

impl FromRawSocket for OwnedSocket {
    /// Constructs a new instance of `Self` from the given raw socket.
    ///
    /// # Safety
    ///
    /// The resource pointed to by `raw` must be open and suitable for assuming
    /// ownership.
    #[inline]
    unsafe fn from_raw_socket(raw: RawSocket) -> Self {
        debug_assert_ne!(raw, c::INVALID_SOCKET as RawSocket);
        Self { raw }
    }
}

impl Drop for OwnedSocket {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let _ = c::closesocket(self.raw);
        }
    }
}

impl fmt::Debug for BorrowedSocket<'_> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("BorrowedSocket").field("socket", &self.raw).finish()
    }
}

impl fmt::Debug for OwnedSocket {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("OwnedSocket").field("socket", &self.raw).finish()
    }
}

/// A trait to borrow the socket from an underlying object.
#[unstable(feature = "io_safety", issue = "87074")]
pub trait AsSocket {
    /// Borrows the socket.
    fn as_socket(&self) -> BorrowedSocket<'_>;
}

impl AsSocket for BorrowedSocket<'_> {
    #[inline]
    fn as_socket(&self) -> BorrowedSocket<'_> {
        *self
    }
}

impl AsSocket for OwnedSocket {
    #[inline]
    fn as_socket(&self) -> BorrowedSocket<'_> {
        unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) }
    }
}

impl AsSocket for crate::net::TcpStream {
    #[inline]
    fn as_socket(&self) -> BorrowedSocket<'_> {
        unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) }
    }
}

impl From<crate::net::TcpStream> for OwnedSocket {
    #[inline]
    fn from(tcp_stream: crate::net::TcpStream) -> OwnedSocket {
        unsafe { OwnedSocket::from_raw_socket(tcp_stream.into_raw_socket()) }
    }
}

impl From<OwnedSocket> for crate::net::TcpStream {
    #[inline]
    fn from(owned: OwnedSocket) -> Self {
        unsafe { Self::from_raw_socket(owned.into_raw_socket()) }
    }
}

impl AsSocket for crate::net::TcpListener {
    #[inline]
    fn as_socket(&self) -> BorrowedSocket<'_> {
        unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) }
    }
}

impl From<crate::net::TcpListener> for OwnedSocket {
    #[inline]
    fn from(tcp_listener: crate::net::TcpListener) -> OwnedSocket {
        unsafe { OwnedSocket::from_raw_socket(tcp_listener.into_raw_socket()) }
    }
}

impl From<OwnedSocket> for crate::net::TcpListener {
    #[inline]
    fn from(owned: OwnedSocket) -> Self {
        unsafe { Self::from_raw_socket(owned.into_raw_socket()) }
    }
}

impl AsSocket for crate::net::UdpSocket {
    #[inline]
    fn as_socket(&self) -> BorrowedSocket<'_> {
        unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) }
    }
}

impl From<crate::net::UdpSocket> for OwnedSocket {
    #[inline]
    fn from(udp_socket: crate::net::UdpSocket) -> OwnedSocket {
        unsafe { OwnedSocket::from_raw_socket(udp_socket.into_raw_socket()) }
    }
}

impl From<OwnedSocket> for crate::net::UdpSocket {
    #[inline]
    fn from(owned: OwnedSocket) -> Self {
        unsafe { Self::from_raw_socket(owned.into_raw_socket()) }
    }
}
<commit_msg>Update library/std/src/os/windows/io/socket.rs<commit_after>//! Owned and borrowed OS sockets.

#![unstable(feature = "io_safety", issue = "87074")]

use super::raw::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
use crate::fmt;
use crate::marker::PhantomData;
use crate::mem::forget;
use crate::sys::c;

/// A borrowed socket.
///
/// This has a lifetime parameter to tie it to the lifetime of something that
/// owns the socket.
///
/// This uses `repr(transparent)` and has the representation of a host socket,
/// so it can be used in FFI in places where a socket is passed as an argument,
/// it is not captured or consumed, and it never has the value
/// `INVALID_SOCKET`.
#[derive(Copy, Clone)]
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(0)]
// This is -2, in two's complement. -1 is `INVALID_SOCKET`.
#[cfg_attr(target_pointer_width = "32", rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE))]
#[cfg_attr(
    target_pointer_width = "64",
    rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FF_FF_FF_FF_FE)
)]
#[unstable(feature = "io_safety", issue = "87074")]
pub struct BorrowedSocket<'socket> {
    raw: RawSocket,
    _phantom: PhantomData<&'socket OwnedSocket>,
}

/// An owned socket.
///
/// This closes the socket on drop.
///
/// This uses `repr(transparent)` and has the representation of a host socket,
/// so it can be used in FFI in places where a socket is passed as a consumed
/// argument or returned as an owned value, and it never has the value
/// `INVALID_SOCKET`.
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(0)]
// This is -2, in two's complement. -1 is `INVALID_SOCKET`.
#[cfg_attr(target_pointer_width = "32", rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE))]
#[cfg_attr(
    target_pointer_width = "64",
    rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FF_FF_FF_FF_FE)
)]
#[unstable(feature = "io_safety", issue = "87074")]
pub struct OwnedSocket {
    raw: RawSocket,
}

impl BorrowedSocket<'_> {
    /// Return a `BorrowedSocket` holding the given raw socket.
    ///
    /// # Safety
    ///
    /// The resource pointed to by `raw` must remain open for the duration of
    /// the returned `BorrowedSocket`, and it must not have the value
    /// `INVALID_SOCKET`.
    #[inline]
    #[unstable(feature = "io_safety", issue = "87074")]
    pub unsafe fn borrow_raw_socket(raw: RawSocket) -> Self {
        debug_assert_ne!(raw, c::INVALID_SOCKET as RawSocket);
        Self { raw, _phantom: PhantomData }
    }
}

impl AsRawSocket for BorrowedSocket<'_> {
    #[inline]
    fn as_raw_socket(&self) -> RawSocket {
        self.raw
    }
}

impl AsRawSocket for OwnedSocket {
    #[inline]
    fn as_raw_socket(&self) -> RawSocket {
        self.raw
    }
}

impl IntoRawSocket for OwnedSocket {
    #[inline]
    fn into_raw_socket(self) -> RawSocket {
        let raw = self.raw;
        forget(self);
        raw
    }
}

impl FromRawSocket for OwnedSocket {
    /// Constructs a new instance of `Self` from the given raw socket.
    ///
    /// # Safety
    ///
    /// The resource pointed to by `raw` must be open and suitable for assuming
    /// ownership. The resource must not require cleanup other than `closesocket`.
    #[inline]
    unsafe fn from_raw_socket(raw: RawSocket) -> Self {
        debug_assert_ne!(raw, c::INVALID_SOCKET as RawSocket);
        Self { raw }
    }
}

impl Drop for OwnedSocket {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let _ = c::closesocket(self.raw);
        }
    }
}

impl fmt::Debug for BorrowedSocket<'_> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("BorrowedSocket").field("socket", &self.raw).finish()
    }
}

impl fmt::Debug for OwnedSocket {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("OwnedSocket").field("socket", &self.raw).finish()
    }
}

/// A trait to borrow the socket from an underlying object.
#[unstable(feature = "io_safety", issue = "87074")]
pub trait AsSocket {
    /// Borrows the socket.
    fn as_socket(&self) -> BorrowedSocket<'_>;
}

impl AsSocket for BorrowedSocket<'_> {
    #[inline]
    fn as_socket(&self) -> BorrowedSocket<'_> {
        *self
    }
}

impl AsSocket for OwnedSocket {
    #[inline]
    fn as_socket(&self) -> BorrowedSocket<'_> {
        unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) }
    }
}

impl AsSocket for crate::net::TcpStream {
    #[inline]
    fn as_socket(&self) -> BorrowedSocket<'_> {
        unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) }
    }
}

impl From<crate::net::TcpStream> for OwnedSocket {
    #[inline]
    fn from(tcp_stream: crate::net::TcpStream) -> OwnedSocket {
        unsafe { OwnedSocket::from_raw_socket(tcp_stream.into_raw_socket()) }
    }
}

impl From<OwnedSocket> for crate::net::TcpStream {
    #[inline]
    fn from(owned: OwnedSocket) -> Self {
        unsafe { Self::from_raw_socket(owned.into_raw_socket()) }
    }
}

impl AsSocket for crate::net::TcpListener {
    #[inline]
    fn as_socket(&self) -> BorrowedSocket<'_> {
        unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) }
    }
}

impl From<crate::net::TcpListener> for OwnedSocket {
    #[inline]
    fn from(tcp_listener: crate::net::TcpListener) -> OwnedSocket {
        unsafe { OwnedSocket::from_raw_socket(tcp_listener.into_raw_socket()) }
    }
}

impl From<OwnedSocket> for crate::net::TcpListener {
    #[inline]
    fn from(owned: OwnedSocket) -> Self {
        unsafe { Self::from_raw_socket(owned.into_raw_socket()) }
    }
}

impl AsSocket for crate::net::UdpSocket {
    #[inline]
    fn as_socket(&self) -> BorrowedSocket<'_> {
        unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) }
    }
}

impl From<crate::net::UdpSocket> for OwnedSocket {
    #[inline]
    fn from(udp_socket: crate::net::UdpSocket) -> OwnedSocket {
        unsafe { OwnedSocket::from_raw_socket(udp_socket.into_raw_socket()) }
    }
}

impl From<OwnedSocket> for crate::net::UdpSocket {
    #[inline]
    fn from(owned: OwnedSocket) -> Self {
        unsafe { Self::from_raw_socket(owned.into_raw_socket()) }
    }
}
<|endoftext|>


<commit_before>#![no_std]

#[macro_use]
extern crate static_assertions;

assert_impl!(byte; u8, Send, Sync);
assert_impl!(slice; [u8], Send, Sync, AsRef<[u8]>);

#[cfg(feature = "failure")]
assert_impl!(ptr; *const u8, Send, Sync);

#[test]
fn str_impl() {
    assert_impl!(str, Send, Sync, AsRef<[u8]>);
}
<commit_msg>[Tests] Check assert_impl for slice IntoIterator<commit_after>#![no_std]

#[macro_use]
extern crate static_assertions;

assert_impl!(byte; u8, Send, Sync);
assert_impl!(iter; &[u8], IntoIterator /* TODO: <Item=&u8> */);
assert_impl!(slice; [u8], Send, Sync, AsRef<[u8]>);

#[cfg(feature = "failure")]
assert_impl!(ptr; *const u8, Send, Sync);

#[test]
fn str_impl() {
    assert_impl!(str, Send, Sync, AsRef<[u8]>);
}
<|endoftext|>


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

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

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: Ship::new(vec![[0, 0], [1, 0]]),
        }
    }

    /// Selects a space.
    pub fn select_space(&mut self, pos: &[u8; 2]) {
        let space_index = self.space_index(pos);
        let ship_hit = self.ships.iter().position(|s| s.pos().contains(pos));
        self.spaces[space_index].set_checked(ship_hit.is_some());
    }

    /// Checks whether a ship at the given position is sunk.
    ///
    /// If all spaces have been hit but the ship has not been set to sunk, then
    /// it will be sunk on execution of this method.
    pub fn is_ship_sunk_by_pos(&mut self, pos: &[u8; 2]) -> bool {
        // TODO return Result; send error if no ship at pos
        let hit_ship = self.ships.iter().position(|s| s.pos().contains(pos));
        let mut ship_sunk = false;

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

            if ship_sunk && self.ships[ship].is_active() {
                self.ships[ship].set_sunk();
            }
        }

        ship_sunk
    }

    /// Returns whether all of the player's ships have been sunk.
    pub fn all_ships_sunk(&self) -> bool {
        self.ships.iter().all(|ship| ship.is_sunk())
    }

    /// 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 = Direction::all();

        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: Direction) {
        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.len() as u8
            ) {
                self.temp_ship = Ship::new(ship);
            }
        }
    }

    pub fn place_temp_ship(&mut self) -> Result<(), &'static str> {
        let ship = self.temp_ship.pos().clone();

        if self.valid_ship_position(&ship) {
            let ship_index = self.ships.len();
            self.ships.push(Ship::new(ship.to_vec()));
            self.ships[ship_index].set_active()?;

            self.temp_ship = Ship::new(self.get_ship_position(
                [0, 0],
                Direction::West,
                self.ships[ship_index].len() as u8 + 1
            ).unwrap());
        }

        Ok(())
    }

    /// Rotates a ship during the ship placement game state.
    pub fn rotate_temp_ship(&mut self) {
        let ship_len = self.temp_ship.len() as u8;
        let dir = match self.temp_ship.dir() {
            Direction::North => Direction::East,
            Direction::East => Direction::South,
            Direction::South => Direction::West,
            Direction::West => Direction::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 {
            Direction::North => [
                old_start_pos[0],
                cmp::min(old_start_pos[1], self.grid_size[1] - ship_len),
            ],
            Direction::East => [
                cmp::max(old_start_pos[0], ship_len - 1),
                old_start_pos[1],
            ],
            Direction::South => [
                old_start_pos[0],
                cmp::max(old_start_pos[1], ship_len - 1),
            ],
            Direction::West => [
                cmp::min(old_start_pos[0], self.grid_size[0] - ship_len),
                old_start_pos[1],
            ],
        };

        if let Some(ship) = self.get_ship_position(start_pos, dir, ship_len) {
            self.temp_ship = Ship::new(ship);
        }
    }

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

    /// RNGs ship locations for CPU players.
    fn cpu_place_ship(&self, length: u8) -> Vec<[u8; 2]> {
        // RNG a position and direction, then make sure it's valid.
        loop {
            let pos = self.rng_pos();
            let direction = Direction::random();

            if let Some(s) = self.get_ship_position(pos, direction, length) {
                if self.valid_ship_position(&s) {
                    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: Direction,
        length: u8
    ) -> Option<Vec<[u8; 2]>> {
        let valid = match direction {
            Direction::North => head[1] + length <= self.grid_size[1],
            Direction::East => head[0] >= length - 1,
            Direction::South => head[1] >= length - 1,
            Direction::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 {
                    Direction::North => [head[0], head[1] + pos_u8],
                    Direction::East => [head[0] - pos_u8, head[1]],
                    Direction::South => [head[0], head[1] - pos_u8],
                    Direction::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: Direction) -> Option<[u8; 2]> {
        let valid = match direction {
            Direction::North => pos[1] > 0,
            Direction::East => pos[0] < self.grid_size[0] - 1,
            Direction::South => pos[1] < self.grid_size[1] - 1,
            Direction::West => pos[0] > 0,
        };

        match valid {
            true => Some(match direction {
                Direction::North => [pos[0], pos[1] - 1],
                Direction::East => [pos[0] + 1, pos[1]],
                Direction::South => [pos[0], pos[1] + 1],
                Direction::West => [pos[0] - 1, pos[1]],
            }),
            false => 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: Direction,
        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: Direction) {
        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;
    }

    pub fn is_cpu(&self) -> bool {
        self.is_cpu
    }

    pub fn placement_ship(&self) -> &Ship {
        &self.temp_ship
    }

    pub fn placement_ship_mut(&mut self) -> &mut Ship {
        &mut self.temp_ship
    }
}

<commit_msg>Player select_space() now returns Result<commit_after>use std::cmp;
use rand::{
    Rng,
    seq::SliceRandom,
    thread_rng,
};
use crate::{
    direction::Direction,
    ship::Ship,
    space::Space,
};

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

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: Ship::new(vec![[0, 0], [1, 0]]),
        }
    }

    /// Selects a space.
    ///
    /// # Errors
    ///
    /// Returns an error if the space at `pos` was already checked.
    pub fn select_space(&mut self, pos: &[u8; 2]) -> Result<(), &'static str> {
        let space_index = self.space_index(pos);
        let ship_hit = self.ships.iter().position(|s| s.pos().contains(pos));
        self.spaces[space_index].set_checked(ship_hit.is_some())?;

        Ok(())
    }

    /// Checks whether a ship at the given position is sunk.
    ///
    /// If all spaces have been hit but the ship has not been set to sunk, then
    /// it will be sunk on execution of this method.
    pub fn is_ship_sunk_by_pos(&mut self, pos: &[u8; 2]) -> bool {
        // TODO return Result; send error if no ship at pos
        let hit_ship = self.ships.iter().position(|s| s.pos().contains(pos));
        let mut ship_sunk = false;

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

            if ship_sunk && self.ships[ship].is_active() {
                self.ships[ship].set_sunk();
            }
        }

        ship_sunk
    }

    /// Returns whether all of the player's ships have been sunk.
    pub fn all_ships_sunk(&self) -> bool {
        self.ships.iter().all(|ship| ship.is_sunk())
    }

    /// 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 = Direction::all();

        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: Direction) {
        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.len() as u8
            ) {
                self.temp_ship = Ship::new(ship);
            }
        }
    }

    pub fn place_temp_ship(&mut self) -> Result<(), &'static str> {
        let ship = self.temp_ship.pos().clone();

        if self.valid_ship_position(&ship) {
            let ship_index = self.ships.len();
            self.ships.push(Ship::new(ship.to_vec()));
            self.ships[ship_index].set_active()?;

            self.temp_ship = Ship::new(self.get_ship_position(
                [0, 0],
                Direction::West,
                self.ships[ship_index].len() as u8 + 1
            ).unwrap());
        }

        Ok(())
    }

    /// Rotates a ship during the ship placement game state.
    pub fn rotate_temp_ship(&mut self) {
        let ship_len = self.temp_ship.len() as u8;
        let dir = match self.temp_ship.dir() {
            Direction::North => Direction::East,
            Direction::East => Direction::South,
            Direction::South => Direction::West,
            Direction::West => Direction::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 {
            Direction::North => [
                old_start_pos[0],
                cmp::min(old_start_pos[1], self.grid_size[1] - ship_len),
            ],
            Direction::East => [
                cmp::max(old_start_pos[0], ship_len - 1),
                old_start_pos[1],
            ],
            Direction::South => [
                old_start_pos[0],
                cmp::max(old_start_pos[1], ship_len - 1),
            ],
            Direction::West => [
                cmp::min(old_start_pos[0], self.grid_size[0] - ship_len),
                old_start_pos[1],
            ],
        };

        if let Some(ship) = self.get_ship_position(start_pos, dir, ship_len) {
            self.temp_ship = Ship::new(ship);
        }
    }

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

    /// RNGs ship locations for CPU players.
    fn cpu_place_ship(&self, length: u8) -> Vec<[u8; 2]> {
        // RNG a position and direction, then make sure it's valid.
        loop {
            let pos = self.rng_pos();
            let direction = Direction::random();

            if let Some(s) = self.get_ship_position(pos, direction, length) {
                if self.valid_ship_position(&s) {
                    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: Direction,
        length: u8
    ) -> Option<Vec<[u8; 2]>> {
        let valid = match direction {
            Direction::North => head[1] + length <= self.grid_size[1],
            Direction::East => head[0] >= length - 1,
            Direction::South => head[1] >= length - 1,
            Direction::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 {
                    Direction::North => [head[0], head[1] + pos_u8],
                    Direction::East => [head[0] - pos_u8, head[1]],
                    Direction::South => [head[0], head[1] - pos_u8],
                    Direction::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: Direction) -> Option<[u8; 2]> {
        let valid = match direction {
            Direction::North => pos[1] > 0,
            Direction::East => pos[0] < self.grid_size[0] - 1,
            Direction::South => pos[1] < self.grid_size[1] - 1,
            Direction::West => pos[0] > 0,
        };

        match valid {
            true => Some(match direction {
                Direction::North => [pos[0], pos[1] - 1],
                Direction::East => [pos[0] + 1, pos[1]],
                Direction::South => [pos[0], pos[1] + 1],
                Direction::West => [pos[0] - 1, pos[1]],
            }),
            false => 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: Direction,
        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: Direction) {
        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;
    }

    pub fn is_cpu(&self) -> bool {
        self.is_cpu
    }

    pub fn placement_ship(&self) -> &Ship {
        &self.temp_ship
    }

    pub fn placement_ship_mut(&mut self) -> &mut Ship {
        &mut self.temp_ship
    }
}

<|endoftext|>


<commit_before>use syntax::ast::TokenTree;
use syntax::codemap::Span;
use syntax::ptr::P;

use syntax::ast::Expr;
use syntax::ext::base::{ExtCtxt, MacResult, MacEager};
use syntax::parse::parser::Parser;
use syntax::parse::token::Token;

pub fn expand<'cx>(cx: &'cx mut ExtCtxt, _: Span, tts: &[TokenTree]) -> Box<MacResult + 'cx> {
    let mut parser = cx.new_parser_from_tts(tts);
    let expr = parse_json(cx, &mut parser);
    if &parser.token != &Token::Eof {
        cx.span_fatal(parser.span, "expected end of `json!` macro invocation");
    }
    MacEager::expr(expr)
}

fn parse_json(cx: &ExtCtxt, parser: &mut Parser) -> P<Expr> {
    use syntax::ext::build::AstBuilder;
    use syntax::parse::token::{DelimToken, IdentStyle};

    macro_rules! comma_sep {
        () =>  {
            ::syntax::parse::common::SeqSep {
                sep: Some(Token::Comma),
                trailing_sep_allowed: true // we could be JSON pedants...
            }
        }
    }

    let orig_span = parser.span;

    match &parser.token {
        &Token::OpenDelim(DelimToken::Bracket) => {
            let _ = parser.bump();
            let r_bracket = Token::CloseDelim(DelimToken::Bracket);
            let exprs = parser.parse_seq_to_end(&r_bracket,
                                                comma_sep!(),
                                                |p| Ok(parse_json(cx, p)))
                              .ok()
                              .unwrap();
            let exprs = cx.expr_vec(orig_span, exprs);
            quote_expr!(cx, {
                use ::std::boxed::Box;
                let xs: Box<[_]> = Box::new($exprs);
                serde_json::Value::Array(xs.into_vec())
            })
        }
        &Token::OpenDelim(DelimToken::Brace) => {
            let _ = parser.bump();
            let r_brace = Token::CloseDelim(DelimToken::Brace);
            let kvs = parser.parse_seq_to_end(&r_brace, comma_sep!(), |p| {
                                let (istr, _) = p.parse_str().ok().unwrap();
                                let s = &*istr;
                                let _ = p.expect(&Token::Colon);
                                let key = quote_expr!(cx, {
                    use ::std::borrow::ToOwned;
                    $s.to_owned()
                });
                                Ok((key, parse_json(cx, p)))
                            })
                            .ok()
                            .unwrap();
            let mut insertions = vec![];
            // Can't use `quote_stmt!()` and interpolate a vector of
            // statements, seemingly.  Should consider filing a bug
            // upstream.
            for &(ref key, ref value) in kvs.iter() {
                insertions.push(quote_expr!(cx, {
                    _ob.insert($key, $value);
                }));
            }
            let expr = quote_expr!(cx, {
                let mut _ob = ::std::collections::BTreeMap::new();
                $insertions;
                ::serde_json::Value::Object(_ob)
            });
            expr
        }
        &Token::OpenDelim(DelimToken::Paren) => {
            let expr = parser.parse_expr().unwrap();
            quote_expr!(cx, {{
                ::serde_json::to_value(&$expr)
            }})
        }
        &Token::Ident(id, IdentStyle::Plain) if id.name.as_str() == "null" => {
            let _ = parser.bump();
            quote_expr!(cx, {
                ::serde_json::Value::Null
            })
        }
        _ => {
            // TODO: investigate can_begin_expr (maybe eliminate need for parens)?
            let expr = parser.parse_pat_literal_maybe_minus().ok().unwrap();
            quote_expr!(cx, {{
                ::serde_json::to_value(&$expr)
            }})
        }
    }
}
<commit_msg>emacs-format src/plugin.rs<commit_after>use syntax::ast::TokenTree;
use syntax::codemap::Span;
use syntax::ptr::P;

use syntax::ast::Expr;
use syntax::ext::base::{ExtCtxt, MacResult, MacEager};
use syntax::parse::parser::Parser;
use syntax::parse::token::Token;

pub fn expand<'cx>(cx: &'cx mut ExtCtxt, _: Span, tts: &[TokenTree]) -> Box<MacResult + 'cx> {
    let mut parser = cx.new_parser_from_tts(tts);
    let expr = parse_json(cx, &mut parser);
    if &parser.token != &Token::Eof {
        cx.span_fatal(parser.span, "expected end of `json!` macro invocation");
    }
    MacEager::expr(expr)
}

fn parse_json(cx: &ExtCtxt, parser: &mut Parser) -> P<Expr> {
    use syntax::ext::build::AstBuilder;
    use syntax::parse::token::{DelimToken, IdentStyle};

    macro_rules! comma_sep {
        () =>  {
            ::syntax::parse::common::SeqSep {
                sep: Some(Token::Comma),
                trailing_sep_allowed: true // we could be JSON pedants...
            }
        }
    }

    let orig_span = parser.span;

    match &parser.token {
        &Token::OpenDelim(DelimToken::Bracket) => {
            let _ = parser.bump();
            let r_bracket = Token::CloseDelim(DelimToken::Bracket);
            let exprs = parser.parse_seq_to_end(&r_bracket,
                                                comma_sep!(),
                                                |p| Ok(parse_json(cx, p)))
                .ok()
                .unwrap();
            let exprs = cx.expr_vec(orig_span, exprs);
            quote_expr!(cx, {
                use ::std::boxed::Box;
                let xs: Box<[_]> = Box::new($exprs);
                serde_json::Value::Array(xs.into_vec())
            })
        }
        &Token::OpenDelim(DelimToken::Brace) => {
            let _ = parser.bump();
            let r_brace = Token::CloseDelim(DelimToken::Brace);
            let kvs = parser.parse_seq_to_end(&r_brace, comma_sep!(), |p| {
                let (istr, _) = p.parse_str().ok().unwrap();
                let s = &*istr;
                let _ = p.expect(&Token::Colon);
                let key = quote_expr!(cx, {
                    use ::std::borrow::ToOwned;
                    $s.to_owned()
                });
                Ok((key, parse_json(cx, p)))
            })
                .ok()
                .unwrap();
            let mut insertions = vec![];
            // Can't use `quote_stmt!()` and interpolate a vector of
            // statements, seemingly.  Should consider filing a bug
            // upstream.
            for &(ref key, ref value) in kvs.iter() {
                insertions.push(quote_expr!(cx, {
                    _ob.insert($key, $value);
                }));
            }
            let expr = quote_expr!(cx, {
                let mut _ob = ::std::collections::BTreeMap::new();
                $insertions;
                ::serde_json::Value::Object(_ob)
            });
            expr
        }
        &Token::OpenDelim(DelimToken::Paren) => {
            let expr = parser.parse_expr().unwrap();
            quote_expr!(cx, {{
                ::serde_json::to_value(&$expr)
            }})
        }
        &Token::Ident(id, IdentStyle::Plain) if id.name.as_str() == "null" => {
            let _ = parser.bump();
            quote_expr!(cx, {
                ::serde_json::Value::Null
            })
        }
        _ => {
            // TODO: investigate can_begin_expr (maybe eliminate need for parens)?
            let expr = parser.parse_pat_literal_maybe_minus().ok().unwrap();
            quote_expr!(cx, {{
                ::serde_json::to_value(&$expr)
            }})
        }
    }
}
<|endoftext|>


<commit_before>use crate::utils::{contains_name, higher, iter_input_pats, snippet, span_lint_and_then};
use rustc_hir::intravisit::FnKind;
use rustc_hir::{
    Block, Body, Expr, ExprKind, FnDecl, Guard, HirId, Local, MutTy, Pat, PatKind, Path, QPath, StmtKind, Ty, TyKind,
    UnOp,
};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;
use rustc_span::symbol::Symbol;

declare_clippy_lint! {
    /// **What it does:** Checks for bindings that shadow other bindings already in
    /// scope, while just changing reference level or mutability.
    ///
    /// **Why is this bad?** Not much, in fact it's a very common pattern in Rust
    /// code. Still, some may opt to avoid it in their code base, they can set this
    /// lint to `Warn`.
    ///
    /// **Known problems:** This lint, as the other shadowing related lints,
    /// currently only catches very simple patterns.
    ///
    /// **Example:**
    /// ```rust
    /// # let x = 1;
    ///
    /// // Bad
    /// let x = &x;
    ///
    /// // Good
    /// let y = &x; // use different variable name
    /// ```
    pub SHADOW_SAME,
    restriction,
    "rebinding a name to itself, e.g., `let mut x = &mut x`"
}

declare_clippy_lint! {
    /// **What it does:** Checks for bindings that shadow other bindings already in
    /// scope, while reusing the original value.
    ///
    /// **Why is this bad?** Not too much, in fact it's a common pattern in Rust
    /// code. Still, some argue that name shadowing like this hurts readability,
    /// because a value may be bound to different things depending on position in
    /// the code.
    ///
    /// **Known problems:** This lint, as the other shadowing related lints,
    /// currently only catches very simple patterns.
    ///
    /// **Example:**
    /// ```rust
    /// let x = 2;
    /// let x = x + 1;
    /// ```
    /// use different variable name:
    /// ```rust
    /// let x = 2;
    /// let y = x + 1;
    /// ```
    pub SHADOW_REUSE,
    restriction,
    "rebinding a name to an expression that re-uses the original value, e.g., `let x = x + 1`"
}

declare_clippy_lint! {
    /// **What it does:** Checks for bindings that shadow other bindings already in
    /// scope, either without a initialization or with one that does not even use
    /// the original value.
    ///
    /// **Why is this bad?** Name shadowing can hurt readability, especially in
    /// large code bases, because it is easy to lose track of the active binding at
    /// any place in the code. This can be alleviated by either giving more specific
    /// names to bindings or introducing more scopes to contain the bindings.
    ///
    /// **Known problems:** This lint, as the other shadowing related lints,
    /// currently only catches very simple patterns.
    ///
    /// **Example:**
    /// ```rust
    /// # let y = 1;
    /// # let z = 2;
    /// let x = y;
    ///
    /// // Bad
    /// let x = z; // shadows the earlier binding
    ///
    /// // Good
    /// let w = z; // use different variable name
    /// ```
    pub SHADOW_UNRELATED,
    pedantic,
    "rebinding a name without even using the original value"
}

declare_lint_pass!(Shadow => [SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED]);

impl<'tcx> LateLintPass<'tcx> for Shadow {
    fn check_fn(
        &mut self,
        cx: &LateContext<'tcx>,
        _: FnKind<'tcx>,
        decl: &'tcx FnDecl<'_>,
        body: &'tcx Body<'_>,
        _: Span,
        _: HirId,
    ) {
        if in_external_macro(cx.sess(), body.value.span) {
            return;
        }
        check_fn(cx, decl, body);
    }
}

fn check_fn<'tcx>(cx: &LateContext<'tcx>, decl: &'tcx FnDecl<'_>, body: &'tcx Body<'_>) {
    let mut bindings = Vec::with_capacity(decl.inputs.len());
    for arg in iter_input_pats(decl, body) {
        if let PatKind::Binding(.., ident, _) = arg.pat.kind {
            bindings.push((ident.name, ident.span))
        }
    }
    check_expr(cx, &body.value, &mut bindings);
}

fn check_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'_>, bindings: &mut Vec<(Symbol, Span)>) {
    let len = bindings.len();
    for stmt in block.stmts {
        match stmt.kind {
            StmtKind::Local(ref local) => check_local(cx, local, bindings),
            StmtKind::Expr(ref e) | StmtKind::Semi(ref e) => check_expr(cx, e, bindings),
            StmtKind::Item(..) => {},
        }
    }
    if let Some(ref o) = block.expr {
        check_expr(cx, o, bindings);
    }
    bindings.truncate(len);
}

fn check_local<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>, bindings: &mut Vec<(Symbol, Span)>) {
    if in_external_macro(cx.sess(), local.span) {
        return;
    }
    if higher::is_from_for_desugar(local) {
        return;
    }
    let Local {
        ref pat,
        ref ty,
        ref init,
        span,
        ..
    } = *local;
    if let Some(ref t) = *ty {
        check_ty(cx, t, bindings)
    }
    if let Some(ref o) = *init {
        check_expr(cx, o, bindings);
        check_pat(cx, pat, Some(o), span, bindings);
    } else {
        check_pat(cx, pat, None, span, bindings);
    }
}

fn is_binding(cx: &LateContext<'_>, pat_id: HirId) -> bool {
    let var_ty = cx.typeck_results().node_type_opt(pat_id);
    var_ty.map_or(false, |var_ty| !matches!(var_ty.kind(), ty::Adt(..)))
}

fn check_pat<'tcx>(
    cx: &LateContext<'tcx>,
    pat: &'tcx Pat<'_>,
    init: Option<&'tcx Expr<'_>>,
    span: Span,
    bindings: &mut Vec<(Symbol, Span)>,
) {
    // TODO: match more stuff / destructuring
    match pat.kind {
        PatKind::Binding(.., ident, ref inner) => {
            let name = ident.name;
            if is_binding(cx, pat.hir_id) {
                let mut new_binding = true;
                for tup in bindings.iter_mut() {
                    if tup.0 == name {
                        lint_shadow(cx, name, span, pat.span, init, tup.1);
                        tup.1 = ident.span;
                        new_binding = false;
                        break;
                    }
                }
                if new_binding {
                    bindings.push((name, ident.span));
                }
            }
            if let Some(ref p) = *inner {
                check_pat(cx, p, init, span, bindings);
            }
        },
        PatKind::Struct(_, pfields, _) => {
            if let Some(init_struct) = init {
                if let ExprKind::Struct(_, ref efields, _) = init_struct.kind {
                    for field in pfields {
                        let name = field.ident.name;
                        let efield = efields
                            .iter()
                            .find_map(|f| if f.ident.name == name { Some(&*f.expr) } else { None });
                        check_pat(cx, &field.pat, efield, span, bindings);
                    }
                } else {
                    for field in pfields {
                        check_pat(cx, &field.pat, init, span, bindings);
                    }
                }
            } else {
                for field in pfields {
                    check_pat(cx, &field.pat, None, span, bindings);
                }
            }
        },
        PatKind::Tuple(inner, _) => {
            if let Some(init_tup) = init {
                if let ExprKind::Tup(ref tup) = init_tup.kind {
                    for (i, p) in inner.iter().enumerate() {
                        check_pat(cx, p, Some(&tup[i]), p.span, bindings);
                    }
                } else {
                    for p in inner {
                        check_pat(cx, p, init, span, bindings);
                    }
                }
            } else {
                for p in inner {
                    check_pat(cx, p, None, span, bindings);
                }
            }
        },
        PatKind::Box(ref inner) => {
            if let Some(initp) = init {
                if let ExprKind::Box(ref inner_init) = initp.kind {
                    check_pat(cx, inner, Some(&**inner_init), span, bindings);
                } else {
                    check_pat(cx, inner, init, span, bindings);
                }
            } else {
                check_pat(cx, inner, init, span, bindings);
            }
        },
        PatKind::Ref(ref inner, _) => check_pat(cx, inner, init, span, bindings),
        // PatVec(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>),
        _ => (),
    }
}

fn lint_shadow<'tcx>(
    cx: &LateContext<'tcx>,
    name: Symbol,
    span: Span,
    pattern_span: Span,
    init: Option<&'tcx Expr<'_>>,
    prev_span: Span,
) {
    if let Some(expr) = init {
        if is_self_shadow(name, expr) {
            span_lint_and_then(
                cx,
                SHADOW_SAME,
                span,
                &format!(
                    "`{}` is shadowed by itself in `{}`",
                    snippet(cx, pattern_span, "_"),
                    snippet(cx, expr.span, "..")
                ),
                |diag| {
                    diag.span_note(prev_span, "previous binding is here");
                },
            );
        } else if contains_name(name, expr) {
            span_lint_and_then(
                cx,
                SHADOW_REUSE,
                pattern_span,
                &format!(
                    "`{}` is shadowed by `{}` which reuses the original value",
                    snippet(cx, pattern_span, "_"),
                    snippet(cx, expr.span, "..")
                ),
                |diag| {
                    diag.span_note(expr.span, "initialization happens here");
                    diag.span_note(prev_span, "previous binding is here");
                },
            );
        } else {
            span_lint_and_then(
                cx,
                SHADOW_UNRELATED,
                pattern_span,
                &format!("`{}` is being shadowed", snippet(cx, pattern_span, "_")),
                |diag| {
                    diag.span_note(expr.span, "initialization happens here");
                    diag.span_note(prev_span, "previous binding is here");
                },
            );
        }
    } else {
        span_lint_and_then(
            cx,
            SHADOW_UNRELATED,
            span,
            &format!("`{}` shadows a previous declaration", snippet(cx, pattern_span, "_")),
            |diag| {
                diag.span_note(prev_span, "previous binding is here");
            },
        );
    }
}

fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut Vec<(Symbol, Span)>) {
    if in_external_macro(cx.sess(), expr.span) {
        return;
    }
    match expr.kind {
        ExprKind::Unary(_, ref e)
        | ExprKind::Field(ref e, _)
        | ExprKind::AddrOf(_, _, ref e)
        | ExprKind::Box(ref e) => check_expr(cx, e, bindings),
        ExprKind::Block(ref block, _) | ExprKind::Loop(ref block, _, _) => check_block(cx, block, bindings),
        // ExprKind::Call
        // ExprKind::MethodCall
        ExprKind::Array(v) | ExprKind::Tup(v) => {
            for e in v {
                check_expr(cx, e, bindings)
            }
        },
        ExprKind::Match(ref init, arms, _) => {
            check_expr(cx, init, bindings);
            let len = bindings.len();
            for arm in arms {
                check_pat(cx, &arm.pat, Some(&**init), arm.pat.span, bindings);
                // This is ugly, but needed to get the right type
                if let Some(ref guard) = arm.guard {
                    match guard {
                        Guard::If(if_expr) => check_expr(cx, if_expr, bindings),
                    }
                }
                check_expr(cx, &arm.body, bindings);
                bindings.truncate(len);
            }
        },
        _ => (),
    }
}

fn check_ty<'tcx>(cx: &LateContext<'tcx>, ty: &'tcx Ty<'_>, bindings: &mut Vec<(Symbol, Span)>) {
    match ty.kind {
        TyKind::Slice(ref sty) => check_ty(cx, sty, bindings),
        TyKind::Array(ref fty, ref anon_const) => {
            check_ty(cx, fty, bindings);
            check_expr(cx, &cx.tcx.hir().body(anon_const.body).value, bindings);
        },
        TyKind::Ptr(MutTy { ty: ref mty, .. }) | TyKind::Rptr(_, MutTy { ty: ref mty, .. }) => {
            check_ty(cx, mty, bindings)
        },
        TyKind::Tup(tup) => {
            for t in tup {
                check_ty(cx, t, bindings)
            }
        },
        TyKind::Typeof(ref anon_const) => check_expr(cx, &cx.tcx.hir().body(anon_const.body).value, bindings),
        _ => (),
    }
}

fn is_self_shadow(name: Symbol, expr: &Expr<'_>) -> bool {
    match expr.kind {
        ExprKind::Box(ref inner) | ExprKind::AddrOf(_, _, ref inner) => is_self_shadow(name, inner),
        ExprKind::Block(ref block, _) => {
            block.stmts.is_empty() && block.expr.as_ref().map_or(false, |e| is_self_shadow(name, e))
        },
        ExprKind::Unary(op, ref inner) => (UnOp::UnDeref == op) && is_self_shadow(name, inner),
        ExprKind::Path(QPath::Resolved(_, ref path)) => path_eq_name(name, path),
        _ => false,
    }
}

fn path_eq_name(name: Symbol, path: &Path<'_>) -> bool {
    !path.is_global() && path.segments.len() == 1 && path.segments[0].ident.as_str() == name.as_str()
}
<commit_msg>Auto merge of #6045 - giraffate:remove_extra_blank_line, r=flip1995<commit_after>use crate::utils::{contains_name, higher, iter_input_pats, snippet, span_lint_and_then};
use rustc_hir::intravisit::FnKind;
use rustc_hir::{
    Block, Body, Expr, ExprKind, FnDecl, Guard, HirId, Local, MutTy, Pat, PatKind, Path, QPath, StmtKind, Ty, TyKind,
    UnOp,
};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;
use rustc_span::symbol::Symbol;

declare_clippy_lint! {
    /// **What it does:** Checks for bindings that shadow other bindings already in
    /// scope, while just changing reference level or mutability.
    ///
    /// **Why is this bad?** Not much, in fact it's a very common pattern in Rust
    /// code. Still, some may opt to avoid it in their code base, they can set this
    /// lint to `Warn`.
    ///
    /// **Known problems:** This lint, as the other shadowing related lints,
    /// currently only catches very simple patterns.
    ///
    /// **Example:**
    /// ```rust
    /// # let x = 1;
    /// // Bad
    /// let x = &x;
    ///
    /// // Good
    /// let y = &x; // use different variable name
    /// ```
    pub SHADOW_SAME,
    restriction,
    "rebinding a name to itself, e.g., `let mut x = &mut x`"
}

declare_clippy_lint! {
    /// **What it does:** Checks for bindings that shadow other bindings already in
    /// scope, while reusing the original value.
    ///
    /// **Why is this bad?** Not too much, in fact it's a common pattern in Rust
    /// code. Still, some argue that name shadowing like this hurts readability,
    /// because a value may be bound to different things depending on position in
    /// the code.
    ///
    /// **Known problems:** This lint, as the other shadowing related lints,
    /// currently only catches very simple patterns.
    ///
    /// **Example:**
    /// ```rust
    /// let x = 2;
    /// let x = x + 1;
    /// ```
    /// use different variable name:
    /// ```rust
    /// let x = 2;
    /// let y = x + 1;
    /// ```
    pub SHADOW_REUSE,
    restriction,
    "rebinding a name to an expression that re-uses the original value, e.g., `let x = x + 1`"
}

declare_clippy_lint! {
    /// **What it does:** Checks for bindings that shadow other bindings already in
    /// scope, either without a initialization or with one that does not even use
    /// the original value.
    ///
    /// **Why is this bad?** Name shadowing can hurt readability, especially in
    /// large code bases, because it is easy to lose track of the active binding at
    /// any place in the code. This can be alleviated by either giving more specific
    /// names to bindings or introducing more scopes to contain the bindings.
    ///
    /// **Known problems:** This lint, as the other shadowing related lints,
    /// currently only catches very simple patterns.
    ///
    /// **Example:**
    /// ```rust
    /// # let y = 1;
    /// # let z = 2;
    /// let x = y;
    ///
    /// // Bad
    /// let x = z; // shadows the earlier binding
    ///
    /// // Good
    /// let w = z; // use different variable name
    /// ```
    pub SHADOW_UNRELATED,
    pedantic,
    "rebinding a name without even using the original value"
}

declare_lint_pass!(Shadow => [SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED]);

impl<'tcx> LateLintPass<'tcx> for Shadow {
    fn check_fn(
        &mut self,
        cx: &LateContext<'tcx>,
        _: FnKind<'tcx>,
        decl: &'tcx FnDecl<'_>,
        body: &'tcx Body<'_>,
        _: Span,
        _: HirId,
    ) {
        if in_external_macro(cx.sess(), body.value.span) {
            return;
        }
        check_fn(cx, decl, body);
    }
}

fn check_fn<'tcx>(cx: &LateContext<'tcx>, decl: &'tcx FnDecl<'_>, body: &'tcx Body<'_>) {
    let mut bindings = Vec::with_capacity(decl.inputs.len());
    for arg in iter_input_pats(decl, body) {
        if let PatKind::Binding(.., ident, _) = arg.pat.kind {
            bindings.push((ident.name, ident.span))
        }
    }
    check_expr(cx, &body.value, &mut bindings);
}

fn check_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'_>, bindings: &mut Vec<(Symbol, Span)>) {
    let len = bindings.len();
    for stmt in block.stmts {
        match stmt.kind {
            StmtKind::Local(ref local) => check_local(cx, local, bindings),
            StmtKind::Expr(ref e) | StmtKind::Semi(ref e) => check_expr(cx, e, bindings),
            StmtKind::Item(..) => {},
        }
    }
    if let Some(ref o) = block.expr {
        check_expr(cx, o, bindings);
    }
    bindings.truncate(len);
}

fn check_local<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>, bindings: &mut Vec<(Symbol, Span)>) {
    if in_external_macro(cx.sess(), local.span) {
        return;
    }
    if higher::is_from_for_desugar(local) {
        return;
    }
    let Local {
        ref pat,
        ref ty,
        ref init,
        span,
        ..
    } = *local;
    if let Some(ref t) = *ty {
        check_ty(cx, t, bindings)
    }
    if let Some(ref o) = *init {
        check_expr(cx, o, bindings);
        check_pat(cx, pat, Some(o), span, bindings);
    } else {
        check_pat(cx, pat, None, span, bindings);
    }
}

fn is_binding(cx: &LateContext<'_>, pat_id: HirId) -> bool {
    let var_ty = cx.typeck_results().node_type_opt(pat_id);
    var_ty.map_or(false, |var_ty| !matches!(var_ty.kind(), ty::Adt(..)))
}

fn check_pat<'tcx>(
    cx: &LateContext<'tcx>,
    pat: &'tcx Pat<'_>,
    init: Option<&'tcx Expr<'_>>,
    span: Span,
    bindings: &mut Vec<(Symbol, Span)>,
) {
    // TODO: match more stuff / destructuring
    match pat.kind {
        PatKind::Binding(.., ident, ref inner) => {
            let name = ident.name;
            if is_binding(cx, pat.hir_id) {
                let mut new_binding = true;
                for tup in bindings.iter_mut() {
                    if tup.0 == name {
                        lint_shadow(cx, name, span, pat.span, init, tup.1);
                        tup.1 = ident.span;
                        new_binding = false;
                        break;
                    }
                }
                if new_binding {
                    bindings.push((name, ident.span));
                }
            }
            if let Some(ref p) = *inner {
                check_pat(cx, p, init, span, bindings);
            }
        },
        PatKind::Struct(_, pfields, _) => {
            if let Some(init_struct) = init {
                if let ExprKind::Struct(_, ref efields, _) = init_struct.kind {
                    for field in pfields {
                        let name = field.ident.name;
                        let efield = efields
                            .iter()
                            .find_map(|f| if f.ident.name == name { Some(&*f.expr) } else { None });
                        check_pat(cx, &field.pat, efield, span, bindings);
                    }
                } else {
                    for field in pfields {
                        check_pat(cx, &field.pat, init, span, bindings);
                    }
                }
            } else {
                for field in pfields {
                    check_pat(cx, &field.pat, None, span, bindings);
                }
            }
        },
        PatKind::Tuple(inner, _) => {
            if let Some(init_tup) = init {
                if let ExprKind::Tup(ref tup) = init_tup.kind {
                    for (i, p) in inner.iter().enumerate() {
                        check_pat(cx, p, Some(&tup[i]), p.span, bindings);
                    }
                } else {
                    for p in inner {
                        check_pat(cx, p, init, span, bindings);
                    }
                }
            } else {
                for p in inner {
                    check_pat(cx, p, None, span, bindings);
                }
            }
        },
        PatKind::Box(ref inner) => {
            if let Some(initp) = init {
                if let ExprKind::Box(ref inner_init) = initp.kind {
                    check_pat(cx, inner, Some(&**inner_init), span, bindings);
                } else {
                    check_pat(cx, inner, init, span, bindings);
                }
            } else {
                check_pat(cx, inner, init, span, bindings);
            }
        },
        PatKind::Ref(ref inner, _) => check_pat(cx, inner, init, span, bindings),
        // PatVec(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>),
        _ => (),
    }
}

fn lint_shadow<'tcx>(
    cx: &LateContext<'tcx>,
    name: Symbol,
    span: Span,
    pattern_span: Span,
    init: Option<&'tcx Expr<'_>>,
    prev_span: Span,
) {
    if let Some(expr) = init {
        if is_self_shadow(name, expr) {
            span_lint_and_then(
                cx,
                SHADOW_SAME,
                span,
                &format!(
                    "`{}` is shadowed by itself in `{}`",
                    snippet(cx, pattern_span, "_"),
                    snippet(cx, expr.span, "..")
                ),
                |diag| {
                    diag.span_note(prev_span, "previous binding is here");
                },
            );
        } else if contains_name(name, expr) {
            span_lint_and_then(
                cx,
                SHADOW_REUSE,
                pattern_span,
                &format!(
                    "`{}` is shadowed by `{}` which reuses the original value",
                    snippet(cx, pattern_span, "_"),
                    snippet(cx, expr.span, "..")
                ),
                |diag| {
                    diag.span_note(expr.span, "initialization happens here");
                    diag.span_note(prev_span, "previous binding is here");
                },
            );
        } else {
            span_lint_and_then(
                cx,
                SHADOW_UNRELATED,
                pattern_span,
                &format!("`{}` is being shadowed", snippet(cx, pattern_span, "_")),
                |diag| {
                    diag.span_note(expr.span, "initialization happens here");
                    diag.span_note(prev_span, "previous binding is here");
                },
            );
        }
    } else {
        span_lint_and_then(
            cx,
            SHADOW_UNRELATED,
            span,
            &format!("`{}` shadows a previous declaration", snippet(cx, pattern_span, "_")),
            |diag| {
                diag.span_note(prev_span, "previous binding is here");
            },
        );
    }
}

fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut Vec<(Symbol, Span)>) {
    if in_external_macro(cx.sess(), expr.span) {
        return;
    }
    match expr.kind {
        ExprKind::Unary(_, ref e)
        | ExprKind::Field(ref e, _)
        | ExprKind::AddrOf(_, _, ref e)
        | ExprKind::Box(ref e) => check_expr(cx, e, bindings),
        ExprKind::Block(ref block, _) | ExprKind::Loop(ref block, _, _) => check_block(cx, block, bindings),
        // ExprKind::Call
        // ExprKind::MethodCall
        ExprKind::Array(v) | ExprKind::Tup(v) => {
            for e in v {
                check_expr(cx, e, bindings)
            }
        },
        ExprKind::Match(ref init, arms, _) => {
            check_expr(cx, init, bindings);
            let len = bindings.len();
            for arm in arms {
                check_pat(cx, &arm.pat, Some(&**init), arm.pat.span, bindings);
                // This is ugly, but needed to get the right type
                if let Some(ref guard) = arm.guard {
                    match guard {
                        Guard::If(if_expr) => check_expr(cx, if_expr, bindings),
                    }
                }
                check_expr(cx, &arm.body, bindings);
                bindings.truncate(len);
            }
        },
        _ => (),
    }
}

fn check_ty<'tcx>(cx: &LateContext<'tcx>, ty: &'tcx Ty<'_>, bindings: &mut Vec<(Symbol, Span)>) {
    match ty.kind {
        TyKind::Slice(ref sty) => check_ty(cx, sty, bindings),
        TyKind::Array(ref fty, ref anon_const) => {
            check_ty(cx, fty, bindings);
            check_expr(cx, &cx.tcx.hir().body(anon_const.body).value, bindings);
        },
        TyKind::Ptr(MutTy { ty: ref mty, .. }) | TyKind::Rptr(_, MutTy { ty: ref mty, .. }) => {
            check_ty(cx, mty, bindings)
        },
        TyKind::Tup(tup) => {
            for t in tup {
                check_ty(cx, t, bindings)
            }
        },
        TyKind::Typeof(ref anon_const) => check_expr(cx, &cx.tcx.hir().body(anon_const.body).value, bindings),
        _ => (),
    }
}

fn is_self_shadow(name: Symbol, expr: &Expr<'_>) -> bool {
    match expr.kind {
        ExprKind::Box(ref inner) | ExprKind::AddrOf(_, _, ref inner) => is_self_shadow(name, inner),
        ExprKind::Block(ref block, _) => {
            block.stmts.is_empty() && block.expr.as_ref().map_or(false, |e| is_self_shadow(name, e))
        },
        ExprKind::Unary(op, ref inner) => (UnOp::UnDeref == op) && is_self_shadow(name, inner),
        ExprKind::Path(QPath::Resolved(_, ref path)) => path_eq_name(name, path),
        _ => false,
    }
}

fn path_eq_name(name: Symbol, path: &Path<'_>) -> bool {
    !path.is_global() && path.segments.len() == 1 && path.segments[0].ident.as_str() == name.as_str()
}
<|endoftext|>


<commit_before>use htslib;
use std::ffi::c_str_to_bytes;
use std::slice::from_raw_parts;
use std::ffi::CString;
use std::mem::copy_lifetime;

#[derive(Debug)]
pub enum Aux<'a> {
    Integer(i32),
    String(&'a [u8]),
    Float(f32),
    Char(u8),
}

impl<'a> Aux<'a> {
    pub fn string(&self) -> &'a [u8] {
        match *self {
            Aux::String(x) => x,
            _ => panic!("not a string"),
        }
    }

    pub fn float(&self) -> f32 {
        match *self {
            Aux::Float(x) => x,
            _ => panic!("not a float"),
        }
    }

    pub fn integer(&self) -> i32 {
        match *self {
            Aux::Integer(x) => x,
            _ => panic!("not an integer"),
        }
    }

    pub fn char(&self) -> u8 {
        match *self {
            Aux::Char(x) => x,
            _ => panic!("not a character"),
        }
    }
}

pub struct Record<'a> {
    b: &'a htslib::bam1_t,
    data: &'a [u8],
}

impl<'a> Record<'a>{
    pub fn new(b: &'a htslib::bam1_t) -> Record {
        Record { b: b, data: unsafe { from_raw_parts((*b).data, b.l_data as usize) } }
    }

    fn qname_len(&self) -> usize {
        self.b.core.l_qname as usize
    }

    pub fn qname(&self) -> &[u8] {
        self.data[0..self.qname_len()].as_slice()
    }

    fn cigar_len(&self) -> usize {
        self.b.core.n_cigar as usize
    }

    pub fn bam_get_cigar(&self) -> &[u32] {
        let x = self.b.core.l_qname as usize;
        unsafe { from_raw_parts(self.data[self.qname_len()..].as_ptr() as *const u32, self.cigar_len()) }
    }

    fn seq_len(&self) -> usize {
        self.b.core.l_qseq as usize
    }

    pub fn seq(&self) -> &[u8] {
        self.data[self.qname_len() + self.cigar_len()*4..][0..self.seq_len()].as_slice()
    }

    pub fn qual(&self) -> &[u8] {
        self.data[self.qname_len() + self.cigar_len()*4 + (self.seq_len()+1)/2..][0..self.seq_len()].as_slice()
    }

    pub fn aux(&self, name: &[u8]) -> Result<Aux, &str> {
        let aux = unsafe { htslib::bam_aux_get(self.b, name.as_ptr() as *mut i8 ) };
        unsafe { println!("{}", *aux); }

        unsafe {
            match *aux {
                b'c'|b'C'|b's'|b'S'|b'i'|b'I' => Ok(Aux::Integer(htslib::bam_aux2i(aux))),
                b'f'|b'd' => Ok(Aux::Float(*(aux.offset(1) as *const f32))),
                b'A' => Ok(Aux::Char(*(aux.offset(1) as *const u8))),
                b'Z' => {
                    let f = (aux.offset(1) as *const i8);
                    let x = c_str_to_bytes(&f);
                    Ok(Aux::String(copy_lifetime(self, x)))
                },
                _ => Err("unexpected aux type"),
            }
        }
    }
}
<commit_msg>replaced own aux functions by htslib functions<commit_after>use htslib;
use std::ffi::c_str_to_bytes;
use std::slice::from_raw_parts;
use std::ffi::CString;
use std::mem::copy_lifetime;

#[derive(Debug)]
pub enum Aux<'a> {
    Integer(i32),
    String(&'a [u8]),
    Float(f64),
    Char(u8),
}

impl<'a> Aux<'a> {
    pub fn string(&self) -> &'a [u8] {
        match *self {
            Aux::String(x) => x,
            _ => panic!("not a string"),
        }
    }

    pub fn float(&self) -> f64 {
        match *self {
            Aux::Float(x) => x,
            _ => panic!("not a float"),
        }
    }

    pub fn integer(&self) -> i32 {
        match *self {
            Aux::Integer(x) => x,
            _ => panic!("not an integer"),
        }
    }

    pub fn char(&self) -> u8 {
        match *self {
            Aux::Char(x) => x,
            _ => panic!("not a character"),
        }
    }
}

pub struct Record<'a> {
    b: &'a htslib::bam1_t,
    data: &'a [u8],
}

impl<'a> Record<'a>{
    pub fn new(b: &'a htslib::bam1_t) -> Record {
        Record { b: b, data: unsafe { from_raw_parts((*b).data, b.l_data as usize) } }
    }

    fn qname_len(&self) -> usize {
        self.b.core.l_qname as usize
    }

    pub fn qname(&self) -> &[u8] {
        self.data[0..self.qname_len()].as_slice()
    }

    fn cigar_len(&self) -> usize {
        self.b.core.n_cigar as usize
    }

    pub fn bam_get_cigar(&self) -> &[u32] {
        let x = self.b.core.l_qname as usize;
        unsafe { from_raw_parts(self.data[self.qname_len()..].as_ptr() as *const u32, self.cigar_len()) }
    }

    fn seq_len(&self) -> usize {
        self.b.core.l_qseq as usize
    }

    pub fn seq(&self) -> &[u8] {
        self.data[self.qname_len() + self.cigar_len()*4..][..self.seq_len()].as_slice()
    }

    pub fn qual(&self) -> &[u8] {
        self.data[self.qname_len() + self.cigar_len()*4 + (self.seq_len()+1)/2..][..self.seq_len()].as_slice()
    }

    pub fn aux(&self, name: &[u8]) -> Result<Aux, &str> {
        let aux = unsafe { htslib::bam_aux_get(self.b, name.as_ptr() as *mut i8 ) };
        unsafe { println!("{}", *aux); }

        unsafe {
            match *aux {
                b'c'|b'C'|b's'|b'S'|b'i'|b'I' => Ok(Aux::Integer(htslib::bam_aux2i(aux))),
                b'f'|b'd' => Ok(Aux::Float(htslib::bam_aux2f(aux))),
                b'A' => Ok(Aux::Char(htslib::bam_aux2A(aux) as u8)),
                b'Z'|b'H' => {
                    let f = (aux.offset(1) as *const i8);
                    let x = c_str_to_bytes(&f);
                    Ok(Aux::String(copy_lifetime(self, x)))
                },
                _ => Err("unexpected aux type"),
            }
        }
    }
}
<|endoftext|>


<commit_before>use rocket::request::Form;
use rocket::request::State;
use rocket_contrib::Json;
use maud::Markup;
use kit::form::to_form;
use app::{Model, ModelResult, AuthInfo};

#[derive(FromForm, Default, Serialize)]
pub struct EditPost {
    post_id: i32,
    title: String,
    body: String,
}

#[get("/edit_post")]
pub fn get() -> Markup {
    to_form(&EditPost::default())
}

#[post("/edit_post", data = "<data>")]
pub fn post(auth: AuthInfo, model: State<Model>, data: Form<EditPost>) -> Json<ModelResult<()>> {
    let form = data.get();
    Json(model.edit_post(&auth, form.post_id, &form.title, &form.body))
}<commit_msg>test json form handler<commit_after>use rocket::request::Form;
use rocket::request::State;
use rocket_contrib::Json;
use maud::Markup;
use kit::form::to_form;
use app::{Model, ModelResult, AuthInfo};

#[derive(FromForm, Default, Serialize, Deserialize)]
pub struct EditPost {
    post_id: i32,
    title: String,
    body: String,
}

#[get("/edit_post")]
pub fn get() -> Markup {
    to_form(&EditPost::default())
}

#[post("/edit_post", data = "<data>")]
pub fn post(auth: AuthInfo, model: State<Model>, data: Form<EditPost>) -> Json<ModelResult<()>> {
    let form = data.get();
    Json(model.edit_post(&auth, form.post_id, &form.title, &form.body))
}

#[post("/edit_post", data = "<data>")]
pub fn post_json(auth: AuthInfo, model: State<Model>, data: Json<EditPost>) -> Json<ModelResult<()>> {
    let form = data.into_inner();
    Json(model.edit_post(&auth, form.post_id, &form.title, &form.body))
}
<|endoftext|>


<commit_before>//!
//! The API for communicating with devices.
//!
//! This API is provided as Traits to be implemented:
//!
//! - by the low-level layers of the FoxBox, including the adapters;
//! - by test suites and tools that need to simulate connected devices.
//!
//! In turn, this API is used to implement:
//!
//! - the public-facing REST and WebSocket API;
//! - the rules API (ThinkerBell).
//!
//!

use devices::*;
use requests::*;
use values::Value;

/// An error produced by one of the APIs in this module.
pub enum Error {
    /// There is no such node connected to the Foxbox, even indirectly.
    NoSuchNode(NodeId),

    /// There is no such service connected to the Foxbox, even indirectly.
    NoSuchService(ServiceId),

    /// Attempting to set a value with the wrong type
    TypeError,
}

/// The public API.
///
/// This API is subdivided in traits purely for the sake of
/// namespacing.
pub trait API {
    /// The subset of the API dedicated to nodes.
    type NodeAPI: NodeAPI;
    fn get_node_api(&self) -> Self::NodeAPI;

    /// The subset of the API dedicated to services.
    type ServiceAPI: ServiceAPI;
    fn get_service_api(&self) -> Self::ServiceAPI;
}

/// Node-level API
pub trait NodeAPI {
    /// Get a list of nodes matching some conditions
    ///
    /// # REST API
    ///
    /// `GET /api/v1/node/list`
    fn get_list(&self, &NodeRequest) -> Vec<Node>;

    /// Add a tag to an existing node.
    ///
    /// Tags can be used to locate nodes.
    ///
    /// # REST API
    ///
    /// `PUT /api/v1/node/tag/$NodeId`
    fn put_tag(&self, &NodeId, String) -> Result<(), Error>;

    /// Add a tag to an existing node.
    ///
    /// Tags can be used to locate nodes.
    ///
    /// # REST API
    ///
    /// `DELETE /api/v1/node/tag/$NodeId`
    fn delete_tag(&self, &NodeId, String) -> Result<(), Error>;
}

/// Service-level API
pub trait ServiceAPI {
    /// A value that causes a disconnection once it is dropped.
    type Guard;

    /// Get a list of inputs matching some conditions
    ///
    /// # REST API
    ///
    /// `GET /api/v1/service/list`
    fn get_input_services(&self, &InputRequest) -> Vec<Service<Input>>;
    fn get_output_services(&self, &OutputRequest) -> Vec<Service<Output>>;

    /// Add a tag to an existing service.
    ///
    /// Tags can be used to locate service.
    ///
    /// # REST API
    ///
    /// `PUT /api/v1/service/tag/$ServiceId`
    fn put_tag(&self, &ServiceId, String) -> Result<(), Error>;

    /// Add a tag to an existing service.
    ///
    /// Tags can be used to locate services.
    ///
    /// # REST API
    ///
    /// `DELETE /api/v1/service/tag/$ServiceId`
    fn delete_tag(&self, &ServiceId, String) -> Result<(), Error>;

    /// Read one value from an input enpoint
    ///
    /// # REST API
    ///
    /// GET /api/v1/service/value/$ServiceId
    fn get_service_value(&self, &Service<Input>) -> Result<Value, Error>;

    /// Send one value to an output enpoint
    ///
    /// # REST API
    ///
    /// `PUT /api/v1/service/value/$ServiceId`
    fn put_service_value(&self, &Service<Output>, Value) -> Result<(), Error>;

    /// Watch for any change
    ///
    /// # WebSocket API
    ///
    /// `/api/v1/service/watch/$ServiceId`
    fn register_watch<F>(&self, &Service<Input>, &WatchOptions, cb: F)
                         -> Result<Self::Guard, Error>
        where F: Fn(Value) + Send;
}

/// Options for watching a service.
/// FIXME: Define.
pub struct WatchOptions;
<commit_msg>Initial definition of WatchOptions<commit_after>//!
//! The API for communicating with devices.
//!
//! This API is provided as Traits to be implemented:
//!
//! - by the low-level layers of the FoxBox, including the adapters;
//! - by test suites and tools that need to simulate connected devices.
//!
//! In turn, this API is used to implement:
//!
//! - the public-facing REST and WebSocket API;
//! - the rules API (ThinkerBell).
//!
//!

use devices::*;
use requests::*;
use values::Value;

/// An error produced by one of the APIs in this module.
pub enum Error {
    /// There is no such node connected to the Foxbox, even indirectly.
    NoSuchNode(NodeId),

    /// There is no such service connected to the Foxbox, even indirectly.
    NoSuchService(ServiceId),

    /// Attempting to set a value with the wrong type
    TypeError,
}

/// The public API.
///
/// This API is subdivided in traits purely for the sake of
/// namespacing.
pub trait API {
    /// The subset of the API dedicated to nodes.
    type NodeAPI: NodeAPI;
    fn get_node_api(&self) -> Self::NodeAPI;

    /// The subset of the API dedicated to services.
    type ServiceAPI: ServiceAPI;
    fn get_service_api(&self) -> Self::ServiceAPI;
}

/// Node-level API
pub trait NodeAPI {
    /// Get a list of nodes matching some conditions
    ///
    /// # REST API
    ///
    /// `GET /api/v1/node/list`
    fn get_list(&self, &NodeRequest) -> Vec<Node>;

    /// Add a tag to an existing node.
    ///
    /// Tags can be used to locate nodes.
    ///
    /// # REST API
    ///
    /// `PUT /api/v1/node/tag/$NodeId`
    fn put_tag(&self, &NodeId, String) -> Result<(), Error>;

    /// Add a tag to an existing node.
    ///
    /// Tags can be used to locate nodes.
    ///
    /// # REST API
    ///
    /// `DELETE /api/v1/node/tag/$NodeId`
    fn delete_tag(&self, &NodeId, String) -> Result<(), Error>;
}

/// Service-level API
pub trait ServiceAPI {
    /// A value that causes a disconnection once it is dropped.
    type Guard;

    /// Get a list of inputs matching some conditions
    ///
    /// # REST API
    ///
    /// `GET /api/v1/service/list`
    fn get_input_services(&self, &InputRequest) -> Vec<Service<Input>>;
    fn get_output_services(&self, &OutputRequest) -> Vec<Service<Output>>;

    /// Add a tag to an existing service.
    ///
    /// Tags can be used to locate service.
    ///
    /// # REST API
    ///
    /// `PUT /api/v1/service/tag/$ServiceId`
    fn put_tag(&self, &ServiceId, String) -> Result<(), Error>;

    /// Add a tag to an existing service.
    ///
    /// Tags can be used to locate services.
    ///
    /// # REST API
    ///
    /// `DELETE /api/v1/service/tag/$ServiceId`
    fn delete_tag(&self, &ServiceId, String) -> Result<(), Error>;

    /// Read one value from an input enpoint
    ///
    /// # REST API
    ///
    /// GET /api/v1/service/value/$ServiceId
    fn get_service_value(&self, &Service<Input>) -> Result<Value, Error>;

    /// Send one value to an output enpoint
    ///
    /// # REST API
    ///
    /// `PUT /api/v1/service/value/$ServiceId`
    fn put_service_value(&self, &Service<Output>, Value) -> Result<(), Error>;

    /// Watch for any change
    ///
    /// # WebSocket API
    ///
    /// `/api/v1/service/watch/$ServiceId`
    fn register_watch<F>(&self, &WatchOptions, cb: F)
                         -> Result<Self::Guard, Error>
        where F: Fn(Value) + Send;
}

/// Options for watching changes in one or more services.
pub struct WatchOptions {
    source: InputRequest,
}

impl WatchOptions {
    pub fn new() -> Self {
        WatchOptions {
            source: InputRequest::new(),
        }
    }

    pub fn and(self, other: Self) -> Self {
        WatchOptions {
            source: self.source.and(other.source),
            ..self
        }
    }
}
<|endoftext|>


<commit_before>// Hound -- A WAV encoding library in Rust
// Copyright (C) 2015 Ruud van Asseldonk
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 3 of the License only.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

//! Hound, a WAV encoding library.
//!
//! TODO: Add some examples here.

#![warn(missing_docs)]
#![allow(dead_code)] // TODO: Remove for v0.1
#![feature(convert, io)]

use std::fs;
use std::io;
use std::io::{Seek, Write};
use std::marker;
use std::path;

trait WriteExt: io::Write {
    fn write_le_u16(&mut self, x: u16) -> io::Result<()>;
    fn write_le_u32(&mut self, x: u32) -> io::Result<()>;
}

impl<W> WriteExt for W where W: io::Write {

    fn write_le_u16(&mut self, x: u16) -> io::Result<()> {
        let mut buf = [0u8; 2];
        buf[0] = (x & 0xff) as u8;
        buf[1] = (x >> 8) as u8;
        self.write_all(&buf)
    }

    fn write_le_u32(&mut self, x: u32) -> io::Result<()> {
        let mut buf = [0u8; 4];
        buf[0] = ((x >> 00) & 0xff) as u8;
        buf[1] = ((x >> 08) & 0xff) as u8;
        buf[2] = ((x >> 16) & 0xff) as u8;
        buf[3] = ((x >> 24) & 0xff) as u8;
        self.write_all(&buf)
    }
}

trait Sample {
    fn write<W: io::Write>(self, writer: &mut W) -> io::Result<()>;
}

impl Sample for u16 {
    fn write<W: io::Write>(self, writer: &mut W) -> io::Result<()> {
        writer.write_le_u16(self)
    }
}

pub struct WavSpec {
    n_channels: u16,
    sample_rate: u16,
    bits_per_sample: u16
}

struct WavWriter<W, S> {
    writer: W,
    wrote_header: bool,
    phantom_sample: marker::PhantomData<fn(S)>
}

impl<W, S> WavWriter<W, S>
where W: io::Write + io::Seek,
      S: Sample {

    /// Creates a writer that writes the WAVE format to the underlying writer.
    pub fn new(writer: W, spec: WavSpec) -> WavWriter<W, S> {
        unimplemented!();
    }

    /// Creates a writer that writes the WAVE format to a file.
    ///
    /// The file will be overwritten if it exists.
    pub fn create<P: AsRef<path::Path>>(filename: P, spec: WavSpec)
           -> io::Result<WavWriter<fs::File, S>> {
        let file = try!(fs::File::create(filename));
        Ok(WavWriter::new(file, spec))
    }

    /// Writes the RIFF WAVE header
    fn write_header(&mut self) -> io::Result<()> {
        let mut header = [0u8; 44];

        // Write the header in-memory first.
        {
            let mut buffer: io::Cursor<&mut [u8]> = io::Cursor::new(&mut header);
            try!(buffer.write_all("RIFF".as_bytes()));

            // Skip 4 bytes that will be filled with the file size afterwards.
            buffer.seek(io::SeekFrom::Current(4));

            try!(buffer.write_all("WAVE".as_bytes()));
            try!(buffer.write_all("fmt\0".as_bytes()));
            try!(buffer.write_le_u32(16)); // Size of the WAVE header
            try!(buffer.write_le_u16(1));  // PCM encoded audio
            try!(buffer.write_le_u16(2)); // TODO: num channels
            try!(buffer.write_le_u32(44100)); // TODO: sample rate
            try!(buffer.write_le_u32(0)); // TODO: sr * bps * n_chan / 8
            try!(buffer.write_le_u16(16)); // TODO: block align
            try!(buffer.write_le_u32(16)); // TODO: bits per sample
        }

        // Then write the entire header at once.
        try!(self.writer.write_all(&header));

        Ok(())
    }

    pub fn write_sample(sample: S) -> io::Result<()> {
        // TODO
        Ok(())
    }
}
<commit_msg>try to design convenient api<commit_after>// Hound -- A WAV encoding library in Rust
// Copyright (C) 2015 Ruud van Asseldonk
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 3 of the License only.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

//! Hound, a WAV encoding library.
//!
//! TODO: Add some examples here.

#![warn(missing_docs)]
#![allow(dead_code)] // TODO: Remove for v0.1
#![feature(convert, io)]

use std::fs;
use std::io;
use std::io::{Seek, Write};
use std::path;

trait WriteExt: io::Write {
    fn write_le_u16(&mut self, x: u16) -> io::Result<()>;
    fn write_le_u32(&mut self, x: u32) -> io::Result<()>;
}

impl<W> WriteExt for W where W: io::Write {

    fn write_le_u16(&mut self, x: u16) -> io::Result<()> {
        let mut buf = [0u8; 2];
        buf[0] = (x & 0xff) as u8;
        buf[1] = (x >> 8) as u8;
        self.write_all(&buf)
    }

    fn write_le_u32(&mut self, x: u32) -> io::Result<()> {
        let mut buf = [0u8; 4];
        buf[0] = ((x >> 00) & 0xff) as u8;
        buf[1] = ((x >> 08) & 0xff) as u8;
        buf[2] = ((x >> 16) & 0xff) as u8;
        buf[3] = ((x >> 24) & 0xff) as u8;
        self.write_all(&buf)
    }
}

trait Sample {
    fn write<W: io::Write>(self, writer: &mut W, bits: u32) -> io::Result<()>;
}

impl Sample for u16 {
    fn write<W: io::Write>(self, writer: &mut W, bits: u32) -> io::Result<()> {
        writer.write_le_u16(self)
        // TODO: take bits into account
    }
}

/// Specifies properties of the audio data.
pub struct WavSpec {
    /// The number of channels.
    channels: u16,

    /// The number of samples per second.
    ///
    /// A common value is 44100, this is 44.1 kHz which is used for CD audio.
    sample_rate: u32,

    /// The number of bits per sample.
    ///
    /// A common value is 16 bits per sample, which is used for CD audio.
    bits_per_sample: u32
}

struct WavWriter<W> where W: io::Write {
    /// Specifies properties of the audio data.
    spec: WavSpec,

    /// Whether the header has been written already.
    wrote_header: bool,

    /// The writer that will be written to.
    writer: io::BufWriter<W>,

    /// The number of bytes written to the data section.
    ///
    /// This is an `u32` because WAVE cannot accomodate more data.
    data_bytes_written: u32
}

impl<W> WavWriter<W> where W: io::Write + io::Seek {
    /// Creates a writer that writes the WAVE format to the underlying writer.
    pub fn new(writer: W, spec: WavSpec) -> WavWriter<W> {
        unimplemented!();
    }

    /// Creates a writer that writes the WAVE format to a file.
    ///
    /// The file will be overwritten if it exists.
    pub fn create<P: AsRef<path::Path>>(filename: P, spec: WavSpec)
           -> io::Result<WavWriter<fs::File>> {
        let file = try!(fs::File::create(filename));
        Ok(WavWriter::new(file, spec))
    }

    /// Writes the RIFF WAVE header
    fn write_header(&mut self) -> io::Result<()> {
        let mut header = [0u8; 44];
        let spec = &self.spec;

        // Write the header in-memory first.
        {
            let mut buffer: io::Cursor<&mut [u8]> = io::Cursor::new(&mut header);
            try!(buffer.write_all("RIFF".as_bytes()));

            // Skip 4 bytes that will be filled with the file size afterwards.
            buffer.seek(io::SeekFrom::Current(4));

            try!(buffer.write_all("WAVE".as_bytes()));
            try!(buffer.write_all("fmt\0".as_bytes()));
            try!(buffer.write_le_u32(16)); // Size of the WAVE header
            try!(buffer.write_le_u16(1));  // PCM encoded audio
            try!(buffer.write_le_u16(spec.channels));
            try!(buffer.write_le_u32(spec.sample_rate));
            let bytes_per_sec = spec.sample_rate
                              * spec.bits_per_sample
                              * spec.channels as u32 / 8;
            try!(buffer.write_le_u32(bytes_per_sec));
            try!(buffer.write_le_u16(16)); // TODO: block align
            try!(buffer.write_le_u32(spec.bits_per_sample));

            // TODO: data section header
        }

        // Then write the entire header at once.
        try!(self.writer.write_all(&header));

        Ok(())
    }

    pub fn write_sample<S: Sample>(&mut self, sample: S) -> io::Result<()> {
        if !self.wrote_header {
            try!(self.write_header());
        }

        try!(sample.write(&mut self.writer, self.spec.bits_per_sample));
        self.data_bytes_written += self.spec.bits_per_sample / 8;
        Ok(())
    }
}
<|endoftext|>