<commit_before>use glutin::{ElementState, MouseButton, MouseScrollDelta};
pub use glutin::VirtualKeyCode as Key;
use mint;

use std::collections::HashSet;
use std::time;

mod timer;
pub mod axis;

pub use self::axis::{AXIS_DOWN_UP, AXIS_LEFT_RIGHT};

pub use self::timer::Timer;

const PIXELS_PER_LINE: f32 = 38.0;

pub type TimerDuration = f32;

struct State {
    time_moment: time::Instant,
    is_focused: bool,
    keys_pressed: HashSet<Key>,
    mouse_pressed: HashSet<MouseButton>,
    mouse_pos: mint::Point2<f32>,
    mouse_pos_ndc: mint::Point2<f32>,
}

struct Diff {
    time_delta: TimerDuration,
    keys_hit: Vec<Key>,
    mouse_moves: Vec<mint::Vector2<f32>>,
    mouse_moves_ndc: Vec<mint::Vector2<f32>>,
    axes_raw: Vec<(u8, f32)>,
    mouse_hit: Vec<MouseButton>,
    mouse_wheel: Vec<f32>,
}

/// Controls user and system input from keyboard, mouse and system clock.
pub struct Input {
    state: State,
    delta: Diff,
}

impl Input {
    pub(crate) fn new() -> Self {
        let state = State {
            time_moment: time::Instant::now(),
            is_focused: true,
            keys_pressed: HashSet::new(),
            mouse_pressed: HashSet::new(),
            mouse_pos: [0.0; 2].into(),
            mouse_pos_ndc: [0.0; 2].into(),
        };
        let delta = Diff {
            time_delta: 0.0,
            keys_hit: Vec::new(),
            mouse_moves: Vec::new(),
            mouse_moves_ndc: Vec::new(),
            axes_raw: Vec::new(),
            mouse_hit: Vec::new(),
            mouse_wheel: Vec::new(),
        };
        Input { state, delta }
    }

    /// Manually reset current `Input` state.
    ///
    /// Usually there is no need in using this method, because [`Window`](struct.Window.html)
    /// resets `Input` on each [`update`](struct.Window.html#method.update) method by default.
    ///
    /// It will discard all mouse or raw axes movements and also all keyboard hits.
    /// Moreover, delta time will be recalculated.
    pub fn reset(&mut self) {
        let now = time::Instant::now();
        let dt = now - self.state.time_moment;
        self.state.time_moment = now;
        self.delta.time_delta = dt.as_secs() as TimerDuration + 1e-9 * dt.subsec_nanos() as TimerDuration;
        self.delta.keys_hit.clear();
        self.delta.mouse_moves.clear();
        self.delta.mouse_moves_ndc.clear();
        self.delta.axes_raw.clear();
        self.delta.mouse_hit.clear();
        self.delta.mouse_wheel.clear();
    }

    /// Create new timer.
    pub fn time(&self) -> Timer {
        Timer {
            start: self.state.time_moment,
        }
    }

    /// Get current delta time (time since previous frame) in seconds.
    pub fn delta_time(&self) -> TimerDuration {
        self.delta.time_delta
    }

    /// Get current mouse pointer position in pixels from top-left.
    pub fn mouse_pos(&self) -> mint::Point2<f32> {
        self.state.mouse_pos
    }

    /// Get current mouse pointer position in Normalized Display Coordinates.
    /// See [`map_to_ndc`](struct.Renderer.html#method.map_to_ndc).
    pub fn mouse_pos_ndc(&self) -> mint::Point2<f32> {
        self.state.mouse_pos_ndc
    }

    /// Get list of all mouse wheel movements since last frame.
    pub fn mouse_wheel_movements(&self) -> &[f32] {
        &self.delta.mouse_wheel[..]
    }

    /// Get summarized mouse wheel movement (the sum of all movements since last frame).
    pub fn mouse_wheel(&self) -> f32 {
        self.delta.mouse_wheel.iter().sum()
    }

    /// Get list of all mouse movements since last frame in pixels.
    pub fn mouse_movements(&self) -> &[mint::Vector2<f32>] {
        &self.delta.mouse_moves[..]
    }

    /// Get list of all mouse movements since last frame in NDC.
    pub fn mouse_movements_ndc(&self) -> &[mint::Vector2<f32>] {
        &self.delta.mouse_moves_ndc[..]
    }

    /// Get list of all raw inputs since last frame.
    pub fn axes_movements(&self) -> &[(u8, f32)] {
        &self.delta.axes_raw[..]
    }

    fn calculate_delta(moves: &[mint::Vector2<f32>]) -> mint::Vector2<f32> {
        use cgmath::Vector2;
        moves
            .iter()
            .cloned()
            .map(Vector2::from)
            .sum::<Vector2<f32>>()
            .into()
    }

    /// Get summarized mouse movements (the sum of all movements since last frame) in pixels.
    pub fn mouse_delta(&self) -> mint::Vector2<f32> {
        Input::calculate_delta(self.mouse_movements())
    }

    /// Get summarized mouse movements (the sum of all movements since last frame) in NDC.
    pub fn mouse_delta_ndc(&self) -> mint::Vector2<f32> {
        Input::calculate_delta(self.mouse_movements_ndc())
    }

    /// Get summarized raw input along `0` and `1` axes since last frame.
    /// It usually corresponds to mouse movements.
    pub fn mouse_delta_raw(&self) -> mint::Vector2<f32> {
        use cgmath::Vector2;
        self.delta
            .axes_raw
            .iter()
            .filter(|&&(axis, _)| axis == 0 || axis == 1)
            .map(|&(axis, value)| if axis == 0 {
                (value, 0.0)
            } else {
                (0.0, value)
            })
            .map(|t| Vector2 { x: t.0, y: t.1 })
            .sum::<Vector2<f32>>()
            .into()
    }

    /// Return whether [`Window`](struct.Window.html) is in focus or not.
    pub fn is_focused(&self) -> bool {
        self.state.is_focused
    }

    pub(crate) fn window_focus(
        &mut self,
        state: bool,
    ) {
        self.state.is_focused = state;
    }

    pub(crate) fn keyboard_input(
        &mut self,
        state: ElementState,
        key: Key,
    ) {
        match state {
            ElementState::Pressed => {
                self.state.keys_pressed.insert(key);
                self.delta.keys_hit.push(key);
            }
            ElementState::Released => {
                self.state.keys_pressed.remove(&key);
            }
        }
    }

    pub(crate) fn mouse_input(
        &mut self,
        state: ElementState,
        button: MouseButton,
    ) {
        match state {
            ElementState::Pressed => {
                self.state.mouse_pressed.insert(button);
                self.delta.mouse_hit.push(button);
            }
            ElementState::Released => {
                self.state.mouse_pressed.remove(&button);
            }
        }
    }

    pub(crate) fn mouse_moved(
        &mut self,
        pos: mint::Point2<f32>,
        pos_ndc: mint::Point2<f32>,
    ) {
        use cgmath::Point2;
        self.delta
            .mouse_moves
            .push((Point2::from(pos) - Point2::from(self.state.mouse_pos)).into());
        self.delta
            .mouse_moves_ndc
            .push((Point2::from(pos_ndc) - Point2::from(self.state.mouse_pos_ndc)).into());
        self.state.mouse_pos = pos;
        self.state.mouse_pos_ndc = pos_ndc;
    }

    pub(crate) fn axis_moved_raw(
        &mut self,
        axis: u8,
        value: f32,
    ) {
        self.delta.axes_raw.push((axis, value));
    }

    pub(crate) fn mouse_wheel_input(
        &mut self,
        delta: MouseScrollDelta,
    ) {
        self.delta.mouse_wheel.push(match delta {
            MouseScrollDelta::LineDelta(_, y) => y * PIXELS_PER_LINE,
            MouseScrollDelta::PixelDelta(_, y) => y,
        });
    }

    /// Returns `true` there is any input info from [`Button`](struct.Button.html),
    /// [`axis::Key`](struct.Key.html) or [`axis::Raw`](struct.Raw.html). Otherwise returns `false`.
    pub fn hit<H: Hit>(
        &self,
        hit: H,
    ) -> bool {
        hit.hit(self)
    }

    /// Returns `Option<delta>` value for specified axis, where `delta` is either `i8` for
    /// [`axis::Key`](struct.Key.html) or `f32` for [`axis::Raw`](struct.Raw.html).
    ///
    /// Delta value for [`axis::Key`](struct.Key.html) represents the amount of `positive` hits minus
    /// amount of `negative` hits.
    ///
    /// Delta value for [`axis::Raw`](struct.Raw.html) represents the sum of all
    /// [raw movements](struct.Input.html#method.axes_movements) along specific axis.
    pub fn delta<D: Delta>(
        &self,
        delta: D,
    ) -> <D as Delta>::Output {
        delta.delta(self)
    }

    /// The shortcut for [delta](struct.Input.html#method.delta) *
    /// [delta_time](struct.Input.html#method.delta_time).
    pub fn timed<D: Delta>(
        &self,
        delta: D,
    ) -> Option<TimerDuration> {
        delta.timed(self)
    }

    /// Returns the amount of:
    ///
    /// - Hits for [`Button`](enum.Button.html) as `u8`.
    ///
    /// - Hits for [`axis::Key`](struct.Key.html) as `(u8, u8)` where first number is for `positive`
    /// direction and the second one is for `negative`.
    pub fn hit_count<C: HitCount>(
        &self,
        hit_count: C,
    ) -> <C as HitCount>::Output {
        hit_count.hit_count(self)
    }
}

/// Keyboard or mouse button.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Button {
    /// Keyboard button.
    Key(Key),
    /// Mouse button.
    Mouse(MouseButton),
}

/// Trait for [`Buttons`](enum.Button.html).
pub trait Hit {
    /// See [`Input::hit`](struct.Input.html#method.hit).
    fn hit(
        &self,
        input: &Input,
    ) -> bool;
}

impl Hit for Button {
    fn hit(
        &self,
        input: &Input,
    ) -> bool {
        match *self {
            Button::Key(button) => input.state.keys_pressed.contains(&button),
            Button::Mouse(button) => input.state.mouse_pressed.contains(&button),
        }
    }
}

impl Hit for axis::Key {
    fn hit(
        &self,
        input: &Input,
    ) -> bool {
        input
            .delta
            .keys_hit
            .iter()
            .filter(|&&k| k == self.pos || k == self.neg)
            .count() > 0
    }
}

impl Hit for axis::Raw {
    fn hit(
        &self,
        input: &Input,
    ) -> bool {
        input
            .delta
            .axes_raw
            .iter()
            .filter(|&&(id, _)| id == self.id)
            .count() > 0
    }
}

/// Trait for [`Buttons`](enum.Button.html) and [`axis::Key`](struct.Key.html).
pub trait HitCount {
    /// Output type.
    type Output;
    /// See [`Input::hit_count`](struct.Input.html#method.hit_count).
    fn hit_count(
        &self,
        input: &Input,
    ) -> Self::Output;
}

impl HitCount for Button {
    type Output = u8;
    fn hit_count(
        &self,
        input: &Input,
    ) -> Self::Output {
        use std::u8::MAX;
        match *self {
            Button::Key(button) => input
                .delta
                .keys_hit
                .iter()
                .filter(|&&key| key == button)
                .take(MAX as usize)
                .count() as Self::Output,
            Button::Mouse(button) => input
                .delta
                .mouse_hit
                .iter()
                .filter(|&&key| key == button)
                .take(MAX as usize)
                .count() as Self::Output,
        }
    }
}

impl HitCount for axis::Key {
    type Output = (u8, u8);

    fn hit_count(
        &self,
        input: &Input,
    ) -> Self::Output {
        use std::u8::MAX;
        let pos = input
            .delta
            .keys_hit
            .iter()
            .filter(|&&k| k == self.pos)
            .take(MAX as usize)
            .count() as u8;
        let neg = input
            .delta
            .keys_hit
            .iter()
            .filter(|&&k| k == self.neg)
            .take(MAX as usize)
            .count() as u8;
        (pos, neg)
    }
}

/// Trait for [`axis::Key`](struct.Key.html) and [`axis::Raw`](struct.Raw.html).
pub trait Delta {
    /// Output type.
    type Output;

    /// See [`Input::delta`](struct.Input.html#method.delta).
    fn delta(
        &self,
        input: &Input,
    ) -> Self::Output;
    /// See [`Input::timed`](struct.Input.html#method.timed).
    fn timed(
        &self,
        input: &Input,
    ) -> Option<TimerDuration>;
}

impl Delta for axis::Key {
    type Output = Option<i8>;

    fn delta(
        &self,
        input: &Input,
    ) -> Self::Output {
        let (pos, neg) = self.hit_count(input);
        if pos + neg == 0 {
            None
        } else {
            Some(pos as i8 - neg as i8)
        }
    }

    fn timed(
        &self,
        input: &Input,
    ) -> Option<TimerDuration> {
        self.delta(input)
            .map(|v| v as TimerDuration * input.delta_time())
    }
}

impl Delta for axis::Raw {
    type Output = Option<f32>;

    fn delta(
        &self,
        input: &Input,
    ) -> Self::Output {
        let moves = input
            .delta
            .axes_raw
            .iter()
            .filter(|&&(id, _)| id == self.id)
            .map(|&(_, value)| value)
            .collect::<Vec<_>>();
        if moves.len() == 0 {
            None
        } else {
            Some(moves.iter().sum::<f32>())
        }
    }

    fn timed(
        &self,
        input: &Input,
    ) -> Option<TimerDuration> {
        self.delta(input)
            .map(|v| v as TimerDuration * input.delta_time())
    }
}

/// `Escape` keyboard button.
pub const KEY_ESCAPE: Button = Button::Key(Key::Escape);
/// `Space` keyboard button.
pub const KEY_SPACE: Button = Button::Key(Key::Space);
/// Left mouse button.
pub const MOUSE_LEFT: Button = Button::Mouse(MouseButton::Left);
/// Right mouse button.
pub const MOUSE_RIGHT: Button = Button::Mouse(MouseButton::Right);
<commit_msg>Add Input::keys_hit<commit_after>use glutin::{ElementState, MouseButton, MouseScrollDelta};
pub use glutin::VirtualKeyCode as Key;
use mint;

use std::collections::HashSet;
use std::time;

mod timer;
pub mod axis;

pub use self::axis::{AXIS_DOWN_UP, AXIS_LEFT_RIGHT};

pub use self::timer::Timer;

const PIXELS_PER_LINE: f32 = 38.0;

pub type TimerDuration = f32;

struct State {
    time_moment: time::Instant,
    is_focused: bool,
    keys_pressed: HashSet<Key>,
    mouse_pressed: HashSet<MouseButton>,
    mouse_pos: mint::Point2<f32>,
    mouse_pos_ndc: mint::Point2<f32>,
}

struct Diff {
    time_delta: TimerDuration,
    keys_hit: Vec<Key>,
    mouse_moves: Vec<mint::Vector2<f32>>,
    mouse_moves_ndc: Vec<mint::Vector2<f32>>,
    axes_raw: Vec<(u8, f32)>,
    mouse_hit: Vec<MouseButton>,
    mouse_wheel: Vec<f32>,
}

/// Controls user and system input from keyboard, mouse and system clock.
pub struct Input {
    state: State,
    delta: Diff,
}

impl Input {
    pub(crate) fn new() -> Self {
        let state = State {
            time_moment: time::Instant::now(),
            is_focused: true,
            keys_pressed: HashSet::new(),
            mouse_pressed: HashSet::new(),
            mouse_pos: [0.0; 2].into(),
            mouse_pos_ndc: [0.0; 2].into(),
        };
        let delta = Diff {
            time_delta: 0.0,
            keys_hit: Vec::new(),
            mouse_moves: Vec::new(),
            mouse_moves_ndc: Vec::new(),
            axes_raw: Vec::new(),
            mouse_hit: Vec::new(),
            mouse_wheel: Vec::new(),
        };
        Input { state, delta }
    }

    /// Manually reset current `Input` state.
    ///
    /// Usually there is no need in using this method, because [`Window`](struct.Window.html)
    /// resets `Input` on each [`update`](struct.Window.html#method.update) method by default.
    ///
    /// It will discard all mouse or raw axes movements and also all keyboard hits.
    /// Moreover, delta time will be recalculated.
    pub fn reset(&mut self) {
        let now = time::Instant::now();
        let dt = now - self.state.time_moment;
        self.state.time_moment = now;
        self.delta.time_delta = dt.as_secs() as TimerDuration + 1e-9 * dt.subsec_nanos() as TimerDuration;
        self.delta.keys_hit.clear();
        self.delta.mouse_moves.clear();
        self.delta.mouse_moves_ndc.clear();
        self.delta.axes_raw.clear();
        self.delta.mouse_hit.clear();
        self.delta.mouse_wheel.clear();
    }

    /// Create new timer.
    pub fn time(&self) -> Timer {
        Timer {
            start: self.state.time_moment,
        }
    }

    /// Get current delta time (time since previous frame) in seconds.
    pub fn delta_time(&self) -> TimerDuration {
        self.delta.time_delta
    }

    /// Get list of all keys hit since the last frame.
    pub fn keys_hit(&self) -> &[Key] {
        &self.delta.keys_hit
    }

    /// Get current mouse pointer position in pixels from top-left.
    pub fn mouse_pos(&self) -> mint::Point2<f32> {
        self.state.mouse_pos
    }

    /// Get current mouse pointer position in Normalized Display Coordinates.
    /// See [`map_to_ndc`](struct.Renderer.html#method.map_to_ndc).
    pub fn mouse_pos_ndc(&self) -> mint::Point2<f32> {
        self.state.mouse_pos_ndc
    }

    /// Get list of all mouse wheel movements since last frame.
    pub fn mouse_wheel_movements(&self) -> &[f32] {
        &self.delta.mouse_wheel[..]
    }

    /// Get summarized mouse wheel movement (the sum of all movements since last frame).
    pub fn mouse_wheel(&self) -> f32 {
        self.delta.mouse_wheel.iter().sum()
    }

    /// Get list of all mouse movements since last frame in pixels.
    pub fn mouse_movements(&self) -> &[mint::Vector2<f32>] {
        &self.delta.mouse_moves[..]
    }

    /// Get list of all mouse movements since last frame in NDC.
    pub fn mouse_movements_ndc(&self) -> &[mint::Vector2<f32>] {
        &self.delta.mouse_moves_ndc[..]
    }

    /// Get list of all raw inputs since last frame.
    pub fn axes_movements(&self) -> &[(u8, f32)] {
        &self.delta.axes_raw[..]
    }

    fn calculate_delta(moves: &[mint::Vector2<f32>]) -> mint::Vector2<f32> {
        use cgmath::Vector2;
        moves
            .iter()
            .cloned()
            .map(Vector2::from)
            .sum::<Vector2<f32>>()
            .into()
    }

    /// Get summarized mouse movements (the sum of all movements since last frame) in pixels.
    pub fn mouse_delta(&self) -> mint::Vector2<f32> {
        Input::calculate_delta(self.mouse_movements())
    }

    /// Get summarized mouse movements (the sum of all movements since last frame) in NDC.
    pub fn mouse_delta_ndc(&self) -> mint::Vector2<f32> {
        Input::calculate_delta(self.mouse_movements_ndc())
    }

    /// Get summarized raw input along `0` and `1` axes since last frame.
    /// It usually corresponds to mouse movements.
    pub fn mouse_delta_raw(&self) -> mint::Vector2<f32> {
        use cgmath::Vector2;
        self.delta
            .axes_raw
            .iter()
            .filter(|&&(axis, _)| axis == 0 || axis == 1)
            .map(|&(axis, value)| if axis == 0 {
                (value, 0.0)
            } else {
                (0.0, value)
            })
            .map(|t| Vector2 { x: t.0, y: t.1 })
            .sum::<Vector2<f32>>()
            .into()
    }

    /// Return whether [`Window`](struct.Window.html) is in focus or not.
    pub fn is_focused(&self) -> bool {
        self.state.is_focused
    }

    pub(crate) fn window_focus(
        &mut self,
        state: bool,
    ) {
        self.state.is_focused = state;
    }

    pub(crate) fn keyboard_input(
        &mut self,
        state: ElementState,
        key: Key,
    ) {
        match state {
            ElementState::Pressed => {
                self.state.keys_pressed.insert(key);
                self.delta.keys_hit.push(key);
            }
            ElementState::Released => {
                self.state.keys_pressed.remove(&key);
            }
        }
    }

    pub(crate) fn mouse_input(
        &mut self,
        state: ElementState,
        button: MouseButton,
    ) {
        match state {
            ElementState::Pressed => {
                self.state.mouse_pressed.insert(button);
                self.delta.mouse_hit.push(button);
            }
            ElementState::Released => {
                self.state.mouse_pressed.remove(&button);
            }
        }
    }

    pub(crate) fn mouse_moved(
        &mut self,
        pos: mint::Point2<f32>,
        pos_ndc: mint::Point2<f32>,
    ) {
        use cgmath::Point2;
        self.delta
            .mouse_moves
            .push((Point2::from(pos) - Point2::from(self.state.mouse_pos)).into());
        self.delta
            .mouse_moves_ndc
            .push((Point2::from(pos_ndc) - Point2::from(self.state.mouse_pos_ndc)).into());
        self.state.mouse_pos = pos;
        self.state.mouse_pos_ndc = pos_ndc;
    }

    pub(crate) fn axis_moved_raw(
        &mut self,
        axis: u8,
        value: f32,
    ) {
        self.delta.axes_raw.push((axis, value));
    }

    pub(crate) fn mouse_wheel_input(
        &mut self,
        delta: MouseScrollDelta,
    ) {
        self.delta.mouse_wheel.push(match delta {
            MouseScrollDelta::LineDelta(_, y) => y * PIXELS_PER_LINE,
            MouseScrollDelta::PixelDelta(_, y) => y,
        });
    }

    /// Returns `true` there is any input info from [`Button`](struct.Button.html),
    /// [`axis::Key`](struct.Key.html) or [`axis::Raw`](struct.Raw.html). Otherwise returns `false`.
    pub fn hit<H: Hit>(
        &self,
        hit: H,
    ) -> bool {
        hit.hit(self)
    }

    /// Returns `Option<delta>` value for specified axis, where `delta` is either `i8` for
    /// [`axis::Key`](struct.Key.html) or `f32` for [`axis::Raw`](struct.Raw.html).
    ///
    /// Delta value for [`axis::Key`](struct.Key.html) represents the amount of `positive` hits minus
    /// amount of `negative` hits.
    ///
    /// Delta value for [`axis::Raw`](struct.Raw.html) represents the sum of all
    /// [raw movements](struct.Input.html#method.axes_movements) along specific axis.
    pub fn delta<D: Delta>(
        &self,
        delta: D,
    ) -> <D as Delta>::Output {
        delta.delta(self)
    }

    /// The shortcut for [delta](struct.Input.html#method.delta) *
    /// [delta_time](struct.Input.html#method.delta_time).
    pub fn timed<D: Delta>(
        &self,
        delta: D,
    ) -> Option<TimerDuration> {
        delta.timed(self)
    }

    /// Returns the amount of:
    ///
    /// - Hits for [`Button`](enum.Button.html) as `u8`.
    ///
    /// - Hits for [`axis::Key`](struct.Key.html) as `(u8, u8)` where first number is for `positive`
    /// direction and the second one is for `negative`.
    pub fn hit_count<C: HitCount>(
        &self,
        hit_count: C,
    ) -> <C as HitCount>::Output {
        hit_count.hit_count(self)
    }
}

/// Keyboard or mouse button.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Button {
    /// Keyboard button.
    Key(Key),
    /// Mouse button.
    Mouse(MouseButton),
}

/// Trait for [`Buttons`](enum.Button.html).
pub trait Hit {
    /// See [`Input::hit`](struct.Input.html#method.hit).
    fn hit(
        &self,
        input: &Input,
    ) -> bool;
}

impl Hit for Button {
    fn hit(
        &self,
        input: &Input,
    ) -> bool {
        match *self {
            Button::Key(button) => input.state.keys_pressed.contains(&button),
            Button::Mouse(button) => input.state.mouse_pressed.contains(&button),
        }
    }
}

impl Hit for axis::Key {
    fn hit(
        &self,
        input: &Input,
    ) -> bool {
        input
            .delta
            .keys_hit
            .iter()
            .filter(|&&k| k == self.pos || k == self.neg)
            .count() > 0
    }
}

impl Hit for axis::Raw {
    fn hit(
        &self,
        input: &Input,
    ) -> bool {
        input
            .delta
            .axes_raw
            .iter()
            .filter(|&&(id, _)| id == self.id)
            .count() > 0
    }
}

/// Trait for [`Buttons`](enum.Button.html) and [`axis::Key`](struct.Key.html).
pub trait HitCount {
    /// Output type.
    type Output;
    /// See [`Input::hit_count`](struct.Input.html#method.hit_count).
    fn hit_count(
        &self,
        input: &Input,
    ) -> Self::Output;
}

impl HitCount for Button {
    type Output = u8;
    fn hit_count(
        &self,
        input: &Input,
    ) -> Self::Output {
        use std::u8::MAX;
        match *self {
            Button::Key(button) => input
                .delta
                .keys_hit
                .iter()
                .filter(|&&key| key == button)
                .take(MAX as usize)
                .count() as Self::Output,
            Button::Mouse(button) => input
                .delta
                .mouse_hit
                .iter()
                .filter(|&&key| key == button)
                .take(MAX as usize)
                .count() as Self::Output,
        }
    }
}

impl HitCount for axis::Key {
    type Output = (u8, u8);

    fn hit_count(
        &self,
        input: &Input,
    ) -> Self::Output {
        use std::u8::MAX;
        let pos = input
            .delta
            .keys_hit
            .iter()
            .filter(|&&k| k == self.pos)
            .take(MAX as usize)
            .count() as u8;
        let neg = input
            .delta
            .keys_hit
            .iter()
            .filter(|&&k| k == self.neg)
            .take(MAX as usize)
            .count() as u8;
        (pos, neg)
    }
}

/// Trait for [`axis::Key`](struct.Key.html) and [`axis::Raw`](struct.Raw.html).
pub trait Delta {
    /// Output type.
    type Output;

    /// See [`Input::delta`](struct.Input.html#method.delta).
    fn delta(
        &self,
        input: &Input,
    ) -> Self::Output;
    /// See [`Input::timed`](struct.Input.html#method.timed).
    fn timed(
        &self,
        input: &Input,
    ) -> Option<TimerDuration>;
}

impl Delta for axis::Key {
    type Output = Option<i8>;

    fn delta(
        &self,
        input: &Input,
    ) -> Self::Output {
        let (pos, neg) = self.hit_count(input);
        if pos + neg == 0 {
            None
        } else {
            Some(pos as i8 - neg as i8)
        }
    }

    fn timed(
        &self,
        input: &Input,
    ) -> Option<TimerDuration> {
        self.delta(input)
            .map(|v| v as TimerDuration * input.delta_time())
    }
}

impl Delta for axis::Raw {
    type Output = Option<f32>;

    fn delta(
        &self,
        input: &Input,
    ) -> Self::Output {
        let moves = input
            .delta
            .axes_raw
            .iter()
            .filter(|&&(id, _)| id == self.id)
            .map(|&(_, value)| value)
            .collect::<Vec<_>>();
        if moves.len() == 0 {
            None
        } else {
            Some(moves.iter().sum::<f32>())
        }
    }

    fn timed(
        &self,
        input: &Input,
    ) -> Option<TimerDuration> {
        self.delta(input)
            .map(|v| v as TimerDuration * input.delta_time())
    }
}

/// `Escape` keyboard button.
pub const KEY_ESCAPE: Button = Button::Key(Key::Escape);
/// `Space` keyboard button.
pub const KEY_SPACE: Button = Button::Key(Key::Space);
/// Left mouse button.
pub const MOUSE_LEFT: Button = Button::Mouse(MouseButton::Left);
/// Right mouse button.
pub const MOUSE_RIGHT: Button = Button::Mouse(MouseButton::Right);
<|endoftext|>


<commit_before>use inkwell::context::Context;
use inkwell::debug_info::{
    AsDIScope, DIFlags, DISubprogram, DWARFEmissionKind, DWARFSourceLanguage, DebugInfoBuilder,
};
use inkwell::module::FlagBehavior;

#[test]
fn test_smoke() {
    let context = Context::create();
    let module = context.create_module("bin");

    let debug_metadata_version = context.i32_type().const_int(3, false);
    module.add_basic_value_flag(
        "Debug Info Version",
        FlagBehavior::Warning,
        debug_metadata_version,
    );
    let builder = context.create_builder();
    let (dibuilder, compile_unit) = module.create_debug_info_builder(
        true,
        DWARFSourceLanguage::C,
        "source_file",
        ".",
        "my llvm compiler frontend",
        false,
        "",
        0,
        "",
        DWARFEmissionKind::Full,
        0,
        false,
        false,
    );

    let ditype = dibuilder
        .create_basic_type("type_name", 0_u64, 0x00, DIFlags::Public)
        .unwrap();
    let subroutine_type = dibuilder.create_subroutine_type(
        compile_unit.get_file(),
        Some(ditype.as_type()),
        &[],
        DIFlags::Public,
    );
    let func_scope: DISubprogram<'_> = dibuilder.create_function(
        compile_unit.as_debug_info_scope(),
        "main",
        None,
        compile_unit.get_file(),
        0,
        subroutine_type,
        true,
        true,
        0,
        DIFlags::Public,
        false,
    );

    let fn_type = context.i64_type().fn_type(&[], false);
    let fn_val = module.add_function("fn_name_str", fn_type, None);
    fn_val.set_subprogram(func_scope);

    let basic_block = context.append_basic_block(fn_val, "entry");
    builder.position_at_end(basic_block);
    builder.build_return(Some(&context.i64_type().const_zero()));

    let lexical_block = dibuilder.create_lexical_block(
        func_scope.as_debug_info_scope(),
        compile_unit.get_file(),
        0,
        0,
    );

    let loc =
        dibuilder.create_debug_location(&context, 0, 0, lexical_block.as_debug_info_scope(), None);
    builder.set_current_debug_location(&context, loc);

    dibuilder.finalize();

    assert!(module.verify().is_ok());
}

#[test]
fn test_struct_with_placeholders() {
    let context = Context::create();
    let module = context.create_module("");

    let builder = context.create_builder();
    let (dibuilder, compile_unit) = module.create_debug_info_builder(
        true,
        DWARFSourceLanguage::C,
        "source_file",
        ".",
        "my llvm compiler frontend",
        false,
        "",
        0,
        "",
        DWARFEmissionKind::Full,
        0,
        false,
        false,
    );

    // Some byte aligned integer types.
    let i32ty = dibuilder
        .create_basic_type("i32", 32, 0x07, DIFlags::Public)
        .unwrap();
    let i64ty = dibuilder
        .create_basic_type("i64", 64, 0x07, DIFlags::Public)
        .unwrap();
    let f32ty = dibuilder
        .create_basic_type("f32", 32, 0x04, DIFlags::Public)
        .unwrap();
    let f64ty = dibuilder
        .create_basic_type("f64", 64, 0x04, DIFlags::Public)
        .unwrap();

    let member_sizes = vec![32, 64, 32, 64];
    let member_types = vec![i32ty, i64ty, f32ty, f64ty];
    let member_placeholders = member_types
        .iter()
        .map(|ty| unsafe { dibuilder.create_placeholder_derived_type(&context) })
        .collect::<Vec<_>>();
    let member_placeholders_as_ditype = member_types
        .iter()
        .map(|ty| ty.as_type())
        .collect::<Vec<_>>();

    let structty = dibuilder.create_struct_type(
        compile_unit.get_file().as_debug_info_scope(),
        "",
        compile_unit.get_file(),
        0,
        192,
        8,
        DIFlags::Public,
        None,
        member_placeholders_as_ditype.as_slice(),
        0,
        None,
        "",
    );

    let mut offset = 0;
    for ((placeholder, ty), size) in member_placeholders
        .iter()
        .zip(member_types.iter())
        .zip(member_sizes.iter())
    {
        let member = dibuilder.create_member_type(
            structty.as_debug_info_scope(),
            "",
            compile_unit.get_file(),
            0,
            *size,
            8,
            offset,
            DIFlags::Public,
            ty.as_type(),
        );
        unsafe {
            dibuilder.replace_placeholder_derived_type(*placeholder, member);
        }
        offset += size;
    }

    dibuilder.finalize();

    assert!(module.verify().is_ok());
}

#[test]
fn test_no_explicit_finalize() {
    let context = Context::create();
    let module = context.create_module("");

    let (dibuilder, _compile_unit) = module.create_debug_info_builder(
        true,
        DWARFSourceLanguage::C,
        "source_file",
        ".",
        "my llvm compiler frontend",
        false,
        "",
        0,
        "",
        DWARFEmissionKind::Full,
        0,
        false,
        false,
    );

    drop(dibuilder);

    assert!(module.verify().is_ok());
}

#[test]
#[llvm_versions(8.0..=9.0)]
fn test_replacing_placeholder_with_placeholder() {
    let context = Context::create();
    let module = context.create_module("");

    let (dibuilder, compile_unit) = module.create_debug_info_builder(
        true,
        DWARFSourceLanguage::C,
        "source_file",
        ".",
        "my llvm compiler frontend",
        false,
        "",
        0,
        "",
        DWARFEmissionKind::Full,
        0,
        false,
        false,
    );

    let i32ty = dibuilder
        .create_basic_type("i32", 32, 0x07, DIFlags::Public)
        .unwrap();
    let typedefty = dibuilder.create_typedef(
        i32ty.as_type(),
        "",
        compile_unit.get_file(),
        0,
        compile_unit.get_file().as_debug_info_scope(),
    );

    unsafe {
        let ph1 = dibuilder.create_placeholder_derived_type(&context);
        let ph2 = dibuilder.create_placeholder_derived_type(&context);

        dibuilder.replace_placeholder_derived_type(ph2, ph1);
        dibuilder.replace_placeholder_derived_type(ph1, typedefty);
    }
}

#[test]
#[llvm_versions(10.0..=latest)]
fn test_replacing_placeholder_with_placeholder() {
    let context = Context::create();
    let module = context.create_module("");

    let (dibuilder, compile_unit) = module.create_debug_info_builder(
        true,
        DWARFSourceLanguage::C,
        "source_file",
        ".",
        "my llvm compiler frontend",
        false,
        "",
        0,
        "",
        DWARFEmissionKind::Full,
        0,
        false,
        false,
    );

    let i32ty = dibuilder
        .create_basic_type("i32", 32, 0x07, DIFlags::Public)
        .unwrap();
    let typedefty = dibuilder.create_typedef(
        i32ty.as_type(),
        "",
        compile_unit.get_file(),
        0,
        compile_unit.get_file().as_debug_info_scope(),
        32,
    );

    unsafe {
        let ph1 = dibuilder.create_placeholder_derived_type(&context);
        let ph2 = dibuilder.create_placeholder_derived_type(&context);

        dibuilder.replace_placeholder_derived_type(ph2, ph1);
        dibuilder.replace_placeholder_derived_type(ph1, typedefty);
    }
}

#[test]
#[llvm_versions(7.0)]
fn test_anonymous_basic_type() {
    let context = Context::create();
    let module = context.create_module("bin");

    let builder = context.create_builder();
    let (dibuilder, _compile_unit) = module.create_debug_info_builder(
        true,
        DWARFSourceLanguage::C,
        "source_file",
        ".",
        "my llvm compiler frontend",
        false,
        "",
        0,
        "",
        DWARFEmissionKind::Full,
        0,
        false,
        false,
    );

    assert_eq!(
        dibuilder.create_basic_type("", 0_u64, 0x00),
        Err("basic types must have names")
    );
}

#[test]
#[llvm_versions(8.0..=latest)]
fn test_anonymous_basic_type() {
    let context = Context::create();
    let module = context.create_module("bin");

    let (dibuilder, _compile_unit) = module.create_debug_info_builder(
        true,
        DWARFSourceLanguage::C,
        "source_file",
        ".",
        "my llvm compiler frontend",
        false,
        "",
        0,
        "",
        DWARFEmissionKind::Full,
        0,
        false,
        false,
    );

    assert_eq!(
        dibuilder.create_basic_type("", 0_u64, 0x00, DIFlags::Zero),
        Err("basic types must have names")
    );
}
<commit_msg>Remove dead IRBuilders in test.<commit_after>use inkwell::context::Context;
use inkwell::debug_info::{
    AsDIScope, DIFlags, DISubprogram, DWARFEmissionKind, DWARFSourceLanguage, DebugInfoBuilder,
};
use inkwell::module::FlagBehavior;

#[test]
fn test_smoke() {
    let context = Context::create();
    let module = context.create_module("bin");

    let debug_metadata_version = context.i32_type().const_int(3, false);
    module.add_basic_value_flag(
        "Debug Info Version",
        FlagBehavior::Warning,
        debug_metadata_version,
    );
    let builder = context.create_builder();
    let (dibuilder, compile_unit) = module.create_debug_info_builder(
        true,
        DWARFSourceLanguage::C,
        "source_file",
        ".",
        "my llvm compiler frontend",
        false,
        "",
        0,
        "",
        DWARFEmissionKind::Full,
        0,
        false,
        false,
    );

    let ditype = dibuilder
        .create_basic_type("type_name", 0_u64, 0x00, DIFlags::Public)
        .unwrap();
    let subroutine_type = dibuilder.create_subroutine_type(
        compile_unit.get_file(),
        Some(ditype.as_type()),
        &[],
        DIFlags::Public,
    );
    let func_scope: DISubprogram<'_> = dibuilder.create_function(
        compile_unit.as_debug_info_scope(),
        "main",
        None,
        compile_unit.get_file(),
        0,
        subroutine_type,
        true,
        true,
        0,
        DIFlags::Public,
        false,
    );

    let fn_type = context.i64_type().fn_type(&[], false);
    let fn_val = module.add_function("fn_name_str", fn_type, None);
    fn_val.set_subprogram(func_scope);

    let basic_block = context.append_basic_block(fn_val, "entry");
    builder.position_at_end(basic_block);
    builder.build_return(Some(&context.i64_type().const_zero()));

    let lexical_block = dibuilder.create_lexical_block(
        func_scope.as_debug_info_scope(),
        compile_unit.get_file(),
        0,
        0,
    );

    let loc =
        dibuilder.create_debug_location(&context, 0, 0, lexical_block.as_debug_info_scope(), None);
    builder.set_current_debug_location(&context, loc);

    dibuilder.finalize();

    assert!(module.verify().is_ok());
}

#[test]
fn test_struct_with_placeholders() {
    let context = Context::create();
    let module = context.create_module("");

    let (dibuilder, compile_unit) = module.create_debug_info_builder(
        true,
        DWARFSourceLanguage::C,
        "source_file",
        ".",
        "my llvm compiler frontend",
        false,
        "",
        0,
        "",
        DWARFEmissionKind::Full,
        0,
        false,
        false,
    );

    // Some byte aligned integer types.
    let i32ty = dibuilder
        .create_basic_type("i32", 32, 0x07, DIFlags::Public)
        .unwrap();
    let i64ty = dibuilder
        .create_basic_type("i64", 64, 0x07, DIFlags::Public)
        .unwrap();
    let f32ty = dibuilder
        .create_basic_type("f32", 32, 0x04, DIFlags::Public)
        .unwrap();
    let f64ty = dibuilder
        .create_basic_type("f64", 64, 0x04, DIFlags::Public)
        .unwrap();

    let member_sizes = vec![32, 64, 32, 64];
    let member_types = vec![i32ty, i64ty, f32ty, f64ty];
    let member_placeholders = member_types
        .iter()
        .map(|ty| unsafe { dibuilder.create_placeholder_derived_type(&context) })
        .collect::<Vec<_>>();
    let member_placeholders_as_ditype = member_types
        .iter()
        .map(|ty| ty.as_type())
        .collect::<Vec<_>>();

    let structty = dibuilder.create_struct_type(
        compile_unit.get_file().as_debug_info_scope(),
        "",
        compile_unit.get_file(),
        0,
        192,
        8,
        DIFlags::Public,
        None,
        member_placeholders_as_ditype.as_slice(),
        0,
        None,
        "",
    );

    let mut offset = 0;
    for ((placeholder, ty), size) in member_placeholders
        .iter()
        .zip(member_types.iter())
        .zip(member_sizes.iter())
    {
        let member = dibuilder.create_member_type(
            structty.as_debug_info_scope(),
            "",
            compile_unit.get_file(),
            0,
            *size,
            8,
            offset,
            DIFlags::Public,
            ty.as_type(),
        );
        unsafe {
            dibuilder.replace_placeholder_derived_type(*placeholder, member);
        }
        offset += size;
    }

    dibuilder.finalize();

    assert!(module.verify().is_ok());
}

#[test]
fn test_no_explicit_finalize() {
    let context = Context::create();
    let module = context.create_module("");

    let (dibuilder, _compile_unit) = module.create_debug_info_builder(
        true,
        DWARFSourceLanguage::C,
        "source_file",
        ".",
        "my llvm compiler frontend",
        false,
        "",
        0,
        "",
        DWARFEmissionKind::Full,
        0,
        false,
        false,
    );

    drop(dibuilder);

    assert!(module.verify().is_ok());
}

#[test]
#[llvm_versions(8.0..=9.0)]
fn test_replacing_placeholder_with_placeholder() {
    let context = Context::create();
    let module = context.create_module("");

    let (dibuilder, compile_unit) = module.create_debug_info_builder(
        true,
        DWARFSourceLanguage::C,
        "source_file",
        ".",
        "my llvm compiler frontend",
        false,
        "",
        0,
        "",
        DWARFEmissionKind::Full,
        0,
        false,
        false,
    );

    let i32ty = dibuilder
        .create_basic_type("i32", 32, 0x07, DIFlags::Public)
        .unwrap();
    let typedefty = dibuilder.create_typedef(
        i32ty.as_type(),
        "",
        compile_unit.get_file(),
        0,
        compile_unit.get_file().as_debug_info_scope(),
    );

    unsafe {
        let ph1 = dibuilder.create_placeholder_derived_type(&context);
        let ph2 = dibuilder.create_placeholder_derived_type(&context);

        dibuilder.replace_placeholder_derived_type(ph2, ph1);
        dibuilder.replace_placeholder_derived_type(ph1, typedefty);
    }
}

#[test]
#[llvm_versions(10.0..=latest)]
fn test_replacing_placeholder_with_placeholder() {
    let context = Context::create();
    let module = context.create_module("");

    let (dibuilder, compile_unit) = module.create_debug_info_builder(
        true,
        DWARFSourceLanguage::C,
        "source_file",
        ".",
        "my llvm compiler frontend",
        false,
        "",
        0,
        "",
        DWARFEmissionKind::Full,
        0,
        false,
        false,
    );

    let i32ty = dibuilder
        .create_basic_type("i32", 32, 0x07, DIFlags::Public)
        .unwrap();
    let typedefty = dibuilder.create_typedef(
        i32ty.as_type(),
        "",
        compile_unit.get_file(),
        0,
        compile_unit.get_file().as_debug_info_scope(),
        32,
    );

    unsafe {
        let ph1 = dibuilder.create_placeholder_derived_type(&context);
        let ph2 = dibuilder.create_placeholder_derived_type(&context);

        dibuilder.replace_placeholder_derived_type(ph2, ph1);
        dibuilder.replace_placeholder_derived_type(ph1, typedefty);
    }
}

#[test]
#[llvm_versions(7.0)]
fn test_anonymous_basic_type() {
    let context = Context::create();
    let module = context.create_module("bin");

    let (dibuilder, _compile_unit) = module.create_debug_info_builder(
        true,
        DWARFSourceLanguage::C,
        "source_file",
        ".",
        "my llvm compiler frontend",
        false,
        "",
        0,
        "",
        DWARFEmissionKind::Full,
        0,
        false,
        false,
    );

    assert_eq!(
        dibuilder.create_basic_type("", 0_u64, 0x00),
        Err("basic types must have names")
    );
}

#[test]
#[llvm_versions(8.0..=latest)]
fn test_anonymous_basic_type() {
    let context = Context::create();
    let module = context.create_module("bin");

    let (dibuilder, _compile_unit) = module.create_debug_info_builder(
        true,
        DWARFSourceLanguage::C,
        "source_file",
        ".",
        "my llvm compiler frontend",
        false,
        "",
        0,
        "",
        DWARFEmissionKind::Full,
        0,
        false,
        false,
    );

    assert_eq!(
        dibuilder.create_basic_type("", 0_u64, 0x00, DIFlags::Zero),
        Err("basic types must have names")
    );
}
<|endoftext|>


<commit_before>use std::cmp::Ordering;
use std::collections::{BinaryHeap, HashMap};
use std::hash::{Hasher, BuildHasherDefault};
use std::usize;

use murmurhash3::murmurhash3_x64_128;

// The individual items to store in the BinaryHeap
pub type ItemHash = usize;

#[inline]
pub fn hash_f(item: &[u8], seed: u64) -> ItemHash {
    murmurhash3_x64_128(item, seed).0 as ItemHash
}

#[derive(Debug)]
struct HashedItem<T> {
    hash: ItemHash,
    item: T,
}

impl<T> PartialEq for HashedItem<T> {
    fn eq(&self, other: &HashedItem<T>) -> bool {
        other.hash.eq(&self.hash)
    }
}

impl<T> Eq for HashedItem<T> {}

impl<T> Ord for HashedItem<T> {
    fn cmp(&self, other: &HashedItem<T>) -> Ordering {
        self.hash.cmp(&other.hash)
    }
}

impl<T> PartialOrd for HashedItem<T> {
    fn partial_cmp(&self, other: &HashedItem<T>) -> Option<Ordering> {
        Some(self.hash.cmp(&other.hash))
    }
}

/// If we're using a `HashMap` where the keys themselves are hashes, it's
/// a little silly to re-hash them. That's where the `NoHashHasher` comes in.
pub struct NoHashHasher(u64);

impl Default for NoHashHasher {
    #[inline]
    fn default() -> NoHashHasher {
        NoHashHasher(0x0000000000000000)
    }
}

impl Hasher for NoHashHasher {
    #[inline]
    fn write(&mut self, bytes: &[u8]) {
        *self = NoHashHasher(
            ((bytes[0] as u64) << 24) +
            ((bytes[1] as u64) << 16) +
            ((bytes[2] as u64) << 8) +
            (bytes[3] as u64)
        );
    }
    fn finish(&self) -> u64 { self.0 }
}

#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Hash, Serialize)]
pub struct KmerCount {
    pub hash: ItemHash,
    pub kmer: Vec<u8>,
    pub count: u16,
    pub extra_count: u16,
}

pub struct MinHashKmers {
    hashes: BinaryHeap<HashedItem<Vec<u8>>>,
    counts: HashMap<ItemHash, (u16, u16), BuildHasherDefault<NoHashHasher>>,
    total_count: u64,
    size: usize,
    seed: u64,
    // heap_lock: Mutex<()>,
    // instead of map_lock, look into using https://docs.rs/chashmap/0.1.2/chashmap/
    // map_lock: Mutex<()>,
}

impl MinHashKmers {
    pub fn new(size: usize, seed: u64) -> Self {
        MinHashKmers {
            hashes: BinaryHeap::with_capacity(size + 1),
            counts: HashMap::with_capacity_and_hasher(size, BuildHasherDefault::default()),
            total_count: 0,
            size: size,
            seed: seed,
            // heap_lock: Mutex::new(()),
            // map_lock: Mutex::new(()),
        }
    }

    pub fn push(&mut self, kmer: &[u8], extra_count: u8) {
        let new_hash = hash_f(kmer, self.seed);
        let add_hash = match self.hashes.peek() {
            None => true,
            Some(old_max_hash) => (new_hash <= (*old_max_hash).hash) || (self.hashes.len() < self.size),
        };

        if add_hash {
            self.total_count += 1;
            if self.counts.contains_key(&new_hash) {
                // let _lock = self.map_lock.lock().unwrap();
                let count = self.counts.entry(new_hash).or_insert((0u16, 0u16));
                (*count).0 += 1;
                (*count).1 += extra_count as u16;
                // drop(_lock);
            } else {
                // let _ = self.heap_lock.lock().unwrap();
                self.hashes.push(HashedItem {
                    hash: new_hash,
                    item: kmer.to_owned(),
                });
                // let _map_lock = self.map_lock.lock().unwrap();
                self.counts.insert(new_hash, (1u16, extra_count as u16));
                if self.hashes.len() > self.size {
                    let hash = self.hashes.pop().unwrap();
                    let old_count = self.counts.remove(&hash.hash).unwrap().0;
                    // TODO: check if old_count / total_count > ...?
                    self.total_count -= old_count as u64;
                }
                // drop(_lock);
                // drop(_map_lock);
            }
        }
    }

    pub fn into_vec(self) -> Vec<KmerCount> {
        let mut vec = self.hashes.into_sorted_vec();

        let mut results = Vec::with_capacity(vec.len());
        for item in vec.drain(..) {
            let counts = *self.counts.get(&item.hash).unwrap();
            let new_item = KmerCount {
                hash: item.hash,
                kmer: item.item,
                count: counts.0,
                extra_count: counts.1,
            };
            results.push(new_item);
        }
        results
    }
}

#[test]
fn test_minhashkmers() {
    let mut queue = MinHashKmers::new(3, 42);
    queue.push(b"ca", 0);
    queue.push(b"cc", 1);
    queue.push(b"ac", 0);
    queue.push(b"ac", 1);
    let array = queue.into_vec();
    assert_eq!(array[0].kmer, vec![b'c', b'c']);
    assert_eq!(array[0].count, 1u16);
    assert_eq!(array[0].extra_count, 1u16);
    assert!(array[0].hash < array[1].hash);
    assert_eq!(array[1].kmer, vec![b'c', b'a']);
    assert_eq!(array[1].count, 1u16);
    assert_eq!(array[1].extra_count, 0u16);
    assert!(array[1].hash < array[2].hash);
    assert_eq!(array[2].kmer, vec![b'a', b'c']);
    assert_eq!(array[2].count, 2u16);
    assert_eq!(array[2].extra_count, 1u16);
}

#[test]
fn test_longer_sequence() {
    let mut queue = MinHashKmers::new(100, 42);

    // for "ACACGGAAATCCTCACGTCGCGGCGCCGGGC"

    // hashes should be:
    //     (3186265289206375993,
    //      3197567229193635484,
    //      5157287830980272133,
    //      7515070071080094037,
    //      9123665698461883699,
    //      9650810550987401968,
    //      10462414310441547028,
    //      12872951831549606632,
    //      13584836512372089324,
    //      14093285637546356047,
    //      16069721578136260683)

}
<commit_msg>Make sketches clonable<commit_after>use std::cmp::Ordering;
use std::collections::{BinaryHeap, HashMap};
use std::hash::{Hasher, BuildHasherDefault};
use std::usize;

use murmurhash3::murmurhash3_x64_128;

// The individual items to store in the BinaryHeap
pub type ItemHash = usize;

#[inline]
pub fn hash_f(item: &[u8], seed: u64) -> ItemHash {
    murmurhash3_x64_128(item, seed).0 as ItemHash
}

#[derive(Debug, Clone)]
struct HashedItem<T> {
    hash: ItemHash,
    item: T,
}

impl<T> PartialEq for HashedItem<T> {
    fn eq(&self, other: &HashedItem<T>) -> bool {
        other.hash.eq(&self.hash)
    }
}

impl<T> Eq for HashedItem<T> {}

impl<T> Ord for HashedItem<T> {
    fn cmp(&self, other: &HashedItem<T>) -> Ordering {
        self.hash.cmp(&other.hash)
    }
}

impl<T> PartialOrd for HashedItem<T> {
    fn partial_cmp(&self, other: &HashedItem<T>) -> Option<Ordering> {
        Some(self.hash.cmp(&other.hash))
    }
}

/// If we're using a `HashMap` where the keys themselves are hashes, it's
/// a little silly to re-hash them. That's where the `NoHashHasher` comes in.
pub struct NoHashHasher(u64);

impl Default for NoHashHasher {
    #[inline]
    fn default() -> NoHashHasher {
        NoHashHasher(0x0000000000000000)
    }
}

impl Hasher for NoHashHasher {
    #[inline]
    fn write(&mut self, bytes: &[u8]) {
        *self = NoHashHasher(
            ((bytes[0] as u64) << 24) +
            ((bytes[1] as u64) << 16) +
            ((bytes[2] as u64) << 8) +
            (bytes[3] as u64)
        );
    }
    fn finish(&self) -> u64 { self.0 }
}

#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Hash, Serialize)]
pub struct KmerCount {
    pub hash: ItemHash,
    pub kmer: Vec<u8>,
    pub count: u16,
    pub extra_count: u16,
}

#[derive(Clone)]
pub struct MinHashKmers {
    hashes: BinaryHeap<HashedItem<Vec<u8>>>,
    counts: HashMap<ItemHash, (u16, u16), BuildHasherDefault<NoHashHasher>>,
    total_count: u64,
    size: usize,
    seed: u64,
    // heap_lock: Mutex<()>,
    // instead of map_lock, look into using https://docs.rs/chashmap/0.1.2/chashmap/
    // map_lock: Mutex<()>,
}

impl MinHashKmers {
    pub fn new(size: usize, seed: u64) -> Self {
        MinHashKmers {
            hashes: BinaryHeap::with_capacity(size + 1),
            counts: HashMap::with_capacity_and_hasher(size, BuildHasherDefault::default()),
            total_count: 0,
            size: size,
            seed: seed,
            // heap_lock: Mutex::new(()),
            // map_lock: Mutex::new(()),
        }
    }

    pub fn push(&mut self, kmer: &[u8], extra_count: u8) {
        let new_hash = hash_f(kmer, self.seed);
        let add_hash = match self.hashes.peek() {
            None => true,
            Some(old_max_hash) => (new_hash <= (*old_max_hash).hash) || (self.hashes.len() < self.size),
        };

        if add_hash {
            self.total_count += 1;
            if self.counts.contains_key(&new_hash) {
                // let _lock = self.map_lock.lock().unwrap();
                let count = self.counts.entry(new_hash).or_insert((0u16, 0u16));
                (*count).0 += 1;
                (*count).1 += extra_count as u16;
                // drop(_lock);
            } else {
                // let _ = self.heap_lock.lock().unwrap();
                self.hashes.push(HashedItem {
                    hash: new_hash,
                    item: kmer.to_owned(),
                });
                // let _map_lock = self.map_lock.lock().unwrap();
                self.counts.insert(new_hash, (1u16, extra_count as u16));
                if self.hashes.len() > self.size {
                    let hash = self.hashes.pop().unwrap();
                    let old_count = self.counts.remove(&hash.hash).unwrap().0;
                    // TODO: check if old_count / total_count > ...?
                    self.total_count -= old_count as u64;
                }
                // drop(_lock);
                // drop(_map_lock);
            }
        }
    }

    pub fn total_kmers(&self) -> usize {
        self.total_count as usize
    }

    pub fn into_vec(self) -> Vec<KmerCount> {
        let mut vec = self.hashes.into_sorted_vec();

        let mut results = Vec::with_capacity(vec.len());
        for item in vec.drain(..) {
            let counts = *self.counts.get(&item.hash).unwrap();
            let new_item = KmerCount {
                hash: item.hash,
                kmer: item.item,
                count: counts.0,
                extra_count: counts.1,
            };
            results.push(new_item);
        }
        results
    }
}

#[test]
fn test_minhashkmers() {
    let mut queue = MinHashKmers::new(3, 42);
    queue.push(b"ca", 0);
    queue.push(b"cc", 1);
    queue.push(b"ac", 0);
    queue.push(b"ac", 1);
    let array = queue.into_vec();
    assert_eq!(array[0].kmer, vec![b'c', b'c']);
    assert_eq!(array[0].count, 1u16);
    assert_eq!(array[0].extra_count, 1u16);
    assert!(array[0].hash < array[1].hash);
    assert_eq!(array[1].kmer, vec![b'c', b'a']);
    assert_eq!(array[1].count, 1u16);
    assert_eq!(array[1].extra_count, 0u16);
    assert!(array[1].hash < array[2].hash);
    assert_eq!(array[2].kmer, vec![b'a', b'c']);
    assert_eq!(array[2].count, 2u16);
    assert_eq!(array[2].extra_count, 1u16);
}

#[test]
fn test_longer_sequence() {
    let mut queue = MinHashKmers::new(100, 42);

    // for "ACACGGAAATCCTCACGTCGCGGCGCCGGGC"

    // hashes should be:
    //     (3186265289206375993,
    //      3197567229193635484,
    //      5157287830980272133,
    //      7515070071080094037,
    //      9123665698461883699,
    //      9650810550987401968,
    //      10462414310441547028,
    //      12872951831549606632,
    //      13584836512372089324,
    //      14093285637546356047,
    //      16069721578136260683)

}
<|endoftext|>


<commit_before>use term_painter::ToStyle;
use term_painter::Color::*;
use std::io;

mod types;

// Game logic (board, initialization, valid move, set, play or finished)

/// Visualization of the boards.
fn print_boards(board1: &Vec<types::SubField>, board2: &Vec<types::SubField>) {
    println!("{}{}", "------------------ O W N   B O A R D ------------------",
        "------------------------- O P P O N E N T ----------------");

    let mut cnt = 9;

    for i in 0..10 {
        println!("");
        print!("{}  ", cnt);
        for j in 0..10 {
            if board1[j + i * 10] == types::SubField::Hit {
                print!(" {} ", Red.paint(board1[j + i * 10]));
            } else {
                print!(" {} ", board1[j + i * 10]);
            }
        }
        print!("        ");
        print!("{}  ", cnt);
        for j in 0..10 {
            if board2[j + i * 10] == types::SubField::Hit {
                print!(" {} ", Green.paint(board2[j + i * 10]));
            } else {
                print!(" {} ", board2[j + i * 10]);
            }
        }
        println!("");
        cnt -= 1;
    }
    println!("");
    println!("{}{}", "     A    B    C    D    E    F    G    H    I    J",
        "               A    B    C    D    E    F    G    H    I    J");
    println!("");
    println!("{}{}", "----------------------------------------------------",
        "--------------------------------------------------------------");
}

/// Reads a string from the terminal / user.
fn read_string() -> String {
    let mut buffer = String::new();
    io::stdin()
        .read_line(&mut buffer)
        .expect("something went horribly wrong...");

    /* Discard trailing newline */
    let new_len = buffer.trim_right().len();
    buffer.truncate(new_len);

    buffer
}

/// The actual placement of the ships.
fn place(player: &mut types::Player, ship: &types::ShipType) -> u8 {

    /* Vector to collect the indices for the possible ship position. */
    let mut indices = Vec::new();

    /* 100 --> invalid value */
    let mut input = 100;
    while input == 100 {
        input = get_input();
        match player.own_board[input] {
            types::SubField::Water => { indices.push(input); },
            _ => {
                println!("Invalid input, again please.");
                input = 100;
            },
        }
    }

    println!("{}{}", "Enter 'h' for a horizontal (upwards) orientation of the ship,",
        "'v' for a vertical (rightwards) one.");
    /* x --> invalid value */
    let mut orientation = "x".to_string();
    while orientation == "x" {
        orientation = read_string();
        if orientation != "h" && orientation != "v" {
            println!("Invalid input, again please.");
            orientation = "x".to_string();
        }
    }

    if orientation == "v" {
        for _ in 0..ship.size - 1 {
            /* Check to prevent out of bounds errors. */
            if input >= 10 {
                input -= 10;
            }
            /* input < 10 --> no field above */
            if player.own_board[input] != types::SubField::Water || input < 10 {
                    println!("Invalid position for this ship.");
                    println!("Please choose another coordinate.");
                    return 1
            }
            indices.push(input);
        }
    } else {
        for _ in 0..ship.size - 1 {
            /* Check to prevent out of bounds errors. */
            if input < 99 {
                input += 1;
            }
            /* unit position == 9 --> no field to the right */
            if player.own_board[input] != types::SubField::Water || (input % 10) == 9 {
                    println!("Invalid position for this ship.");
                    println!("Please choose another coordinate.");
                    return 1
            }
            indices.push(input);
        }
    }

    /* Places the ships on the board. */
    for i in indices.iter() {
        player.own_board[*i] = types::SubField::Ship;
    }

    0
}

/// Handles the initial ship placement for each player.
fn place_ships(mut player1: &mut types::Player, mut player2: &mut types::Player) {

    /* A vector of all the ships each player needs to place.
       The default version: #  Class of ship Size
                            1   Carrier       5
                            2   Battleship    4
                            3   Cruiser       3
                            4   Submarine     3
                            5   Destroyer     2
    */
    let s1 = types::ShipType{ name: "Carrier".to_string(), size: 5, amount: 1 };
    let s2 = types::ShipType{ name: "Battleship".to_string(), size: 4, amount: 2 };
    let s3 = types::ShipType{ name: "Cruiser".to_string(), size: 3, amount: 3 };
    let s4 = types::ShipType{ name: "Submarine".to_string(), size: 3, amount: 4 };
    let s5 = types::ShipType{ name: "Destroyer".to_string(), size: 2, amount: 5 };
    let ships = vec![s1, s2, s3, s4, s5];

    print_boards(&player1.own_board, &player1.op_board);

    /* Error code, should be replaced by proper error handling later. */
    let mut err;

    /* Asks player1 to place the ships. */
    for i in ships.iter() {
        for _ in 0..i.amount {
            err = 1;
            while err == 1 {
                println!("{}, please enter the first coordinate for your {:?} ({} fields).",
                    player1.name, i.name, i.size);
                err = place(&mut player1, i);
            }
            player1.capacity += i.size;
            print_boards(&player1.own_board, &player1.op_board);
        }
    }

    /* Asks player2 to place the ships. */
    for i in ships.iter() {
        for _ in 0..i.amount {
            err = 1;
            while err == 1 {
                println!("{}, please enter the first coordinate for your {:?} ({} fields).",
                    player2.name, i.name, i.size);
                err = place(&mut player2, i);
            }
            player2.capacity += i.size;
            print_boards(&player2.own_board, &player2.op_board);
        }
    }
}

/// Reads the coordinates of a field from the user
/// and returns the corresponding index.
fn get_input() -> usize {

    /* 100 --> invalid */
    let mut input = 100;

    while input == 100 {
        input = match read_string().as_ref() {
            "A0" => 90, "A1" => 80,"A2" => 70, "A3" => 60, "A4" => 50,
            "A5" => 40, "A6" => 30, "A7" => 20, "A8" => 10, "A9" => 0,
            "B0" => 91, "B1" => 81, "B2" => 71, "B3" => 61, "B4" => 51,
            "B5" => 41, "B6" => 31, "B7" => 21, "B8" => 11, "B9" => 1,
            "C0" => 92, "C1" => 82, "C2" => 72, "C3" => 62, "C4" => 52,
            "C5" => 42, "C6" => 32, "C7" => 22, "C8" => 12, "C9" => 2,
            "D0" => 93, "D1" => 83, "D2" => 73, "D3" => 63, "D4" => 53,
            "D5" => 43, "D6" => 33, "D7" => 23, "D8" => 13, "D9" => 3,
            "E0" => 94, "E1" => 84, "E2" => 74, "E3" => 64, "E4" => 54,
            "E5" => 44, "E6" => 34, "E7" => 24, "E8" => 14, "E9" => 4,
            "F0" => 95, "F1" => 85, "F2" => 75, "F3" => 65, "F4" => 55,
            "F5" => 45, "F6" => 35, "F7" => 25, "F8" => 15, "F9" => 5,
            "G0" => 96, "G1" => 86, "G2" => 76, "G3" => 66, "G4" => 56,
            "G5" => 46, "G6" => 36, "G7" => 26, "G8" => 16, "G9" => 6,
            "H0" => 97, "H1" => 87, "H2" => 77, "H3" => 67, "H4" => 57,
            "H5" => 47, "H6" => 37, "H7" => 27, "H8" => 17, "H9" => 7,
            "I0" => 98, "I1" => 88, "I2" => 78, "I3" => 68, "I4" => 58,
            "I5" => 48, "I6" => 38, "I7" => 28, "I8" => 18, "I9" => 8,
            "J0" => 99, "J1" => 89, "J2" => 79, "J3" => 69, "J4" => 59,
            "J5" => 49, "J6" => 39, "J7" => 29, "J8" => 19, "J9" => 9,
            _ => 100,
        };

        if input == 100 {
            println!("Invalid field, try again.")
        }
    }
    input
}

/// Determines the type of the SubField that got hit
/// by the current move and sets it accordingly.
fn match_move(first: &mut types::Player, second: &mut types::Player, idx: usize) {

    match second.own_board[idx] {
        types::SubField::Water => {
            println!("Miss - try again.");
            first.op_board[idx] = types::SubField::WaterHit;
        }
        types::SubField::Ship => {
            println!("Hit!");
            first.op_board[idx] = types::SubField::Hit;
            second.own_board[idx] = types::SubField::Hit;
            second.capacity -= 1;
        },
        types::SubField::Hit => { println!("Already hit."); }
        types::SubField::WaterHit => { println!("Miss - try again."); }
    }
}

/// Lets the players perform their moves.
fn make_move(mut first: &mut types::Player, mut second: &mut types::Player) {
    println!("Enter coordinates, {}:", first.name);
    let input = get_input();
    match_move(&mut first, &mut second, input);
}

/// Returns whether all the player's ships got destroyed.
pub fn game_over(player: &types::Player) -> bool {
    player.capacity <= 0
}

/// Initializes the players and the boards and provides the
/// game loop which lets the players perform their moves alternately.
pub fn start_match() {

    /* Creates the initial (empty) boards (10 x 10) for player1. */
    let mut player1 = types::Player {
        own_board: vec![types::SubField::Water; 100],
        op_board: vec![types::SubField::Water; 100],
        capacity: 0,
        name: "Player1".to_string(),
    };
    /* Creates the initial (empty) boards (10 x 10) for player2. */
    let mut player2 = types::Player {
        own_board: vec![types::SubField::Water; 100],
        op_board: vec![types::SubField::Water; 100],
        capacity: 0,
        name: "Player2".to_string(),
    };

    /* Initializes the boards with the player's ships. */
    place_ships(&mut player1, &mut player2);

    loop {
        print_boards(&player1.own_board, &player1.op_board);
        make_move(&mut player1, &mut player2);
        if game_over(&player2) {
            println!("G A M E   O V E R");
            println!("Congratulations, Player1");
            break;
        }

        print_boards(&player2.own_board, &player2.op_board);
        make_move(&mut player2, &mut player1);
        if game_over(&player1) {
            println!("G A M E   O V E R");
            println!("Congratulations, Player2");
            break;
        }
    }
}
<commit_msg>error handling<commit_after>use term_painter::ToStyle;
use term_painter::Color::*;
use std::io;

mod types;

// Game logic (board, initialization, valid move, set, play or finished)

/// Visualization of the boards.
fn print_boards(board1: &Vec<types::SubField>, board2: &Vec<types::SubField>) {
    println!("{}{}", "------------------ O W N   B O A R D ------------------",
        "------------------------- O P P O N E N T ----------------");

    let mut cnt = 9;

    for i in 0..10 {
        println!("");
        print!("{}  ", cnt);
        for j in 0..10 {
            if board1[j + i * 10] == types::SubField::Hit {
                print!(" {} ", Red.paint(board1[j + i * 10]));
            } else {
                print!(" {} ", board1[j + i * 10]);
            }
        }
        print!("        ");
        print!("{}  ", cnt);
        for j in 0..10 {
            if board2[j + i * 10] == types::SubField::Hit {
                print!(" {} ", Green.paint(board2[j + i * 10]));
            } else {
                print!(" {} ", board2[j + i * 10]);
            }
        }
        println!("");
        cnt -= 1;
    }
    println!("");
    println!("{}{}", "     A    B    C    D    E    F    G    H    I    J",
        "               A    B    C    D    E    F    G    H    I    J");
    println!("");
    println!("{}{}", "----------------------------------------------------",
        "--------------------------------------------------------------");
}

/// Reads a string from the terminal / user.
fn read_string() -> String {
    let mut buffer = String::new();
    io::stdin()
        .read_line(&mut buffer)
        .expect("something went horribly wrong...");

    /* Discard trailing newline */
    let new_len = buffer.trim_right().len();
    buffer.truncate(new_len);

    buffer
}

/// The actual placement of the ships.
fn place(player: &mut types::Player, ship: &types::ShipType) -> Result<(), String> {

    /* Vector to collect the indices for the possible ship position. */
    let mut indices = Vec::new();

    /* 100 --> invalid value */
    let mut input = 100;
    while input == 100 {
        input = get_input();
        match player.own_board[input] {
            types::SubField::Water => { indices.push(input); },
            _ => {
                println!("Invalid input, again please.");
                input = 100;
            },
        }
    }

    println!("{}{}", "Enter 'h' for a horizontal (upwards) orientation of the ship,",
        "'v' for a vertical (rightwards) one.");
    /* x --> invalid value */
    let mut orientation = "x".to_string();
    while orientation == "x" {
        orientation = read_string();
        if orientation != "h" && orientation != "v" {
            println!("Invalid input, again please.");
            orientation = "x".to_string();
        }
    }

    if orientation == "v" {
        for _ in 0..ship.size - 1 {
            /* Check to prevent out of bounds errors. */
            if input >= 10 {
                input -= 10;
            }
            /* input < 10 --> no field above */
            if player.own_board[input] != types::SubField::Water || input < 10 {
                return Err("Invalid position for this ship, please choose another coordinate."
                    .to_string())
            }
            indices.push(input);
        }
    } else {
        for _ in 0..ship.size - 1 {
            /* Check to prevent out of bounds errors. */
            if input < 99 {
                input += 1;
            }
            /* unit position == 9 --> no field to the right */
            if player.own_board[input] != types::SubField::Water || (input % 10) == 9 {
                return Err("Invalid position for this ship, please choose another coordinate."
                    .to_string())
            }
            indices.push(input);
        }
    }

    /* Places the ships on the board. */
    for i in indices.iter() {
        player.own_board[*i] = types::SubField::Ship;
    }

    Ok(())
}

/// Handles the initial ship placement for each player.
fn place_ships(mut player1: &mut types::Player, mut player2: &mut types::Player) {

    /* A vector of all the ships each player needs to place.
       The default version: #  Class of ship Size
                            1   Carrier       5
                            2   Battleship    4
                            3   Cruiser       3
                            4   Submarine     3
                            5   Destroyer     2
    */
    let s1 = types::ShipType{ name: "Carrier".to_string(), size: 5, amount: 1 };
    let s2 = types::ShipType{ name: "Battleship".to_string(), size: 4, amount: 2 };
    let s3 = types::ShipType{ name: "Cruiser".to_string(), size: 3, amount: 3 };
    let s4 = types::ShipType{ name: "Submarine".to_string(), size: 3, amount: 4 };
    let s5 = types::ShipType{ name: "Destroyer".to_string(), size: 2, amount: 5 };
    let ships = vec![s1, s2, s3, s4, s5];

    print_boards(&player1.own_board, &player1.op_board);

    /* Asks player1 to place the ships. */
    for i in ships.iter() {
        for _ in 0..i.amount {
            loop {
                println!("{}, please enter the first coordinate for your {:?} ({} fields).",
                    player1.name, i.name, i.size);
                match place(&mut player1, i) {
                    Ok(_) => { break; },
                    Err(e) => { println!("{}", e); },
                }
            }
            player1.capacity += i.size;
            print_boards(&player1.own_board, &player1.op_board);
        }
    }

    /* Asks player2 to place the ships. */
    for i in ships.iter() {
        for _ in 0..i.amount {
            loop {
                println!("{}, please enter the first coordinate for your {:?} ({} fields).",
                    player2.name, i.name, i.size);
                match place(&mut player2, i) {
                    Ok(_) => { break; },
                    Err(e) => { println!("{}", e); },
                }
            }
            player2.capacity += i.size;
            print_boards(&player2.own_board, &player2.op_board);
        }
    }
}

/// Reads the coordinates of a field from the user
/// and returns the corresponding index.
fn get_input() -> usize {

    /* 100 --> invalid */
    let mut input = 100;

    while input == 100 {
        input = match read_string().as_ref() {
            "A0" => 90, "A1" => 80,"A2" => 70, "A3" => 60, "A4" => 50,
            "A5" => 40, "A6" => 30, "A7" => 20, "A8" => 10, "A9" => 0,
            "B0" => 91, "B1" => 81, "B2" => 71, "B3" => 61, "B4" => 51,
            "B5" => 41, "B6" => 31, "B7" => 21, "B8" => 11, "B9" => 1,
            "C0" => 92, "C1" => 82, "C2" => 72, "C3" => 62, "C4" => 52,
            "C5" => 42, "C6" => 32, "C7" => 22, "C8" => 12, "C9" => 2,
            "D0" => 93, "D1" => 83, "D2" => 73, "D3" => 63, "D4" => 53,
            "D5" => 43, "D6" => 33, "D7" => 23, "D8" => 13, "D9" => 3,
            "E0" => 94, "E1" => 84, "E2" => 74, "E3" => 64, "E4" => 54,
            "E5" => 44, "E6" => 34, "E7" => 24, "E8" => 14, "E9" => 4,
            "F0" => 95, "F1" => 85, "F2" => 75, "F3" => 65, "F4" => 55,
            "F5" => 45, "F6" => 35, "F7" => 25, "F8" => 15, "F9" => 5,
            "G0" => 96, "G1" => 86, "G2" => 76, "G3" => 66, "G4" => 56,
            "G5" => 46, "G6" => 36, "G7" => 26, "G8" => 16, "G9" => 6,
            "H0" => 97, "H1" => 87, "H2" => 77, "H3" => 67, "H4" => 57,
            "H5" => 47, "H6" => 37, "H7" => 27, "H8" => 17, "H9" => 7,
            "I0" => 98, "I1" => 88, "I2" => 78, "I3" => 68, "I4" => 58,
            "I5" => 48, "I6" => 38, "I7" => 28, "I8" => 18, "I9" => 8,
            "J0" => 99, "J1" => 89, "J2" => 79, "J3" => 69, "J4" => 59,
            "J5" => 49, "J6" => 39, "J7" => 29, "J8" => 19, "J9" => 9,
            _ => 100,
        };

        if input == 100 {
            println!("Invalid field, try again.")
        }
    }
    input
}

/// Determines the type of the SubField that got hit
/// by the current move and sets it accordingly.
fn match_move(first: &mut types::Player, second: &mut types::Player, idx: usize) {

    match second.own_board[idx] {
        types::SubField::Water => {
            println!("Miss - try again.");
            first.op_board[idx] = types::SubField::WaterHit;
        }
        types::SubField::Ship => {
            println!("Hit!");
            first.op_board[idx] = types::SubField::Hit;
            second.own_board[idx] = types::SubField::Hit;
            second.capacity -= 1;
        },
        types::SubField::Hit => { println!("Already hit."); }
        types::SubField::WaterHit => { println!("Miss - try again."); }
    }
}

/// Lets the players perform their moves.
fn make_move(mut first: &mut types::Player, mut second: &mut types::Player) {
    println!("Enter coordinates, {}:", first.name);
    let input = get_input();
    match_move(&mut first, &mut second, input);
}

/// Returns whether all the player's ships got destroyed.
pub fn game_over(player: &types::Player) -> bool {
    player.capacity <= 0
}

/// Initializes the players and the boards and provides the
/// game loop which lets the players perform their moves alternately.
pub fn start_match() {

    /* Creates the initial (empty) boards (10 x 10) for player1. */
    let mut player1 = types::Player {
        own_board: vec![types::SubField::Water; 100],
        op_board: vec![types::SubField::Water; 100],
        capacity: 0,
        name: "Player1".to_string(),
    };
    /* Creates the initial (empty) boards (10 x 10) for player2. */
    let mut player2 = types::Player {
        own_board: vec![types::SubField::Water; 100],
        op_board: vec![types::SubField::Water; 100],
        capacity: 0,
        name: "Player2".to_string(),
    };

    /* Initializes the boards with the player's ships. */
    place_ships(&mut player1, &mut player2);

    loop {
        print_boards(&player1.own_board, &player1.op_board);
        make_move(&mut player1, &mut player2);
        if game_over(&player2) {
            println!("G A M E   O V E R");
            println!("Congratulations, Player1");
            break;
        }

        print_boards(&player2.own_board, &player2.op_board);
        make_move(&mut player2, &mut player1);
        if game_over(&player1) {
            println!("G A M E   O V E R");
            println!("Congratulations, Player2");
            break;
        }
    }
}
<|endoftext|>


<commit_before>#![cfg(target_os = "macos")]

use Scale;
use Vsync;
use Key;

use libc;
//use cocoa::appkit;
use cocoa::appkit::*;
//use cocoa::appkit::NSEventSubtype::*;

#[allow(unused_imports)]
use cocoa::base::{id, nil};
#[allow(unused_imports)]
use objc::runtime::{Class, Object, Sel, BOOL, YES, NO};
use objc::declare::ClassDecl;

#[allow(unused_imports)]
use cocoa::foundation::{NSAutoreleasePool, NSDate, NSDefaultRunLoopMode, NSPoint, NSRect, NSSize,
                        NSString, NSUInteger};

use std::ops::Deref;

pub struct Window {
    view: IdRef,
    window: IdRef,
    delegate: WindowDelegate,
}

struct DelegateState {
    view: IdRef,
    window: IdRef,
    resize_handler: Option<fn(u32, u32)>,
}

struct WindowDelegate {
    state: Box<DelegateState>,
    _this: IdRef,
}

//sthou

impl WindowDelegate {
    /// Get the delegate class, initiailizing it neccessary
    fn class() -> *const Class {
        use std::sync::{Once, ONCE_INIT};

        extern fn window_should_close(this: &Object, _: Sel, _: id) -> BOOL {
            unsafe {
                let state: *mut libc::c_void = *this.get_ivar("glutinState");
                let state = state as *mut DelegateState;
                //(*state).pending_events.lock().unwrap().push_back(Closed);
            }
            YES
        }

        extern fn window_did_resize(this: &Object, _: Sel, _: id) {
            unsafe {
                let state: *mut libc::c_void = *this.get_ivar("glutinState");
                let state = &mut *(state as *mut DelegateState);

                println!("did_resize");

                //let _: () = msg_send![*state.context, update];

                if let Some(handler) = state.resize_handler {
                    let rect = NSView::frame(*state.view);
                    let scale_factor = NSWindow::backingScaleFactor(*state.window) as f32;
                    (handler)((scale_factor * rect.size.width as f32) as u32,
                              (scale_factor * rect.size.height as f32) as u32);
                }
            }
        }

        extern fn window_did_become_key(this: &Object, _: Sel, _: id) {
            unsafe {
                // TODO: center the cursor if the window had mouse grab when it
                // lost focus

                println!("became key window");
                let state: *mut libc::c_void = *this.get_ivar("glutinState");
                let state = state as *mut DelegateState;
                //(*state).pending_events.lock().unwrap().push_back(Focused(true));
            }
        }

        extern fn window_did_resign_key(this: &Object, _: Sel, _: id) {
            unsafe {
                let state: *mut libc::c_void = *this.get_ivar("glutinState");
                let state = state as *mut DelegateState;
                //(*state).pending_events.lock().unwrap().push_back(Focused(false));
            }
        }

        static mut delegate_class: *const Class = 0 as *const Class;
        static INIT: Once = ONCE_INIT;

        INIT.call_once(|| unsafe {
            println!("Create new NSWindowDelegate");
            let superclass = Class::get("NSObject").unwrap();
            let mut decl = ClassDecl::new(superclass, "GlutinWindowDelegate").unwrap();

            // Add callback methods
            decl.add_method(sel!(windowShouldClose:),
                window_should_close as extern fn(&Object, Sel, id) -> BOOL);
            decl.add_method(sel!(windowDidResize:),
                window_did_resize as extern fn(&Object, Sel, id));

            decl.add_method(sel!(windowDidBecomeKey:),
                window_did_become_key as extern fn(&Object, Sel, id));
            decl.add_method(sel!(windowDidResignKey:),
                window_did_resign_key as extern fn(&Object, Sel, id));

            // Store internal state as user data
            decl.add_ivar::<*mut libc::c_void>("glutinState");

            delegate_class = decl.register();
        });

        unsafe {
            delegate_class
        }
    }

    fn new(state: DelegateState) -> WindowDelegate {
        // Box the state so we can give a pointer to it
        let mut state = Box::new(state);
        let state_ptr: *mut DelegateState = &mut *state;
        unsafe {
            let delegate = IdRef::new(msg_send![WindowDelegate::class(), new]);

            (&mut **delegate).set_ivar("glutinState", state_ptr as *mut libc::c_void);
            let _: () = msg_send![*state.window, setDelegate:*delegate];

            WindowDelegate { state: state, _this: delegate }
        }
    }
}

impl Drop for WindowDelegate {
    fn drop(&mut self) {
        unsafe {
            // Nil the window's delegate so it doesn't still reference us
            let _: () = msg_send![*self.state.window, setDelegate:nil];
        }
    }
}

impl Window {
    pub fn new(name: &str, width: usize, height: usize, _: Scale, _: Vsync) -> Result<Window, &str> {
        unsafe  {
            let app = match Self::create_app() {
                Some(app) => app,
                None => {
                    return Err("Couldn't create NSApplication");
                },
            };

            let window = match Self::create_window(name, width, height) {
                Some(window) => window,
                None => {
                    return Err("Unable to create NSWindow");
                }
            };

            let view = match Self::create_view(*window) {
                Some(view) => view,
                None => {
                    return Err("Unable to create NSView");
                }
            };

            app.activateIgnoringOtherApps_(YES);
            window.makeKeyAndOrderFront_(nil);

            let ds = DelegateState {
                view: view.clone(),
                window: window.clone(),
                resize_handler: None,
            };

            println!("Created window and view");

            return Ok(Window {
                window: window,
                view: view,
                delegate: WindowDelegate::new(ds),
            });
        }
    }

    unsafe fn create_window(name: &str, width: usize, height: usize) -> Option<IdRef> {
        let masks = NSResizableWindowMask as NSUInteger |
                    NSClosableWindowMask as NSUInteger |
                    NSTitledWindowMask as NSUInteger;

        let frame = NSRect::new(NSPoint::new(0., 0.), NSSize::new(width as f64, height as f64));

        let window = IdRef::new(NSWindow::alloc(nil).initWithContentRect_styleMask_backing_defer_(
            frame,
            masks,
            NSBackingStoreBuffered,
            NO,
        ));

        window.non_nil().map(|window| {
            let title = IdRef::new(NSString::alloc(nil).init_str(name));
            window.setLevel_(NSMainMenuWindowLevel as i64 + 1);
            window.setTitle_(*title);
            window.center();
            window
        })
    }

    unsafe fn create_view(window: id) -> Option<IdRef> {
        let view = IdRef::new(NSView::alloc(nil).init());
        view.non_nil().map(|view| {
            window.setContentView_(*view);
            view
        })
    }

    pub fn update(&self, _: &[u32]) {
        unsafe {
            NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
                NSAnyEventMask.bits(),
                NSDate::distantPast(nil),
                NSDefaultRunLoopMode,
                YES);
        }
    }

    pub fn get_keys() -> Option<Vec<Key>> {
        return None;
    }

    pub fn is_esc_pressed() -> bool {
        false
    }

    pub fn close() {

    }

    fn create_app() -> Option<id> {
        unsafe {
            let app = NSApp();
            if app == nil {
                None
            } else {
                app.setActivationPolicy_(NSApplicationActivationPolicyRegular);
                Some(app)
            }
        }
    }
}

struct IdRef(id);

impl IdRef {
    fn new(i: id) -> IdRef {
        IdRef(i)
    }

    #[allow(dead_code)]
    fn retain(i: id) -> IdRef {
        if i != nil {
            let _: id = unsafe { msg_send![i, retain] };
        }
        IdRef(i)
    }

    fn non_nil(self) -> Option<IdRef> {
        if self.0 == nil { None } else { Some(self) }
    }
}

impl Drop for IdRef {
    fn drop(&mut self) {
        if self.0 != nil {
            let _: () = unsafe { msg_send![self.0, release] };
        }
    }
}

impl Deref for IdRef {
    type Target = id;
    fn deref<'a>(&'a self) -> &'a id {
        &self.0
    }
}

impl Clone for IdRef {
    fn clone(&self) -> IdRef {
        if self.0 != nil {
            let _: id = unsafe { msg_send![self.0, retain] };
        }
        IdRef(self.0)
    }
}
<commit_msg>WIP on Mac version<commit_after>#![cfg(target_os = "macos")]

use Scale;
use Vsync;
use Key;

use libc;
//use cocoa::appkit;
use cocoa::appkit::*;
//use cocoa::appkit::NSEventSubtype::*;

#[allow(unused_imports)]
use cocoa::base::{id, nil};
#[allow(unused_imports)]
use objc::runtime::{Class, Object, Sel, BOOL, YES, NO};
use objc::declare::ClassDecl;

#[allow(unused_imports)]
use cocoa::foundation::{NSAutoreleasePool, NSDate, NSDefaultRunLoopMode, NSPoint, NSRect, NSSize,
    NSString, NSUInteger};

use std::ops::Deref;

pub struct Window {
    view: IdRef,
    window: IdRef,
    delegate: WindowDelegate,
    view_delegate: ViewDelegate,
}

struct DelegateState {
    view: IdRef,
    window: IdRef,
    resize_handler: Option<fn(u32, u32)>,
}

struct WindowDelegate {
    state: Box<DelegateState>,
    _this: IdRef,
}

struct ViewDelegateState {
    view: IdRef,
}

struct ViewDelegate {
    state: Box<ViewDelegateState>,
    _this: IdRef,
}

impl WindowDelegate {
    /// Get the delegate class, initiailizing it neccessary
    fn class() -> *const Class {
        use std::sync::{Once, ONCE_INIT};

        extern fn window_should_close(this: &Object, _: Sel, _: id) -> BOOL {
            println!("Should close");
            unsafe {
                //let state: *mut libc::c_void = *this.get_ivar("minifb_window_state");
                //let state = state as *mut DelegateState;
                //(*state).pending_events.lock().unwrap().push_back(Closed);
            }
            YES
        }

        extern fn window_did_resize(this: &Object, _: Sel, _: id) {
            unsafe {
                let state: *mut libc::c_void = *this.get_ivar("minifb_window_state");
                let state = &mut *(state as *mut DelegateState);

                println!("did_resize");

                //let _: () = msg_send![*state.context, update];

                if let Some(handler) = state.resize_handler {
                    let rect = NSView::frame(*state.view);
                    let scale_factor = NSWindow::backingScaleFactor(*state.window) as f32;
                    (handler)((scale_factor * rect.size.width as f32) as u32,
                    (scale_factor * rect.size.height as f32) as u32);
                }
            }
        }

        extern fn window_did_become_key(this: &Object, _: Sel, _: id) {
            unsafe {
                // TODO: center the cursor if the window had mouse grab when it
                // lost focus

                println!("became key window");
                let state: *mut libc::c_void = *this.get_ivar("minifb_window_state");
                let state = state as *mut DelegateState;
                //(*state).pending_events.lock().unwrap().push_back(Focused(true));
            }
        }

        extern fn window_did_resign_key(this: &Object, _: Sel, _: id) {
            unsafe {
                let state: *mut libc::c_void = *this.get_ivar("minifb_window_state");
                let state = state as *mut DelegateState;
                //(*state).pending_events.lock().unwrap().push_back(Focused(false));
            }
        }

        static mut delegate_class: *const Class = 0 as *const Class;
        static INIT: Once = ONCE_INIT;

        INIT.call_once(|| unsafe {
            println!("Create new NSWindowDelegate");
            let superclass = Class::get("NSObject").unwrap();
            let mut decl = ClassDecl::new(superclass, "minifb_window_delegate").unwrap();

            // Add callback methods
            decl.add_method(sel!(windowShouldClose:),
            window_should_close as extern fn(&Object, Sel, id) -> BOOL);
            decl.add_method(sel!(windowDidResize:),
            window_did_resize as extern fn(&Object, Sel, id));

            decl.add_method(sel!(windowDidBecomeKey:),
            window_did_become_key as extern fn(&Object, Sel, id));
            decl.add_method(sel!(windowDidResignKey:),
            window_did_resign_key as extern fn(&Object, Sel, id));

            // Store internal state as user data
            decl.add_ivar::<*mut libc::c_void>("minifb_window_state");

            delegate_class = decl.register();
        });

        unsafe {
            delegate_class
        }
    }

    fn new(state: DelegateState) -> WindowDelegate {
        // Box the state so we can give a pointer to it
        let mut state = Box::new(state);
        let state_ptr: *mut DelegateState = &mut *state;
        unsafe {
            let delegate = IdRef::new(msg_send![WindowDelegate::class(), new]);

            (&mut **delegate).set_ivar("minifb_window_state", state_ptr as *mut libc::c_void);
            let _: () = msg_send![*state.window, setDelegate:*delegate];

            println!("Setup delegate");

            WindowDelegate { state: state, _this: delegate }
        }
    }
}

impl Drop for WindowDelegate {
    fn drop(&mut self) {
        unsafe {
            // Nil the window's delegate so it doesn't still reference us
            let _: () = msg_send![*self.state.window, setDelegate:nil];
        }
    }
}

impl ViewDelegate {
    fn class() -> *const Class {
        use std::sync::{Once, ONCE_INIT};

        extern fn draw_rect(this: &Object, _: Sel, _: id) {
            println!("draw_rect");
        }

        static mut delegate_class: *const Class = 0 as *const Class;
        static INIT: Once = ONCE_INIT;

        INIT.call_once(|| unsafe {
            println!("Create new ViewDelegate");
            let superclass = Class::get("NSObject").unwrap();
            let mut decl = ClassDecl::new(superclass, "minifb_view_delegate").unwrap();

            // Add callback methods
            decl.add_method(sel!(drawRect:),
            draw_rect as extern fn(&Object, Sel, id));
            // Store internal state as user data
            decl.add_ivar::<*mut libc::c_void>("minifb_view_state");

            delegate_class = decl.register();
        });

        unsafe {
            delegate_class
        }
    }

    fn new(state: ViewDelegateState) -> ViewDelegate {
        let mut state = Box::new(state);
        let state_ptr: *mut ViewDelegateState = &mut *state;
        unsafe {
            let delegate = IdRef::new(msg_send![ViewDelegate::class(), new]);

            (&mut **delegate).set_ivar("minifb_view_state", state_ptr as *mut libc::c_void);
            let _: () = msg_send![*state.view, setDelegate:*delegate];

            ViewDelegate { state: state, _this: delegate }
        }
    }
}

impl Drop for ViewDelegate {
    fn drop(&mut self) {
        unsafe {
            // Nil the views's delegate so it doesn't still reference us
            let _: () = msg_send![*self.state.view, setDelegate:nil];
        }
    }
}

impl Window {
    pub fn new(name: &str, width: usize, height: usize, _: Scale, _: Vsync) -> Result<Window, &str> {
        unsafe  {
            let app = match Self::create_app() {
                Some(app) => app,
                None => {
                    return Err("Couldn't create NSApplication");
                },
            };

            let window = match Self::create_window(name, width, height) {
                Some(window) => window,
                None => {
                    return Err("Unable to create NSWindow");
                }
            };

            let view = match Self::create_view(*window) {
                Some(view) => view,
                None => {
                    return Err("Unable to create NSView");
                }
            };

            app.activateIgnoringOtherApps_(YES);
            window.makeKeyAndOrderFront_(nil);

            let ds = DelegateState {
                view: view.clone(),
                window: window.clone(),
                resize_handler: None,
            };

            let vs = ViewDelegateState {
                view: view.clone(),
            };

            println!("Created window and view");

            return Ok(Window {
                window: window,
                view: view,
                delegate: WindowDelegate::new(ds),
                view_delegate: ViewDelegate::new(vs),
            });
        }
    }

    unsafe fn create_window(name: &str, width: usize, height: usize) -> Option<IdRef> {
        let masks = NSResizableWindowMask as NSUInteger |
            NSClosableWindowMask as NSUInteger |
            NSTitledWindowMask as NSUInteger;

        let frame = NSRect::new(NSPoint::new(0., 0.), NSSize::new(width as f64, height as f64));

        let window = IdRef::new(NSWindow::alloc(nil).initWithContentRect_styleMask_backing_defer_(
                frame,
                masks,
                NSBackingStoreBuffered,
                NO,
                ));

        window.non_nil().map(|window| {
            let title = IdRef::new(NSString::alloc(nil).init_str(name));
            window.setLevel_(NSMainMenuWindowLevel as i64 + 1);
            window.setTitle_(*title);
            window.center();
            window
        })
    }

    unsafe fn create_view(window: id) -> Option<IdRef> {
        let view = IdRef::new(NSView::alloc(nil).init());
        view.non_nil().map(|view| {
            window.setContentView_(*view);
            view
        })
    }

    pub fn update(&self, _: &[u32]) {
        unsafe {
            let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
                NSAnyEventMask.bits(),
                NSDate::distantPast(nil),
                NSDefaultRunLoopMode,
                YES);

            if event != nil {
                NSApp().sendEvent_(event);
            }
        }
    }

    pub fn get_keys() -> Option<Vec<Key>> {
        return None;
    }

    pub fn is_esc_pressed() -> bool {
        false
    }

    pub fn close() {

    }

    fn create_app() -> Option<id> {
        unsafe {
            let app = NSApp();
            if app == nil {
                None
            } else {
                app.setActivationPolicy_(NSApplicationActivationPolicyRegular);
                Some(app)
            }
        }
    }
}

struct IdRef(id);

impl IdRef {
    fn new(i: id) -> IdRef {
        IdRef(i)
    }

    #[allow(dead_code)]
    fn retain(i: id) -> IdRef {
        if i != nil {
            let _: id = unsafe { msg_send![i, retain] };
        }
        IdRef(i)
    }

    fn non_nil(self) -> Option<IdRef> {
        if self.0 == nil { None } else { Some(self) }
    }
}

impl Drop for IdRef {
    fn drop(&mut self) {
        if self.0 != nil {
            let _: () = unsafe { msg_send![self.0, release] };
        }
    }
}

impl Deref for IdRef {
    type Target = id;
    fn deref<'a>(&'a self) -> &'a id {
        &self.0
    }
}

impl Clone for IdRef {
    fn clone(&self) -> IdRef {
        if self.0 != nil {
            let _: id = unsafe { msg_send![self.0, retain] };
        }
        IdRef(self.0)
    }
}
<|endoftext|>