<commit_before>use multiinput::manager::{RawInputManager, DeviceType, XInputInclude,DeviceStats};
use multiinput::event::{RawEvent, KeyId, State, MouseButton, Axis};
use multiinput::devices::HatSwitch;
use std::collections::HashMap;
use games::GameInput;
use input;
use super::{InputHandler, bool_switch};

pub struct MultiInput {
    pub raw_states: RawStates,
    raw_manager: RawInputManager,
    escape_key_switch: bool_switch::BoolSwitch,
    backtick_key_switch: bool_switch::BoolSwitch,
}

#[derive(Default)]
pub struct RawStates {
    pub key_states: HashMap<Key, bool>,
    pub mouse_button_states: HashMap<MouseAndButton, bool>,
    pub mouse_move_states: HashMap<usize, (i32, i32)>,
    pub joystick_button_states: HashMap<JoystickButton, bool>,
    pub joystick_axis_states: HashMap<JoystickAxis, f64>,
    pub joystick_hatswitch_states: HashMap<JoystickHatSwitch, HatSwitch>,
    device_stats: DeviceStats,
}

impl RawStates {
    pub fn flush(&mut self) {
        self.key_states.clear();
        self.mouse_button_states.clear();
        self.mouse_move_states.clear();
    }
}

#[derive(Eq, PartialEq, Hash)]
pub struct Key(pub usize, pub KeyId);
#[derive(Eq, PartialEq, Hash)]
pub struct MouseAndButton(pub usize, pub MouseButton);
#[derive(Eq, PartialEq, Hash)]
pub struct JoystickButton(pub usize, pub usize);
#[derive(Eq, PartialEq, Hash)]
pub struct JoystickAxis(pub usize, pub Axis);
#[derive(Eq, PartialEq, Hash)]
pub struct JoystickHatSwitch(pub usize);

impl MultiInput {
    pub fn new() -> Self {
        let mut raw_manager = RawInputManager::new().unwrap();
        raw_manager.register_devices(DeviceType::Keyboards);
        raw_manager.register_devices(DeviceType::Mice);
        raw_manager.register_devices(DeviceType::Joysticks(XInputInclude::True));
        let raw_states = RawStates{
            device_stats: raw_manager.get_device_stats(),
            ..Default::default()
            };
        MultiInput {
            raw_states: raw_states,
            raw_manager: raw_manager,
            escape_key_switch: bool_switch::BoolSwitch::new(),
            backtick_key_switch: bool_switch::BoolSwitch::new(),
        }
    }
}

impl InputHandler for MultiInput {
    fn receive_input(&mut self) {
        let raw_states = &mut self.raw_states;
        while let Some(event) = self.raw_manager.get_event() {
            match event {
                RawEvent::KeyboardEvent(num, key_id, state)
                    => {raw_states.key_states.insert(Key(num, key_id), state == State::Pressed);},
                RawEvent::MouseButtonEvent(num, mouse_button, state)
                    => {raw_states.mouse_button_states.insert(MouseAndButton(num, mouse_button), state == State::Pressed);},
                RawEvent::MouseMoveEvent(num, x, y)
                    => {raw_states.mouse_move_states.insert(num, (x, y));},
                RawEvent::JoystickButtonEvent(num, button_num, state)
                    => {raw_states.joystick_button_states.insert(JoystickButton(num, button_num), state == State::Pressed);},
                RawEvent::JoystickAxisEvent(num, axis, value)
                    => {raw_states.joystick_axis_states.insert(JoystickAxis(num, axis), value);},
                RawEvent::JoystickHatSwitchEvent(num, value)
                    => {raw_states.joystick_hatswitch_states.insert(JoystickHatSwitch(num), value);},
                _ => (),
            }
        }

        for index in 0..raw_states.device_stats.number_of_keyboards {
            if let Some(&state) = raw_states.key_states.get(&Key(index, KeyId::Escape)) {
                self.escape_key_switch.update_state(state);
            }
            else {
                self.escape_key_switch.clear_switch();
            }
        }
        for index in 0..raw_states.device_stats.number_of_keyboards {
            if let Some(&state) = raw_states.key_states.get(&Key(index, KeyId::BackTick)) {
                self.backtick_key_switch.update_state(state);
            }
            else {
                self.backtick_key_switch.clear_switch();
            }
        }
    }

    fn pass_on_input<'a>(&self, game_input: Option<&'a mut GameInput>) {
        if let Some(input) = game_input {
            if let Some(kbd) = input.get_kbd_inp() {
                for index in 0..self.raw_states.device_stats.number_of_keyboards {
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::Escape)) {
                        kbd.escape = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::Left)) {
                        kbd.left = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::Right)) {
                        kbd.right = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::Up)) {
                        kbd.up = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::Down)) {
                        kbd.down = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::A)) {
                        kbd.a = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::B)) {
                        kbd.b = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::C)) {
                        kbd.c = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::D)) {
                        kbd.d = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::E)) {
                        kbd.e = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::F)) {
                        kbd.f = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::G)) {
                        kbd.g = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::H)) {
                        kbd.h = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::I)) {
                        kbd.i = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::J)) {
                        kbd.j = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::K)) {
                        kbd.k = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::L)) {
                        kbd.l = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::M)) {
                        kbd.m = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::N)) {
                        kbd.n = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::O)) {
                        kbd.o = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::P)) {
                        kbd.p = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::Q)) {
                        kbd.q = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::R)) {
                        kbd.r = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::S)) {
                        kbd.s = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::T)) {
                        kbd.t = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::U)) {
                        kbd.u = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::V)) {
                        kbd.v = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::W)) {
                        kbd.w = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::X)) {
                        kbd.x = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::Y)) {
                        kbd.y = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::Z)) {
                        kbd.z = val;
                    }
                }
            }

            if let Some(mouse) = input.get_mouse_inp() {
                mouse.movement = (0, 0);
                for index in 0..self.raw_states.device_stats.number_of_mice {
                    if let Some(&val) = self.raw_states.mouse_button_states.get(&MouseAndButton(index, MouseButton::Left)) {
                        mouse.left = val;
                    }
                    if let Some(&val) = self.raw_states.mouse_button_states.get(&MouseAndButton(index, MouseButton::Right)) {
                        mouse.left = val;
                    }
                    if let Some(&val) = self.raw_states.mouse_button_states.get(&MouseAndButton(index, MouseButton::Middle)) {
                        mouse.middle = val;
                    }
                    if let Some(&val) = self.raw_states.mouse_button_states.get(&MouseAndButton(index, MouseButton::Button4)) {
                        mouse.button4 = val;
                    }
                    if let Some(&val) = self.raw_states.mouse_button_states.get(&MouseAndButton(index, MouseButton::Button5)) {
                        mouse.button5 = val;
                    }
                    if let Some(&val) = self.raw_states.mouse_move_states.get(&index) {
                        mouse.movement = val;
                    }
                }
            }

            if let Some(joystick) = input.get_joystick_inp() {
                for index in 0..self.raw_states.device_stats.number_of_joysticks {
                    if let Some(&val) = self.raw_states.joystick_button_states.get(&JoystickButton(index, 0)) {
                        joystick.button_1 = val;
                    }
                    if let Some(&val) = self.raw_states.joystick_button_states.get(&JoystickButton(index, 1)) {
                        joystick.button_2 = val;
                    }
                    if let Some(&val) = self.raw_states.joystick_button_states.get(&JoystickButton(index, 2)) {
                        joystick.button_3 = val;
                    }
                    if let Some(&val) = self.raw_states.joystick_button_states.get(&JoystickButton(index, 3)) {
                        joystick.button_4 = val;
                    }
                    if let Some(&val) = self.raw_states.joystick_button_states.get(&JoystickButton(index, 4)) {
                        joystick.button_5 = val;
                    }
                    if let Some(&val) = self.raw_states.joystick_button_states.get(&JoystickButton(index, 5)) {
                        joystick.button_6 = val;
                    }
                    if let Some(&val) = self.raw_states.joystick_button_states.get(&JoystickButton(index, 6)) {
                        joystick.button_7 = val;
                    }
                    if let Some(&val) = self.raw_states.joystick_button_states.get(&JoystickButton(index, 7)) {
                        joystick.button_8 = val;
                    }
                    if let Some(&val) = self.raw_states.joystick_button_states.get(&JoystickButton(index, 8)) {
                        joystick.button_9 = val;
                    }
                    if let Some(&val) = self.raw_states.joystick_button_states.get(&JoystickButton(index, 9)) {
                        joystick.button_10 = val;
                    }
                    if let Some(&val) = self.raw_states.joystick_axis_states.get(&JoystickAxis(index, Axis::X)) {
                        joystick.x_axis = val;
                    }
                    if let Some(&val) = self.raw_states.joystick_axis_states.get(&JoystickAxis(index, Axis::Y)) {
                        joystick.y_axis = val;
                    }
                    if let Some(&val) = self.raw_states.joystick_axis_states.get(&JoystickAxis(index, Axis::Z)) {
                        joystick.z_axis = val;
                    }
                    if let Some(&val) = self.raw_states.joystick_axis_states.get(&JoystickAxis(index, Axis::RX)) {
                        joystick.rx_axis = val;
                    }
                    if let Some(&val) = self.raw_states.joystick_axis_states.get(&JoystickAxis(index, Axis::RY)) {
                        joystick.ry_axis = val;
                    }
                    if let Some(&val) = self.raw_states.joystick_axis_states.get(&JoystickAxis(index, Axis::RZ)) {
                        joystick.rz_axis = val;
                    }
                    if let Some(&ref val) = self.raw_states.joystick_hatswitch_states.get(&JoystickHatSwitch(index)) {
                        let converted_val = match *val {
                            HatSwitch::Center => input::HatSwitch::Center,
                            HatSwitch::Up => input::HatSwitch::Up,
                            HatSwitch::UpRight => input::HatSwitch::UpRight,
                            HatSwitch::Right => input::HatSwitch::Right,
                            HatSwitch::DownRight => input::HatSwitch::DownRight,
                            HatSwitch::Down => input::HatSwitch::Down,
                            HatSwitch::DownLeft => input::HatSwitch::DownLeft,
                            HatSwitch::Left => input::HatSwitch::Left,
                            HatSwitch::UpLeft => input::HatSwitch::UpLeft,
                        };
                        joystick.hat_switch = converted_val;
                    }
                }
            }
        }
    }

    fn flush_input(&mut self) {
        self.raw_states.flush();
    }

    fn escape_key_pressed(&self) -> bool {
        self.escape_key_switch.pressed()
    }

    fn backtick_key_pressed(&self) -> bool {
        self.backtick_key_switch.pressed()
    }
}
<commit_msg>Add some standard keyboard key mappings<commit_after>use multiinput::manager::{RawInputManager, DeviceType, XInputInclude,DeviceStats};
use multiinput::event::{RawEvent, KeyId, State, MouseButton, Axis};
use multiinput::devices::HatSwitch;
use std::collections::HashMap;
use games::GameInput;
use input;
use super::{InputHandler, bool_switch};

pub struct MultiInput {
    pub raw_states: RawStates,
    raw_manager: RawInputManager,
    escape_key_switch: bool_switch::BoolSwitch,
    backtick_key_switch: bool_switch::BoolSwitch,
}

#[derive(Default)]
pub struct RawStates {
    pub key_states: HashMap<Key, bool>,
    pub mouse_button_states: HashMap<MouseAndButton, bool>,
    pub mouse_move_states: HashMap<usize, (i32, i32)>,
    pub joystick_button_states: HashMap<JoystickButton, bool>,
    pub joystick_axis_states: HashMap<JoystickAxis, f64>,
    pub joystick_hatswitch_states: HashMap<JoystickHatSwitch, HatSwitch>,
    device_stats: DeviceStats,
}

impl RawStates {
    pub fn flush(&mut self) {
        self.key_states.clear();
        self.mouse_button_states.clear();
        self.mouse_move_states.clear();
    }
}

#[derive(Eq, PartialEq, Hash)]
pub struct Key(pub usize, pub KeyId);
#[derive(Eq, PartialEq, Hash)]
pub struct MouseAndButton(pub usize, pub MouseButton);
#[derive(Eq, PartialEq, Hash)]
pub struct JoystickButton(pub usize, pub usize);
#[derive(Eq, PartialEq, Hash)]
pub struct JoystickAxis(pub usize, pub Axis);
#[derive(Eq, PartialEq, Hash)]
pub struct JoystickHatSwitch(pub usize);

impl MultiInput {
    pub fn new() -> Self {
        let mut raw_manager = RawInputManager::new().unwrap();
        raw_manager.register_devices(DeviceType::Keyboards);
        raw_manager.register_devices(DeviceType::Mice);
        raw_manager.register_devices(DeviceType::Joysticks(XInputInclude::True));
        let raw_states = RawStates{
            device_stats: raw_manager.get_device_stats(),
            ..Default::default()
            };
        MultiInput {
            raw_states: raw_states,
            raw_manager: raw_manager,
            escape_key_switch: bool_switch::BoolSwitch::new(),
            backtick_key_switch: bool_switch::BoolSwitch::new(),
        }
    }
}

impl InputHandler for MultiInput {
    fn receive_input(&mut self) {
        let raw_states = &mut self.raw_states;
        while let Some(event) = self.raw_manager.get_event() {
            match event {
                RawEvent::KeyboardEvent(num, key_id, state)
                    => {raw_states.key_states.insert(Key(num, key_id), state == State::Pressed);},
                RawEvent::MouseButtonEvent(num, mouse_button, state)
                    => {raw_states.mouse_button_states.insert(MouseAndButton(num, mouse_button), state == State::Pressed);},
                RawEvent::MouseMoveEvent(num, x, y)
                    => {raw_states.mouse_move_states.insert(num, (x, y));},
                RawEvent::JoystickButtonEvent(num, button_num, state)
                    => {raw_states.joystick_button_states.insert(JoystickButton(num, button_num), state == State::Pressed);},
                RawEvent::JoystickAxisEvent(num, axis, value)
                    => {raw_states.joystick_axis_states.insert(JoystickAxis(num, axis), value);},
                RawEvent::JoystickHatSwitchEvent(num, value)
                    => {raw_states.joystick_hatswitch_states.insert(JoystickHatSwitch(num), value);},
                _ => (),
            }
        }

        for index in 0..raw_states.device_stats.number_of_keyboards {
            if let Some(&state) = raw_states.key_states.get(&Key(index, KeyId::Escape)) {
                self.escape_key_switch.update_state(state);
            }
            else {
                self.escape_key_switch.clear_switch();
            }
        }
        for index in 0..raw_states.device_stats.number_of_keyboards {
            if let Some(&state) = raw_states.key_states.get(&Key(index, KeyId::BackTick)) {
                self.backtick_key_switch.update_state(state);
            }
            else {
                self.backtick_key_switch.clear_switch();
            }
        }
    }

    fn pass_on_input<'a>(&self, game_input: Option<&'a mut GameInput>) {
        if let Some(input) = game_input {
            if let Some(kbd) = input.get_kbd_inp() {
                for index in 0..self.raw_states.device_stats.number_of_keyboards {
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::Escape)) {
                        kbd.escape = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::Return)) {
                        kbd.ret = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::Backspace)) {
                        kbd.backspace = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::Space)) {
                        kbd.space = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::Left)) {
                        kbd.left = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::Right)) {
                        kbd.right = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::Up)) {
                        kbd.up = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::Down)) {
                        kbd.down = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::A)) {
                        kbd.a = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::B)) {
                        kbd.b = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::C)) {
                        kbd.c = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::D)) {
                        kbd.d = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::E)) {
                        kbd.e = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::F)) {
                        kbd.f = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::G)) {
                        kbd.g = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::H)) {
                        kbd.h = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::I)) {
                        kbd.i = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::J)) {
                        kbd.j = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::K)) {
                        kbd.k = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::L)) {
                        kbd.l = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::M)) {
                        kbd.m = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::N)) {
                        kbd.n = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::O)) {
                        kbd.o = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::P)) {
                        kbd.p = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::Q)) {
                        kbd.q = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::R)) {
                        kbd.r = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::S)) {
                        kbd.s = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::T)) {
                        kbd.t = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::U)) {
                        kbd.u = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::V)) {
                        kbd.v = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::W)) {
                        kbd.w = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::X)) {
                        kbd.x = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::Y)) {
                        kbd.y = val;
                    }
                    if let Some(&val) = self.raw_states.key_states.get(&Key(index, KeyId::Z)) {
                        kbd.z = val;
                    }
                }
            }

            if let Some(mouse) = input.get_mouse_inp() {
                mouse.movement = (0, 0);
                for index in 0..self.raw_states.device_stats.number_of_mice {
                    if let Some(&val) = self.raw_states.mouse_button_states.get(&MouseAndButton(index, MouseButton::Left)) {
                        mouse.left = val;
                    }
                    if let Some(&val) = self.raw_states.mouse_button_states.get(&MouseAndButton(index, MouseButton::Right)) {
                        mouse.left = val;
                    }
                    if let Some(&val) = self.raw_states.mouse_button_states.get(&MouseAndButton(index, MouseButton::Middle)) {
                        mouse.middle = val;
                    }
                    if let Some(&val) = self.raw_states.mouse_button_states.get(&MouseAndButton(index, MouseButton::Button4)) {
                        mouse.button4 = val;
                    }
                    if let Some(&val) = self.raw_states.mouse_button_states.get(&MouseAndButton(index, MouseButton::Button5)) {
                        mouse.button5 = val;
                    }
                    if let Some(&val) = self.raw_states.mouse_move_states.get(&index) {
                        mouse.movement = val;
                    }
                }
            }

            if let Some(joystick) = input.get_joystick_inp() {
                for index in 0..self.raw_states.device_stats.number_of_joysticks {
                    if let Some(&val) = self.raw_states.joystick_button_states.get(&JoystickButton(index, 0)) {
                        joystick.button_1 = val;
                    }
                    if let Some(&val) = self.raw_states.joystick_button_states.get(&JoystickButton(index, 1)) {
                        joystick.button_2 = val;
                    }
                    if let Some(&val) = self.raw_states.joystick_button_states.get(&JoystickButton(index, 2)) {
                        joystick.button_3 = val;
                    }
                    if let Some(&val) = self.raw_states.joystick_button_states.get(&JoystickButton(index, 3)) {
                        joystick.button_4 = val;
                    }
                    if let Some(&val) = self.raw_states.joystick_button_states.get(&JoystickButton(index, 4)) {
                        joystick.button_5 = val;
                    }
                    if let Some(&val) = self.raw_states.joystick_button_states.get(&JoystickButton(index, 5)) {
                        joystick.button_6 = val;
                    }
                    if let Some(&val) = self.raw_states.joystick_button_states.get(&JoystickButton(index, 6)) {
                        joystick.button_7 = val;
                    }
                    if let Some(&val) = self.raw_states.joystick_button_states.get(&JoystickButton(index, 7)) {
                        joystick.button_8 = val;
                    }
                    if let Some(&val) = self.raw_states.joystick_button_states.get(&JoystickButton(index, 8)) {
                        joystick.button_9 = val;
                    }
                    if let Some(&val) = self.raw_states.joystick_button_states.get(&JoystickButton(index, 9)) {
                        joystick.button_10 = val;
                    }
                    if let Some(&val) = self.raw_states.joystick_axis_states.get(&JoystickAxis(index, Axis::X)) {
                        joystick.x_axis = val;
                    }
                    if let Some(&val) = self.raw_states.joystick_axis_states.get(&JoystickAxis(index, Axis::Y)) {
                        joystick.y_axis = val;
                    }
                    if let Some(&val) = self.raw_states.joystick_axis_states.get(&JoystickAxis(index, Axis::Z)) {
                        joystick.z_axis = val;
                    }
                    if let Some(&val) = self.raw_states.joystick_axis_states.get(&JoystickAxis(index, Axis::RX)) {
                        joystick.rx_axis = val;
                    }
                    if let Some(&val) = self.raw_states.joystick_axis_states.get(&JoystickAxis(index, Axis::RY)) {
                        joystick.ry_axis = val;
                    }
                    if let Some(&val) = self.raw_states.joystick_axis_states.get(&JoystickAxis(index, Axis::RZ)) {
                        joystick.rz_axis = val;
                    }
                    if let Some(&ref val) = self.raw_states.joystick_hatswitch_states.get(&JoystickHatSwitch(index)) {
                        let converted_val = match *val {
                            HatSwitch::Center => input::HatSwitch::Center,
                            HatSwitch::Up => input::HatSwitch::Up,
                            HatSwitch::UpRight => input::HatSwitch::UpRight,
                            HatSwitch::Right => input::HatSwitch::Right,
                            HatSwitch::DownRight => input::HatSwitch::DownRight,
                            HatSwitch::Down => input::HatSwitch::Down,
                            HatSwitch::DownLeft => input::HatSwitch::DownLeft,
                            HatSwitch::Left => input::HatSwitch::Left,
                            HatSwitch::UpLeft => input::HatSwitch::UpLeft,
                        };
                        joystick.hat_switch = converted_val;
                    }
                }
            }
        }
    }

    fn flush_input(&mut self) {
        self.raw_states.flush();
    }

    fn escape_key_pressed(&self) -> bool {
        self.escape_key_switch.pressed()
    }

    fn backtick_key_pressed(&self) -> bool {
        self.backtick_key_switch.pressed()
    }
}
<|endoftext|>


<commit_before>// Higher level OpenCL wrappers.

use CL::*;
use CL::ll::*;
use error::check;

struct Platform {
    id: cl_platform_id
}

impl Platform {
    fn get_devices() -> ~[Device] {
        get_devices(self)
    }

    fn name() -> ~str {
        let mut size = 0;

        clGetPlatformInfo(self.id,
                          CL_PLATFORM_NAME,
                          0,
                          ptr::null(),
                          ptr::mut_addr_of(&size));

        let name = str::repeat(" ", size as uint);

        do str::as_buf(name) |p, len| {
            clGetPlatformInfo(self.id,
                              CL_PLATFORM_NAME,
                              len as libc::size_t,
                              p as *libc::c_void,
                              ptr::mut_addr_of(&size));
        };

        move name
    }
}

pub fn get_platforms() -> ~[Platform] {
    let mut num_platforms = 0;

    // TODO: Check result status
    clGetPlatformIDs(0, ptr::null(), ptr::addr_of(&num_platforms));

    let ids = vec::to_mut(vec::from_elem(num_platforms as uint,
                                         0 as cl_platform_id));

    do vec::as_imm_buf(ids) |ids, len| {
        clGetPlatformIDs(len as cl_uint,
                         ids, ptr::addr_of(&num_platforms))
    };

    do ids.map |id| { Platform { id: *id } }
}

struct Device {
    id: cl_device_id
}

pub fn get_devices(platform: Platform) -> ~[Device] {
    let mut num_devices = 0;

    clGetDeviceIDs(platform.id, CL_DEVICE_TYPE_GPU, 0, ptr::null(),
                   ptr::addr_of(&num_devices));

    let ids = vec::to_mut(vec::from_elem(num_devices as uint,
                                         0 as cl_device_id));
    do vec::as_imm_buf(ids) |ids, len| {
        clGetDeviceIDs(platform.id, CL_DEVICE_TYPE_GPU, len as cl_uint,
                       ids, ptr::addr_of(&num_devices));
    };

    do ids.map |id| { Device {id: *id }}
}

struct Context {
    ctx: cl_context,

    drop {
        clReleaseContext(self.ctx);
    }
}

pub fn create_context(device: Device) -> Context {
    // TODO: Support for multiple devices
    let mut errcode = 0;

    // TODO: Proper error messages
    let ctx = clCreateContext(ptr::null(), 1, ptr::addr_of(&device.id),
                              ptr::null(), ptr::null(), ptr::addr_of(&errcode));

    check(errcode, "Failed to create opencl context!");

    Context { ctx: ctx }
}

struct CommandQueue {
    cqueue: cl_command_queue,
    device: Device,

    drop {
        clReleaseCommandQueue(self.cqueue);
    }
}

pub fn create_commandqueue(ctx: & Context, device: Device) -> CommandQueue {
    let mut errcode = 0;

    let cqueue = clCreateCommandQueue(ctx.ctx, device.id, 0, ptr::addr_of(&errcode));

    check(errcode, "Failed to create command queue!");

    CommandQueue {
        cqueue: cqueue,
        device: device
    }
}

struct Buffer {
    buffer: cl_mem,
    size: int,

    drop {
        clReleaseMemObject(self.buffer);
    }
}

// TODO: How to make this function cleaner and nice
pub fn create_buffer(ctx: & Context, size: int, flags: cl_mem_flags) -> Buffer {
    let mut errcode = 0;

    let buffer = clCreateBuffer(ctx.ctx, flags, size as libc::size_t, ptr::null(),
                                ptr::addr_of(&errcode));

    check(errcode, "Failed to create buffer!");

    Buffer { buffer: buffer, size: size }
}

pub fn enqueue_write_buffer<T: KernelArg>(
    cqueue: & CommandQueue,
    buf: & Buffer,
    host_vector: T) unsafe
{
    let ret = clEnqueueWriteBuffer(
        cqueue.cqueue, buf.buffer, CL_TRUE, 0,
        buf.size as libc::size_t,
        host_vector.get_value(),
        0, ptr::null(), ptr::null());
    check(ret, "Failed to enqueue write buffer!");
}

pub fn enqueue_read_buffer<T: KernelArg>(
    cqueue: & CommandQueue,
    buf: & Buffer,
    host_vector: T) unsafe
{
    let ret = clEnqueueReadBuffer(
        cqueue.cqueue, buf.buffer, CL_TRUE, 0,
        buf.size as libc::size_t,
        host_vector.get_value(), 0, ptr::null(), ptr::null());

    check(ret, "Failed to enqueue read buffer!");
}

struct Program {
    prg: cl_program,

    drop {
        clReleaseProgram(self.prg);
    }
}

// TODO: Support multiple devices
pub fn create_program_with_binary(ctx: & Context, device: Device,
                                  binary_path: & Path) -> Program {
    let mut errcode = 0;
    let binary = match move io::read_whole_file_str(binary_path) {
        result::Ok(move binary) => move binary,
        Err(e) => fail fmt!("%?", e)
    };
    let program = do str::as_c_str(binary) |kernel_binary| {
        clCreateProgramWithBinary(ctx.ctx, 1, ptr::addr_of(&device.id),
                                  ptr::addr_of(&(binary.len() + 1)) as *libc::size_t,
                                  ptr::addr_of(&kernel_binary) as **libc::c_uchar,
                                  ptr::null(),
                                  ptr::addr_of(&errcode))
    };

    check(errcode, "Failed to create open cl program with binary!");

    Program { prg: program }
}

pub fn build_program(program: & Program, device: Device){
    let ret = clBuildProgram(program.prg, 1, ptr::addr_of(&device.id),
                             ptr::null(), ptr::null(), ptr::null());
    if ret != CL_SUCCESS as cl_int {
        let mut logv = ~"";
        for uint::range(0,1024*1204) |_i| {
            str::push_char(& mut logv, ' ');
        }
        do str::as_buf(logv) |logs, l| {
            let r = clGetProgramBuildInfo(program.prg, device.id, CL_PROGRAM_BUILD_LOG, l as libc::size_t, logs as *libc::c_void, ptr::null());
            check(r, "failed to get build info!");
        }
        info!("%s", logv);
        //io::println(logv);
        fail fmt!("Failure during program building! %?", ret)
    }
}

struct Kernel {
    kernel: cl_kernel,

    drop {
        clReleaseKernel(self.kernel);
    }
}

impl Kernel {
    fn set_arg<T: KernelArg>(i: uint, x: &T) {
        set_kernel_arg(&self, i as CL::cl_uint, x)
    }
}

pub fn create_kernel(program: & Program, kernel: & str) -> Kernel unsafe{
    let mut errcode = 0;
    let bytes = str::to_bytes(kernel);
    let kernel = clCreateKernel(program.prg, vec::raw::to_ptr(bytes) as *libc::c_char, ptr::addr_of(&errcode));

    check(errcode, "Failed to create kernel!");

    Kernel { kernel: kernel }
}

pub trait KernelArg{
    fn get_value() -> *libc::c_void;
}

pub fn set_kernel_arg<T: KernelArg>(kernel: & Kernel, position: cl_uint, arg: & T) unsafe{
    // TODO: How to set different argument types. Currently only support cl_mem
    let ret = clSetKernelArg(kernel.kernel, position,
                             sys::size_of::<cl_mem>() as libc::size_t,
                             arg.get_value());

    check(ret, "Failed to set kernel arg!");
}

pub fn enqueue_nd_range_kernel(cqueue: & CommandQueue, kernel: & Kernel, work_dim: cl_uint,
                               _global_work_offset: int, global_work_size: int,
                               local_work_size: int) unsafe{
    let ret = clEnqueueNDRangeKernel(cqueue.cqueue, kernel.kernel, work_dim,
                                     // ptr::addr_of(&global_work_offset) as *libc::size_t,
                                     ptr::null(),
                                     ptr::addr_of(&global_work_size) as *libc::size_t,
                                     ptr::addr_of(&local_work_size) as *libc::size_t,
                                     0, ptr::null(), ptr::null());
    check(ret, "Failed to enqueue nd range kernel!");
}

pub impl<T> &~[T]: KernelArg {
    fn get_value() -> *libc::c_void {
        do vec::as_imm_buf(*self) |p, _len| {
            p as *libc::c_void
        }
    }
}

pub impl<T> &~[mut T]: KernelArg {
    fn get_value() -> *libc::c_void {
        do vec::as_imm_buf(*self) |p, _len| {
            p as *libc::c_void
        }
    }
}

pub impl Buffer: KernelArg{
    fn get_value() -> *libc::c_void{
        ptr::addr_of(&self.buffer) as *libc::c_void
    }
}

pub impl *libc::c_void: KernelArg{
    fn get_value() -> *libc::c_void {
        self
    }
}

/**
This packages an OpenCL context, a device, and a command queue to
simplify handling all these structures.
*/
struct ComputeContext {
    ctx: Context,
    device: Device,
    q: CommandQueue
}

pub fn create_compute_context() -> @ComputeContext {
    // Enumerate all platforms until we find a device that works.

    for get_platforms().each |p| {
        let devices = p.get_devices();
        if devices.len() > 0 {
            let device = devices[0];
            let ctx = create_context(device);
            let q = create_commandqueue(&ctx, device);
            return @ComputeContext {
                ctx: move ctx,
                device: move device,
                q: move q
            }
        }
    }
    fail ~"Could not find an acceptable device."
}<commit_msg>Simpler program build interface.<commit_after>// Higher level OpenCL wrappers.

use CL::*;
use CL::ll::*;
use error::check;

struct Platform {
    id: cl_platform_id
}

impl Platform {
    fn get_devices() -> ~[Device] {
        get_devices(self)
    }

    fn name() -> ~str {
        let mut size = 0;

        clGetPlatformInfo(self.id,
                          CL_PLATFORM_NAME,
                          0,
                          ptr::null(),
                          ptr::mut_addr_of(&size));

        let name = str::repeat(" ", size as uint);

        do str::as_buf(name) |p, len| {
            clGetPlatformInfo(self.id,
                              CL_PLATFORM_NAME,
                              len as libc::size_t,
                              p as *libc::c_void,
                              ptr::mut_addr_of(&size));
        };

        move name
    }
}

pub fn get_platforms() -> ~[Platform] {
    let mut num_platforms = 0;

    // TODO: Check result status
    clGetPlatformIDs(0, ptr::null(), ptr::addr_of(&num_platforms));

    let ids = vec::to_mut(vec::from_elem(num_platforms as uint,
                                         0 as cl_platform_id));

    do vec::as_imm_buf(ids) |ids, len| {
        clGetPlatformIDs(len as cl_uint,
                         ids, ptr::addr_of(&num_platforms))
    };

    do ids.map |id| { Platform { id: *id } }
}

struct Device {
    id: cl_device_id
}

pub fn get_devices(platform: Platform) -> ~[Device] {
    let mut num_devices = 0;

    clGetDeviceIDs(platform.id, CL_DEVICE_TYPE_GPU, 0, ptr::null(),
                   ptr::addr_of(&num_devices));

    let ids = vec::to_mut(vec::from_elem(num_devices as uint,
                                         0 as cl_device_id));
    do vec::as_imm_buf(ids) |ids, len| {
        clGetDeviceIDs(platform.id, CL_DEVICE_TYPE_GPU, len as cl_uint,
                       ids, ptr::addr_of(&num_devices));
    };

    do ids.map |id| { Device {id: *id }}
}

struct Context {
    ctx: cl_context,

    drop {
        clReleaseContext(self.ctx);
    }
}

pub fn create_context(device: Device) -> Context {
    // TODO: Support for multiple devices
    let mut errcode = 0;

    // TODO: Proper error messages
    let ctx = clCreateContext(ptr::null(), 1, ptr::addr_of(&device.id),
                              ptr::null(), ptr::null(), ptr::addr_of(&errcode));

    check(errcode, "Failed to create opencl context!");

    Context { ctx: ctx }
}

struct CommandQueue {
    cqueue: cl_command_queue,
    device: Device,

    drop {
        clReleaseCommandQueue(self.cqueue);
    }
}

pub fn create_commandqueue(ctx: & Context, device: Device) -> CommandQueue {
    let mut errcode = 0;

    let cqueue = clCreateCommandQueue(ctx.ctx, device.id, 0, ptr::addr_of(&errcode));

    check(errcode, "Failed to create command queue!");

    CommandQueue {
        cqueue: cqueue,
        device: device
    }
}

struct Buffer {
    buffer: cl_mem,
    size: int,

    drop {
        clReleaseMemObject(self.buffer);
    }
}

// TODO: How to make this function cleaner and nice
pub fn create_buffer(ctx: & Context, size: int, flags: cl_mem_flags) -> Buffer {
    let mut errcode = 0;

    let buffer = clCreateBuffer(ctx.ctx, flags, size as libc::size_t, ptr::null(),
                                ptr::addr_of(&errcode));

    check(errcode, "Failed to create buffer!");

    Buffer { buffer: buffer, size: size }
}

pub fn enqueue_write_buffer<T: KernelArg>(
    cqueue: & CommandQueue,
    buf: & Buffer,
    host_vector: T) unsafe
{
    let ret = clEnqueueWriteBuffer(
        cqueue.cqueue, buf.buffer, CL_TRUE, 0,
        buf.size as libc::size_t,
        host_vector.get_value(),
        0, ptr::null(), ptr::null());
    check(ret, "Failed to enqueue write buffer!");
}

pub fn enqueue_read_buffer<T: KernelArg>(
    cqueue: & CommandQueue,
    buf: & Buffer,
    host_vector: T) unsafe
{
    let ret = clEnqueueReadBuffer(
        cqueue.cqueue, buf.buffer, CL_TRUE, 0,
        buf.size as libc::size_t,
        host_vector.get_value(), 0, ptr::null(), ptr::null());

    check(ret, "Failed to enqueue read buffer!");
}

struct Program {
    prg: cl_program,

    drop {
        clReleaseProgram(self.prg);
    }
}

pub impl Program {
    fn build(&self, device: Device) {
        build_program(self, device);
    }
}

// TODO: Support multiple devices
pub fn create_program_with_binary(ctx: & Context, device: Device,
                                  binary_path: & Path) -> Program {
    let mut errcode = 0;
    let binary = match move io::read_whole_file_str(binary_path) {
        result::Ok(move binary) => move binary,
        Err(e) => fail fmt!("%?", e)
    };
    let program = do str::as_c_str(binary) |kernel_binary| {
        clCreateProgramWithBinary(ctx.ctx, 1, ptr::addr_of(&device.id),
                                  ptr::addr_of(&(binary.len() + 1)) as *libc::size_t,
                                  ptr::addr_of(&kernel_binary) as **libc::c_uchar,
                                  ptr::null(),
                                  ptr::addr_of(&errcode))
    };

    check(errcode, "Failed to create open cl program with binary!");

    Program { prg: program }
}

pub fn build_program(program: & Program, device: Device) {
    let ret = clBuildProgram(program.prg, 1, ptr::addr_of(&device.id),
                             ptr::null(), ptr::null(), ptr::null());
    if ret != CL_SUCCESS as cl_int {
        let mut logv = ~"";
        for uint::range(0,1024*1204) |_i| {
            str::push_char(& mut logv, ' ');
        }
        do str::as_buf(logv) |logs, l| {
            let r = clGetProgramBuildInfo(program.prg, device.id, CL_PROGRAM_BUILD_LOG, l as libc::size_t, logs as *libc::c_void, ptr::null());
            check(r, "failed to get build info!");
        }
        info!("%s", logv);
        //io::println(logv);
        fail fmt!("Failure during program building! %?", ret)
    }
}

struct Kernel {
    kernel: cl_kernel,

    drop {
        clReleaseKernel(self.kernel);
    }
}

impl Kernel {
    fn set_arg<T: KernelArg>(i: uint, x: &T) {
        set_kernel_arg(&self, i as CL::cl_uint, x)
    }
}

pub fn create_kernel(program: & Program, kernel: & str) -> Kernel unsafe{
    let mut errcode = 0;
    let bytes = str::to_bytes(kernel);
    let kernel = clCreateKernel(program.prg, vec::raw::to_ptr(bytes) as *libc::c_char, ptr::addr_of(&errcode));

    check(errcode, "Failed to create kernel!");

    Kernel { kernel: kernel }
}

pub trait KernelArg{
    fn get_value() -> *libc::c_void;
}

pub fn set_kernel_arg<T: KernelArg>(kernel: & Kernel, position: cl_uint, arg: & T) unsafe{
    // TODO: How to set different argument types. Currently only support cl_mem
    let ret = clSetKernelArg(kernel.kernel, position,
                             sys::size_of::<cl_mem>() as libc::size_t,
                             arg.get_value());

    check(ret, "Failed to set kernel arg!");
}

pub fn enqueue_nd_range_kernel(cqueue: & CommandQueue, kernel: & Kernel, work_dim: cl_uint,
                               _global_work_offset: int, global_work_size: int,
                               local_work_size: int) unsafe{
    let ret = clEnqueueNDRangeKernel(cqueue.cqueue, kernel.kernel, work_dim,
                                     // ptr::addr_of(&global_work_offset) as *libc::size_t,
                                     ptr::null(),
                                     ptr::addr_of(&global_work_size) as *libc::size_t,
                                     ptr::addr_of(&local_work_size) as *libc::size_t,
                                     0, ptr::null(), ptr::null());
    check(ret, "Failed to enqueue nd range kernel!");
}

pub impl<T> &~[T]: KernelArg {
    fn get_value() -> *libc::c_void {
        do vec::as_imm_buf(*self) |p, _len| {
            p as *libc::c_void
        }
    }
}

pub impl<T> &~[mut T]: KernelArg {
    fn get_value() -> *libc::c_void {
        do vec::as_imm_buf(*self) |p, _len| {
            p as *libc::c_void
        }
    }
}

pub impl Buffer: KernelArg{
    fn get_value() -> *libc::c_void{
        ptr::addr_of(&self.buffer) as *libc::c_void
    }
}

pub impl *libc::c_void: KernelArg{
    fn get_value() -> *libc::c_void {
        self
    }
}

/**
This packages an OpenCL context, a device, and a command queue to
simplify handling all these structures.
*/
struct ComputeContext {
    ctx: Context,
    device: Device,
    q: CommandQueue
}

impl ComputeContext {
    fn create_program_with_source(src: &str) -> Program {
        do str::as_c_str(src) |src| {
            let mut status = CL_SUCCESS as cl_int;
            let program = clCreateProgramWithSource(
                self.ctx.ctx,
                1,
                ptr::addr_of(&src),
                ptr::null(),
                ptr::addr_of(&status));
            check(status, "Could not create program");

            Program { prg: program }
        }
    }
}

pub fn create_compute_context() -> @ComputeContext {
    // Enumerate all platforms until we find a device that works.

    for get_platforms().each |p| {
        let devices = p.get_devices();
        if devices.len() > 0 {
            let device = devices[0];
            let ctx = create_context(device);
            let q = create_commandqueue(&ctx, device);
            return @ComputeContext {
                ctx: move ctx,
                device: move device,
                q: move q
            }
        }
    }
    fail ~"Could not find an acceptable device."
}

#[cfg(test)]
mod test {
    #[test]
    fn program_build() {
        let src = "__kernel void test(__global int *i) { \
                       *i += 1; \
                   }";
        let ctx = create_compute_context();
        let prog = ctx.create_program_with_source(src);
        prog.build(ctx.device);
    }
}<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::io;
use std::net::{Ipv4Addr, SocketAddr};
use std::rc::{Rc, Weak};
use mio::{Event, PollOpt, Ready, Token};
use mio::net::TcpStream;

use super::client::Client;
use super::connection::{self, Connection, ConnectionId};
use super::ipv4_header::IPv4Header;
use super::ipv4_packet::{IPv4Packet, MAX_PACKET_LENGTH};
use super::packetizer::Packetizer;
use super::selector::Selector;
use super::stream_buffer::StreamBuffer;
use super::tcp_header::TCPHeader;
use super::transport_header::TransportHeader;

const TAG: &'static str = "TCPConnection";

enum TCPState {
    Init,
    SynSent,
//    SynReceived,
    Established,
    CloseWait,
    LastAck,
}

struct TCPConnection {
    id: ConnectionId,
    client: Weak<RefCell<Client>>,
    stream: TcpStream,
    token: Token,
    client_to_network: StreamBuffer,
    network_to_client: Packetizer,
    closed: bool,
    state: TCPState,
    syn_sequence_number: u32,
    sequence_number: u32,
    acknowledgement_number: u32,
    their_acknowledgement_number: u32,
    client_window: u16,
    remote_closed: bool,
}

impl TCPConnection {
    pub fn new(selector: &mut Selector, id: ConnectionId, client: Weak<RefCell<Client>>, ipv4_header: &IPv4Header, transport_header: &TransportHeader) -> io::Result<Rc<RefCell<Self>>> {
        let stream = TCPConnection::create_stream(&id)?;

        if let TransportHeader::TCP(ref tcp_header) = *transport_header {
            // shrink the TCP options to pass a minimal refrence header to the packetizer
            let mut shrinked_tcp_header_raw = [0u8; 20];
            shrinked_tcp_header_raw.copy_from_slice(&tcp_header.raw()[..20]);
            let mut shrinked_tcp_header_data = tcp_header.data().clone();
            {
                let mut shrinked_tcp_header = shrinked_tcp_header_data.bind_mut(&mut shrinked_tcp_header_raw);
                shrinked_tcp_header.shrink_options();
                assert_eq!(20, shrinked_tcp_header.header_length());
            }

            let shrinked_transport_header = shrinked_tcp_header_data.bind(&shrinked_tcp_header_raw).into();

            let packetizer = Packetizer::new(&ipv4_header, &shrinked_transport_header);

            let rc = Rc::new(RefCell::new(Self {
                id: id,
                client: client,
                stream: stream,
                token: Token(0), // default value, will be set afterwards
                client_to_network: StreamBuffer::new(4 * MAX_PACKET_LENGTH),
                network_to_client: packetizer,
                closed: false,
                state: TCPState::Init,
                syn_sequence_number: 0,
                sequence_number: 0,
                acknowledgement_number: 0,
                their_acknowledgement_number: 0,
                client_window: 0,
                remote_closed: false,
            }));

            {
                let rc_clone = rc.clone();
                let handler = move |selector: &mut Selector, ready| {
                    let mut self_ref = rc_clone.borrow_mut();
                    self_ref.on_ready(selector, ready);
                };
                let mut self_ref = rc.borrow_mut();
                let token = selector.register(&self_ref.stream, handler, Ready::readable(), PollOpt::level())?;
                self_ref.token = token;
            }
            Ok(rc)
        } else {
            panic!("Not a TCP header");
        }
    }

    fn create_stream(id: &ConnectionId) -> io::Result<TcpStream> {
        let rewritten_destination = connection::rewritten_destination(id.destination_ip(), id.destination_port()).into();
        TcpStream::connect(&rewritten_destination)
    }

    fn process_send(&mut self, selector: &mut Selector) {
        // TODO
    }

    fn process_receive(&mut self, selector: &mut Selector) {
        // TODO
    }

    fn update_interests(&mut self, selector: &mut Selector) {
        if !self.closed {
            let mut ready = Ready::empty();
            if self.may_read() {
                ready = ready | Ready::readable()
            }
            if self.may_write() {
                ready = ready | Ready::writable()
            }
            selector.reregister(&self.stream, self.token, ready, PollOpt::level()).expect("Cannot register on poll");
        }
    }

    fn may_read(&self) -> bool {
        // TODO
        false
    }

    fn may_write(&self) -> bool {
        // TODO
        false
    }

    fn on_ready(&mut self, selector: &mut Selector, event: Event) {
        assert!(!self.closed);
        let ready = event.readiness();
        if ready.is_writable() {
            self.process_send(selector);
        }
        if !self.closed && ready.is_readable() {
            self.process_receive(selector);
        }
        if !self.closed {
            self.update_interests(selector);
        }
    }
}
<commit_msg>Implement TCPConnection.process_send()<commit_after>use std::cell::RefCell;
use std::io;
use std::net::{Ipv4Addr, SocketAddr};
use std::rc::{Rc, Weak};
use mio::{Event, PollOpt, Ready, Token};
use mio::net::TcpStream;

use super::client::Client;
use super::connection::{self, Connection, ConnectionId};
use super::ipv4_header::IPv4Header;
use super::ipv4_packet::{IPv4Packet, MAX_PACKET_LENGTH};
use super::packetizer::Packetizer;
use super::selector::Selector;
use super::stream_buffer::StreamBuffer;
use super::tcp_header::TCPHeader;
use super::transport_header::TransportHeader;

const TAG: &'static str = "TCPConnection";

enum TCPState {
    Init,
    SynSent,
//    SynReceived,
    Established,
    CloseWait,
    LastAck,
}

struct TCPConnection {
    id: ConnectionId,
    client: Weak<RefCell<Client>>,
    stream: TcpStream,
    token: Token,
    client_to_network: StreamBuffer,
    network_to_client: Packetizer,
    closed: bool,
    state: TCPState,
    syn_sequence_number: u32,
    sequence_number: u32,
    acknowledgement_number: u32,
    their_acknowledgement_number: u32,
    client_window: u16,
    remote_closed: bool,
}

impl TCPConnection {
    pub fn new(selector: &mut Selector, id: ConnectionId, client: Weak<RefCell<Client>>, ipv4_header: &IPv4Header, transport_header: &TransportHeader) -> io::Result<Rc<RefCell<Self>>> {
        let stream = TCPConnection::create_stream(&id)?;

        if let TransportHeader::TCP(ref tcp_header) = *transport_header {
            // shrink the TCP options to pass a minimal refrence header to the packetizer
            let mut shrinked_tcp_header_raw = [0u8; 20];
            shrinked_tcp_header_raw.copy_from_slice(&tcp_header.raw()[..20]);
            let mut shrinked_tcp_header_data = tcp_header.data().clone();
            {
                let mut shrinked_tcp_header = shrinked_tcp_header_data.bind_mut(&mut shrinked_tcp_header_raw);
                shrinked_tcp_header.shrink_options();
                assert_eq!(20, shrinked_tcp_header.header_length());
            }

            let shrinked_transport_header = shrinked_tcp_header_data.bind(&shrinked_tcp_header_raw).into();

            let packetizer = Packetizer::new(&ipv4_header, &shrinked_transport_header);

            let rc = Rc::new(RefCell::new(Self {
                id: id,
                client: client,
                stream: stream,
                token: Token(0), // default value, will be set afterwards
                client_to_network: StreamBuffer::new(4 * MAX_PACKET_LENGTH),
                network_to_client: packetizer,
                closed: false,
                state: TCPState::Init,
                syn_sequence_number: 0,
                sequence_number: 0,
                acknowledgement_number: 0,
                their_acknowledgement_number: 0,
                client_window: 0,
                remote_closed: false,
            }));

            {
                let rc_clone = rc.clone();
                let handler = move |selector: &mut Selector, ready| {
                    let mut self_ref = rc_clone.borrow_mut();
                    self_ref.on_ready(selector, ready);
                };
                let mut self_ref = rc.borrow_mut();
                let token = selector.register(&self_ref.stream, handler, Ready::readable(), PollOpt::level())?;
                self_ref.token = token;
            }
            Ok(rc)
        } else {
            panic!("Not a TCP header");
        }
    }

    fn create_stream(id: &ConnectionId) -> io::Result<TcpStream> {
        let rewritten_destination = connection::rewritten_destination(id.destination_ip(), id.destination_port()).into();
        TcpStream::connect(&rewritten_destination)
    }

    fn close(&mut self, selector: &mut Selector) {

    }

    fn process_send(&mut self, selector: &mut Selector) {
        match self.client_to_network.write_to(&mut self.stream) {
            Ok(w) => if w == 0 {
                self.close(selector);
            },
            Err(err) => {
                error!(target: TAG, "{} Cannot write: {}", self.id, err);
                self.reset_connection(selector);
            }
        }
    }

    fn process_receive(&mut self, selector: &mut Selector) {
        // TODO
    }

    fn reset_connection(&mut self, selector: &mut Selector) {
        // TODO
    }

    fn update_interests(&mut self, selector: &mut Selector) {
        if !self.closed {
            let mut ready = Ready::empty();
            if self.may_read() {
                ready = ready | Ready::readable()
            }
            if self.may_write() {
                ready = ready | Ready::writable()
            }
            selector.reregister(&self.stream, self.token, ready, PollOpt::level()).expect("Cannot register on poll");
        }
    }

    fn may_read(&self) -> bool {
        // TODO
        false
    }

    fn may_write(&self) -> bool {
        !self.client_to_network.is_empty()
    }

    fn on_ready(&mut self, selector: &mut Selector, event: Event) {
        assert!(!self.closed);
        let ready = event.readiness();
        if ready.is_writable() {
            self.process_send(selector);
        }
        if !self.closed && ready.is_readable() {
            self.process_receive(selector);
        }
        if !self.closed {
            self.update_interests(selector);
        }
    }
}

impl Connection for TCPConnection {
    fn id(&self) -> &ConnectionId {
        &self.id
    }

    fn send_to_network(&mut self, selector: &mut Selector, ipv4_packet: &IPv4Packet) {
        // TODO
    }

    fn disconnect(&mut self, selector: &mut Selector) {
        info!(target: TAG, "{} Close", self.id);
        selector.deregister(&self.stream, self.token).unwrap();
        // socket will be closed by RAII
    }

    fn is_expired(&self) -> bool {
        // no external timeout expiration
        false
    }
}
<|endoftext|>


<commit_before>//! Generates descriptors structure for unstable feature from Unstable Book
use std::fmt::Write;
use std::path::{Path, PathBuf};

use walkdir::WalkDir;
use xshell::{cmd, read_file};

use crate::codegen::{ensure_file_contents, project_root, reformat, Result};

pub(crate) fn generate_lint_completions() -> Result<()> {
    if !Path::new("./target/rust").exists() {
        cmd!("git clone --depth=1 https://github.com/rust-lang/rust ./target/rust").run()?;
    }

    let mut contents = String::from("use crate::completions::attribute::LintCompletion;\n\n");
    generate_descriptor(&mut contents, "./target/rust/src/doc/unstable-book/src".into())?;
    contents.push('\n');

    cmd!("curl http://rust-lang.github.io/rust-clippy/master/lints.json --output ./target/clippy_lints.json").run()?;
    generate_descriptor_clippy(&mut contents, &Path::new("./target/clippy_lints.json"))?;
    let contents = reformat(&contents)?;

    let destination =
        project_root().join("crates/ide_completion/src/generated_lint_completions.rs");
    ensure_file_contents(destination.as_path(), &contents)?;

    Ok(())
}

fn generate_descriptor(buf: &mut String, src_dir: PathBuf) -> Result<()> {
    buf.push_str(r#"pub(super) const FEATURES: &[LintCompletion] = &["#);
    buf.push('\n');
    ["language-features", "library-features"]
        .iter()
        .flat_map(|it| WalkDir::new(src_dir.join(it)))
        .filter_map(|e| e.ok())
        .filter(|entry| {
            // Get all `.md ` files
            entry.file_type().is_file() && entry.path().extension().unwrap_or_default() == "md"
        })
        .for_each(|entry| {
            let path = entry.path();
            let feature_ident = path.file_stem().unwrap().to_str().unwrap().replace("-", "_");
            let doc = read_file(path).unwrap();

            push_lint_completion(buf, &feature_ident, &doc);
        });
    buf.push_str("];\n");
    Ok(())
}

#[derive(Default)]
struct ClippyLint {
    help: String,
    id: String,
}

fn generate_descriptor_clippy(buf: &mut String, path: &Path) -> Result<()> {
    let file_content = read_file(path)?;
    let mut clippy_lints: Vec<ClippyLint> = vec![];

    for line in file_content.lines().map(|line| line.trim()) {
        if line.starts_with(r#""id":"#) {
            let clippy_lint = ClippyLint {
                id: line
                    .strip_prefix(r#""id": ""#)
                    .expect("should be prefixed by id")
                    .strip_suffix(r#"","#)
                    .expect("should be suffixed by comma")
                    .into(),
                help: String::new(),
            };
            clippy_lints.push(clippy_lint)
        } else if line.starts_with(r#""What it does":"#) {
            // Typical line to strip: "What is doest": "Here is my useful content",
            let prefix_to_strip = r#""What it does": ""#;
            let suffix_to_strip = r#"","#;

            let clippy_lint = clippy_lints.last_mut().expect("clippy lint must already exist");
            clippy_lint.help = line
                .strip_prefix(prefix_to_strip)
                .expect("should be prefixed by what it does")
                .strip_suffix(suffix_to_strip)
                .expect("should be suffixed by comma")
                .into();
        }
    }

    buf.push_str(r#"pub(super) const CLIPPY_LINTS: &[LintCompletion] = &["#);
    buf.push('\n');
    clippy_lints.into_iter().for_each(|clippy_lint| {
        let lint_ident = format!("clippy::{}", clippy_lint.id);
        let doc = clippy_lint.help;
        push_lint_completion(buf, &lint_ident, &doc);
    });

    buf.push_str("];\n");

    Ok(())
}

fn push_lint_completion(buf: &mut String, label: &str, description: &str) {
    writeln!(
        buf,
        r###"    LintCompletion {{
        label: "{}",
        description: r##"{}"##
    }},"###,
        label, description
    )
    .unwrap();
}
<commit_msg>Minor<commit_after>//! Generates descriptors structure for unstable feature from Unstable Book
use std::fmt::Write;
use std::path::{Path, PathBuf};

use walkdir::WalkDir;
use xshell::{cmd, read_file};

use crate::codegen::{ensure_file_contents, project_root, reformat, Result};

pub(crate) fn generate_lint_completions() -> Result<()> {
    if !project_root().join("./target/rust").exists() {
        cmd!("git clone --depth=1 https://github.com/rust-lang/rust ./target/rust").run()?;
    }

    let mut contents = String::from("use crate::completions::attribute::LintCompletion;\n\n");
    generate_descriptor(&mut contents, "./target/rust/src/doc/unstable-book/src".into())?;
    contents.push('\n');

    cmd!("curl http://rust-lang.github.io/rust-clippy/master/lints.json --output ./target/clippy_lints.json").run()?;
    generate_descriptor_clippy(&mut contents, &Path::new("./target/clippy_lints.json"))?;
    let contents = reformat(&contents)?;

    let destination =
        project_root().join("crates/ide_completion/src/generated_lint_completions.rs");
    ensure_file_contents(destination.as_path(), &contents)?;

    Ok(())
}

fn generate_descriptor(buf: &mut String, src_dir: PathBuf) -> Result<()> {
    buf.push_str(r#"pub(super) const FEATURES: &[LintCompletion] = &["#);
    buf.push('\n');
    ["language-features", "library-features"]
        .iter()
        .flat_map(|it| WalkDir::new(src_dir.join(it)))
        .filter_map(|e| e.ok())
        .filter(|entry| {
            // Get all `.md ` files
            entry.file_type().is_file() && entry.path().extension().unwrap_or_default() == "md"
        })
        .for_each(|entry| {
            let path = entry.path();
            let feature_ident = path.file_stem().unwrap().to_str().unwrap().replace("-", "_");
            let doc = read_file(path).unwrap();

            push_lint_completion(buf, &feature_ident, &doc);
        });
    buf.push_str("];\n");
    Ok(())
}

#[derive(Default)]
struct ClippyLint {
    help: String,
    id: String,
}

fn generate_descriptor_clippy(buf: &mut String, path: &Path) -> Result<()> {
    let file_content = read_file(path)?;
    let mut clippy_lints: Vec<ClippyLint> = vec![];

    for line in file_content.lines().map(|line| line.trim()) {
        if line.starts_with(r#""id":"#) {
            let clippy_lint = ClippyLint {
                id: line
                    .strip_prefix(r#""id": ""#)
                    .expect("should be prefixed by id")
                    .strip_suffix(r#"","#)
                    .expect("should be suffixed by comma")
                    .into(),
                help: String::new(),
            };
            clippy_lints.push(clippy_lint)
        } else if line.starts_with(r#""What it does":"#) {
            // Typical line to strip: "What is doest": "Here is my useful content",
            let prefix_to_strip = r#""What it does": ""#;
            let suffix_to_strip = r#"","#;

            let clippy_lint = clippy_lints.last_mut().expect("clippy lint must already exist");
            clippy_lint.help = line
                .strip_prefix(prefix_to_strip)
                .expect("should be prefixed by what it does")
                .strip_suffix(suffix_to_strip)
                .expect("should be suffixed by comma")
                .into();
        }
    }

    buf.push_str(r#"pub(super) const CLIPPY_LINTS: &[LintCompletion] = &["#);
    buf.push('\n');
    clippy_lints.into_iter().for_each(|clippy_lint| {
        let lint_ident = format!("clippy::{}", clippy_lint.id);
        let doc = clippy_lint.help;
        push_lint_completion(buf, &lint_ident, &doc);
    });

    buf.push_str("];\n");

    Ok(())
}

fn push_lint_completion(buf: &mut String, label: &str, description: &str) {
    writeln!(
        buf,
        r###"    LintCompletion {{
        label: "{}",
        description: r##"{}"##
    }},"###,
        label, description
    )
    .unwrap();
}
<|endoftext|>


<commit_before>use std::fmt;
use std::thread::sleep;
use std::time::Duration;

use super::byteorder::{BigEndian, ByteOrder};
use super::sdl2;
use super::sdl2::pixels::Color;
use super::sdl2::rect::Point;
use super::sdl2::event::Event;
use super::sdl2::keyboard::Keycode;

// Size of the memory map of a CHIP-8 interpreter is 4kb.
const RAM_SIZE: usize = 4096;

// Where fonts are stored in interpreter memory.
const FONT_OFFSET: usize = 0;

// Font size constants.
const CHARACTER_SIZE: usize = 5;
const CHARACTER_COUNT: usize = 16;

// Display size parameters.
const DISPLAY_WIDTH: usize = 64;
const DISPLAY_HEIGHT: usize = 32;
const DISPLAY_SIZE: usize = DISPLAY_WIDTH * DISPLAY_HEIGHT;

// Wait for the duration it takes for an instruction to execute.
const INPUT_WAIT_DELAY: u64 = 2;

// Memory map constraints.
pub const START_RESERVED: usize = 0x000;
pub const END_RESERVED: usize = 0x200;
pub const END_PROGRAM_SPACE: usize = 0xFFF;

pub struct Interconnect {
    sdl_context: sdl2::Sdl,
    video_subsystem: sdl2::VideoSubsystem,
    renderer: sdl2::render::Renderer<'static>,
    event_pump: sdl2::EventPump,

    // The current keyboard input state.
    pub input_state: [bool; 0xF],

    // Used for input waiting.
    pub input_dirty: bool,

    // Last key pressed.
    pub last_input: u8,

    // The CPU reads this value before executing instructions, and when set to
    // true the CPU will stop executing.
    pub halt: bool,

    // RAM used by the application. 4k in size.
    pub ram: Vec<u8>,

    // 64x32 buffer for the application to write to.
    pub display: Vec<u8>,
}

impl Interconnect {
    pub fn new(rom: Vec<u8>) -> Interconnect {
        let mut ram = vec![0; RAM_SIZE];

        // Dump the rom into ram starting at the start of the program space.
        for i in 0..rom.len() {
            ram[i + END_RESERVED] = rom[i];
        }

        // Setup SDL for graphics and audio.
        let sdl_context = sdl2::init().unwrap();
        let video_subsystem = sdl_context.video().unwrap();
        let window = video_subsystem.window("Notch", 640, 320)
            .position_centered()
            .build()
            .unwrap();

        // Create a renderer that is scaled up a bit. The CHIP-8 display is
        // very small for today's standards.
        let mut renderer = window.renderer().build().unwrap();
        renderer.set_scale(10.0, 10.0);

        // Clear the screen to black.
        renderer.set_draw_color(Color::RGB(0, 0, 0));
        renderer.clear();
        renderer.present();

        let mut event_pump = sdl_context.event_pump().unwrap();

        let mut interconnect = Interconnect {
            sdl_context: sdl_context,
            video_subsystem: video_subsystem,
            renderer: renderer,
            event_pump: event_pump,
            input_state: [false; 0xF],
            input_dirty: false,
            last_input: 0,
            halt: false,
            ram: ram,
            display: vec![0; DISPLAY_SIZE],
        };
        interconnect.dump_fonts();
        interconnect
    }

    fn set_input(&mut self, key: u8, down: bool) {
        self.input_state[key as usize] = down;
        self.last_input = key;
        self.input_dirty = true;
    }

    /// Get input events from SDL and set the input state.
    pub fn handle_input(&mut self) {
        // Collect the events from the iterator ahead of time so we are not
        // borrowing when we need to set the input state.
        let events: Vec<Event> = self.event_pump.poll_iter().collect();

        for event in events {
            match event {
                Event::Quit {..} => {
                    // Detect close button or escape button events.
                    // The interpreter is then signaled to halt and stop
                    // executing code.
                    self.halt = true;
                },

                // Keyboard to CHIP-8 keycode mapping.
                Event::KeyDown { keycode: Some(Keycode::Num0), .. } => { self.set_input(0x0, true ); },
                Event::KeyUp   { keycode: Some(Keycode::Num0), .. } => { self.set_input(0x0, false); },
                Event::KeyDown { keycode: Some(Keycode::Num1), .. } => { self.set_input(0x1, true ); },
                Event::KeyUp   { keycode: Some(Keycode::Num1), .. } => { self.set_input(0x1, false); },
                Event::KeyDown { keycode: Some(Keycode::Num2), .. } => { self.set_input(0x2, true ); },
                Event::KeyUp   { keycode: Some(Keycode::Num2), .. } => { self.set_input(0x2, false); },
                Event::KeyDown { keycode: Some(Keycode::Num3), .. } => { self.set_input(0x3, true ); },
                Event::KeyUp   { keycode: Some(Keycode::Num3), .. } => { self.set_input(0x3, false); },
                Event::KeyDown { keycode: Some(Keycode::Num4), .. } => { self.set_input(0x4, true ); },
                Event::KeyUp   { keycode: Some(Keycode::Num4), .. } => { self.set_input(0x4, false); },
                Event::KeyDown { keycode: Some(Keycode::Num5), .. } => { self.set_input(0x5, true ); },
                Event::KeyUp   { keycode: Some(Keycode::Num5), .. } => { self.set_input(0x5, false); },
                Event::KeyDown { keycode: Some(Keycode::Num6), .. } => { self.set_input(0x6, true ); },
                Event::KeyUp   { keycode: Some(Keycode::Num6), .. } => { self.set_input(0x6, false); },
                Event::KeyDown { keycode: Some(Keycode::Num7), .. } => { self.set_input(0x7, true ); },
                Event::KeyUp   { keycode: Some(Keycode::Num7), .. } => { self.set_input(0x7, false); },
                Event::KeyDown { keycode: Some(Keycode::Num8), .. } => { self.set_input(0x8, true ); },
                Event::KeyUp   { keycode: Some(Keycode::Num8), .. } => { self.set_input(0x8, false); },
                Event::KeyDown { keycode: Some(Keycode::Num9), .. } => { self.set_input(0x9, true ); },
                Event::KeyUp   { keycode: Some(Keycode::Num9), .. } => { self.set_input(0x9, false); },
                Event::KeyDown { keycode: Some(Keycode::A),    .. } => { self.set_input(0xa, true ); },
                Event::KeyUp   { keycode: Some(Keycode::A),    .. } => { self.set_input(0xa, false); },
                Event::KeyDown { keycode: Some(Keycode::B),    .. } => { self.set_input(0xb, true ); },
                Event::KeyUp   { keycode: Some(Keycode::B),    .. } => { self.set_input(0xb, false); },
                Event::KeyDown { keycode: Some(Keycode::C),    .. } => { self.set_input(0xc, true ); },
                Event::KeyUp   { keycode: Some(Keycode::C),    .. } => { self.set_input(0xc, false); },
                Event::KeyDown { keycode: Some(Keycode::D),    .. } => { self.set_input(0xd, true ); },
                Event::KeyUp   { keycode: Some(Keycode::D),    .. } => { self.set_input(0xd, false); },
                Event::KeyDown { keycode: Some(Keycode::E),    .. } => { self.set_input(0xe, true ); },
                Event::KeyUp   { keycode: Some(Keycode::E),    .. } => { self.set_input(0xe, false); },
                Event::KeyDown { keycode: Some(Keycode::F),    .. } => { self.set_input(0xf, true ); },
                Event::KeyUp   { keycode: Some(Keycode::F),    .. } => { self.set_input(0xf, false); },
                _ => {}
            }
        }
    }

    /// Wait until an input event comes through and return the key for that
    /// input event.
    pub fn wait_input(&mut self) -> u8 {
        // Input dirtiness is used to determine if a key has been pressed,
        // regardless if the input state changed at all.
        self.input_dirty = false;

        loop {
            // Poll for input from SDL.
            self.handle_input();

            // Return the key that was pressed to make the input state dirty.
            if self.input_dirty {
                self.last_input;
            }

            sleep(Duration::from_millis(INPUT_WAIT_DELAY));
        }
    }

    /// Reads a 16 bit word from ram. This function is used mainly to read and
    /// execute instructions.
    #[inline(always)]
    pub fn read_word(&self, addr: u16) -> u16 {
        BigEndian::read_u16(&self.ram[addr as usize..])
    }

    /// Find the memory address of the requested character.
    #[inline(always)]
    pub fn get_font(&self, font: u8) -> u16 {
        FONT_OFFSET as u16 + font as u16 * CHARACTER_SIZE as u16
    }

    /// Draws a sprite to the display.
    #[inline(always)]
    pub fn draw(&mut self, x: usize, y: usize, sprite: Vec<u8>) -> u8 {
        let line = y * DISPLAY_WIDTH;
        let mut collision: u8 = 0;
        let mut values = vec![0 as u8; 8];

        for i in 0..sprite.len() {
            // Each byte in a sprite draws on one line.
            let offset = line + DISPLAY_WIDTH * i;

            // Organize the bits from the current sprite byte into a slice.
            for j in 0..values.len() {
                let bit = (sprite[i] >> j) & 0x01;
                values[8 - 1 - j] = bit;
            }

            // Loop through the bits in the current byte and set the display
            // values based on them.
            for j in 0..values.len() {
                let value = values[j];
                let pos: usize = x + j;
                let index: usize;

                // Draw a pixel in the sprite onto the display. If the pixel x
                // position is greater than the width of the display, the sprite
                // wraps around the display.
                if pos > DISPLAY_WIDTH {
                    // Wrap around to the left side to draw.
                    index = offset + pos - DISPLAY_WIDTH;
                } else {
                    // Draw at the current offset.
                    index = offset + pos;
                }

                if index >= 0 && index < DISPLAY_SIZE {
                    // Save the previous state of the pixel before setting it
                    // for collision detection.
                    let prev = self.display[index];

                    // Draw the bit to the display.
                    self.display[index] = value ^ prev;

                    // Check the previous state of the pixel and check if it
                    // was erased, if so then there was a sprite collision.
                    if prev == 1 && self.display[index] == 0 {
                        collision = 1;
                    }
                }
            }
        }

        // Draw to the SDL surface. Humans have these things called "eyes" and
        // they get upset when they cannot see things.
        self.draw_display();

        collision
    }

    /// Clears all pixels on the display by setting them all to an off state.
    pub fn clear_display(&mut self) {
        for i in 0..DISPLAY_SIZE {
            self.display[i] = 0;
        }
        self.draw_display();
    }

    /// Draw the display to the SDL surface. All pixels are white.
    fn draw_display(&mut self) {
        // Clear the screen to black.
        self.renderer.set_draw_color(Color::RGB(0, 0, 0));
        self.renderer.clear();

        // Draw the display to the SDL surface.
        self.renderer.set_draw_color(Color::RGB(255, 255, 255));
        for i in 0..DISPLAY_HEIGHT {
            let offset = DISPLAY_WIDTH * i;
            for j in 0..DISPLAY_WIDTH {
                if self.display[offset + j] == 1 {
                    self.renderer.draw_point(Point::new(j as i32, i as i32));
                }
            }
        }
        self.renderer.present();
    }

    /// Dumps the standard CHIP-8 fonts to ram.
    fn dump_fonts(&mut self) {
        // The characters 0-F to be stored in ram as a font for chip 8 programs.
        // Vectorception for ease of reading.
        let fonts = vec![
            vec![0xF0, 0x90, 0x90, 0x90, 0xF0], // 0
            vec![0x20, 0x60, 0x20, 0x20, 0x70], // 1
            vec![0xF0, 0x10, 0xf0, 0x80, 0xF0], // 2
            vec![0xF0, 0x10, 0xF0, 0x10, 0xF0], // 3
            vec![0x90, 0x90, 0xF0, 0x10, 0x10], // 4
            vec![0xF0, 0x80, 0xF0, 0x10, 0xF0], // 5
            vec![0xF0, 0x80, 0xF0, 0x90, 0xF0], // 6
            vec![0xF0, 0x10, 0x20, 0x40, 0x40], // 7
            vec![0xF0, 0x90, 0xF0, 0x90, 0xF0], // 8
            vec![0xF0, 0x90, 0xF0, 0x10, 0xF0], // 9
            vec![0xF0, 0x90, 0xF0, 0x90, 0x90], // A
            vec![0xE0, 0x90, 0xE0, 0x90, 0xE0], // B
            vec![0xF0, 0x80, 0x80, 0x80, 0xF0], // C
            vec![0xE0, 0x90, 0x90, 0x90, 0xE0], // D
            vec![0xF0, 0x80, 0xF0, 0x80, 0xF0], // E
            vec![0xF0, 0x80, 0xF0, 0x80, 0x80], // F
        ];

        for i in 0..CHARACTER_COUNT {
            // Find where the current character should be stored in memory.
            let start: usize = FONT_OFFSET + i * CHARACTER_SIZE;

            // Copy the current character into the calculated spot in memory.
            for j in 0..CHARACTER_SIZE {
                self.ram[start + j] = fonts[i][j];
            }
        }
    }
}

impl fmt::Debug for Interconnect {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "interconnect")
    }
}
<commit_msg>Fix input pausing<commit_after>use std::fmt;
use std::thread::sleep;
use std::time::Duration;

use super::byteorder::{BigEndian, ByteOrder};
use super::sdl2;
use super::sdl2::pixels::Color;
use super::sdl2::rect::Point;
use super::sdl2::event::Event;
use super::sdl2::keyboard::Keycode;

// Size of the memory map of a CHIP-8 interpreter is 4kb.
const RAM_SIZE: usize = 4096;

// Where fonts are stored in interpreter memory.
const FONT_OFFSET: usize = 0;

// Font size constants.
const CHARACTER_SIZE: usize = 5;
const CHARACTER_COUNT: usize = 16;

// Display size parameters.
const DISPLAY_WIDTH: usize = 64;
const DISPLAY_HEIGHT: usize = 32;
const DISPLAY_SIZE: usize = DISPLAY_WIDTH * DISPLAY_HEIGHT;

// Wait for the duration it takes for an instruction to execute.
const INPUT_WAIT_DELAY: u64 = 2;

// Memory map constraints.
pub const START_RESERVED: usize = 0x000;
pub const END_RESERVED: usize = 0x200;
pub const END_PROGRAM_SPACE: usize = 0xFFF;

pub struct Interconnect {
    sdl_context: sdl2::Sdl,
    video_subsystem: sdl2::VideoSubsystem,
    renderer: sdl2::render::Renderer<'static>,
    event_pump: sdl2::EventPump,

    // The current keyboard input state.
    pub input_state: [bool; 16],

    // Used for input waiting.
    pub input_dirty: bool,

    // Last key pressed.
    pub last_input: u8,

    // The CPU reads this value before executing instructions, and when set to
    // true the CPU will stop executing.
    pub halt: bool,

    // RAM used by the application. 4k in size.
    pub ram: Vec<u8>,

    // 64x32 buffer for the application to write to.
    pub display: Vec<u8>,
}

impl Interconnect {
    pub fn new(rom: Vec<u8>) -> Interconnect {
        let mut ram = vec![0; RAM_SIZE];

        // Dump the rom into ram starting at the start of the program space.
        for i in 0..rom.len() {
            ram[i + END_RESERVED] = rom[i];
        }

        // Setup SDL for graphics and audio.
        let sdl_context = sdl2::init().unwrap();
        let video_subsystem = sdl_context.video().unwrap();
        let window = video_subsystem.window("Notch", 640, 320)
            .position_centered()
            .build()
            .unwrap();

        // Create a renderer that is scaled up a bit. The CHIP-8 display is
        // very small for today's standards.
        let mut renderer = window.renderer().build().unwrap();
        renderer.set_scale(10.0, 10.0);

        // Clear the screen to black.
        renderer.set_draw_color(Color::RGB(0, 0, 0));
        renderer.clear();
        renderer.present();

        let mut event_pump = sdl_context.event_pump().unwrap();

        let mut interconnect = Interconnect {
            sdl_context: sdl_context,
            video_subsystem: video_subsystem,
            renderer: renderer,
            event_pump: event_pump,
            input_state: [false; 16],
            input_dirty: false,
            last_input: 0,
            halt: false,
            ram: ram,
            display: vec![0; DISPLAY_SIZE],
        };
        interconnect.dump_fonts();
        interconnect
    }

    fn set_input(&mut self, key: u8, down: bool) {
        self.input_state[key as usize] = down;
        self.last_input = key;
        self.input_dirty = true;
    }

    /// Get input events from SDL and set the input state.
    pub fn handle_input(&mut self) {
        // Collect the events from the iterator ahead of time so we are not
        // borrowing when we need to set the input state.
        let events: Vec<Event> = self.event_pump.poll_iter().collect();

        for event in events {
            match event {
                Event::Quit {..} => {
                    // Detect close button or escape button events.
                    // The interpreter is then signaled to halt and stop
                    // executing code.
                    self.halt = true;
                },

                // Keyboard to CHIP-8 keycode mapping.
                Event::KeyDown { keycode: Some(Keycode::Num0), .. } => { self.set_input(0x0, true ); },
                Event::KeyUp   { keycode: Some(Keycode::Num0), .. } => { self.set_input(0x0, false); },
                Event::KeyDown { keycode: Some(Keycode::Num1), .. } => { self.set_input(0x1, true ); },
                Event::KeyUp   { keycode: Some(Keycode::Num1), .. } => { self.set_input(0x1, false); },
                Event::KeyDown { keycode: Some(Keycode::Num2), .. } => { self.set_input(0x2, true ); },
                Event::KeyUp   { keycode: Some(Keycode::Num2), .. } => { self.set_input(0x2, false); },
                Event::KeyDown { keycode: Some(Keycode::Num3), .. } => { self.set_input(0x3, true ); },
                Event::KeyUp   { keycode: Some(Keycode::Num3), .. } => { self.set_input(0x3, false); },
                Event::KeyDown { keycode: Some(Keycode::Num4), .. } => { self.set_input(0x4, true ); },
                Event::KeyUp   { keycode: Some(Keycode::Num4), .. } => { self.set_input(0x4, false); },
                Event::KeyDown { keycode: Some(Keycode::Num5), .. } => { self.set_input(0x5, true ); },
                Event::KeyUp   { keycode: Some(Keycode::Num5), .. } => { self.set_input(0x5, false); },
                Event::KeyDown { keycode: Some(Keycode::Num6), .. } => { self.set_input(0x6, true ); },
                Event::KeyUp   { keycode: Some(Keycode::Num6), .. } => { self.set_input(0x6, false); },
                Event::KeyDown { keycode: Some(Keycode::Num7), .. } => { self.set_input(0x7, true ); },
                Event::KeyUp   { keycode: Some(Keycode::Num7), .. } => { self.set_input(0x7, false); },
                Event::KeyDown { keycode: Some(Keycode::Num8), .. } => { self.set_input(0x8, true ); },
                Event::KeyUp   { keycode: Some(Keycode::Num8), .. } => { self.set_input(0x8, false); },
                Event::KeyDown { keycode: Some(Keycode::Num9), .. } => { self.set_input(0x9, true ); },
                Event::KeyUp   { keycode: Some(Keycode::Num9), .. } => { self.set_input(0x9, false); },
                Event::KeyDown { keycode: Some(Keycode::A),    .. } => { self.set_input(0xa, true ); },
                Event::KeyUp   { keycode: Some(Keycode::A),    .. } => { self.set_input(0xa, false); },
                Event::KeyDown { keycode: Some(Keycode::B),    .. } => { self.set_input(0xb, true ); },
                Event::KeyUp   { keycode: Some(Keycode::B),    .. } => { self.set_input(0xb, false); },
                Event::KeyDown { keycode: Some(Keycode::C),    .. } => { self.set_input(0xc, true ); },
                Event::KeyUp   { keycode: Some(Keycode::C),    .. } => { self.set_input(0xc, false); },
                Event::KeyDown { keycode: Some(Keycode::D),    .. } => { self.set_input(0xd, true ); },
                Event::KeyUp   { keycode: Some(Keycode::D),    .. } => { self.set_input(0xd, false); },
                Event::KeyDown { keycode: Some(Keycode::E),    .. } => { self.set_input(0xe, true ); },
                Event::KeyUp   { keycode: Some(Keycode::E),    .. } => { self.set_input(0xe, false); },
                Event::KeyDown { keycode: Some(Keycode::F),    .. } => { self.set_input(0xf, true ); },
                Event::KeyUp   { keycode: Some(Keycode::F),    .. } => { self.set_input(0xf, false); },
                _ => {}
            }
        }
    }

    /// Wait until an input event comes through and return the key for that
    /// input event.
    pub fn wait_input(&mut self) -> u8 {
        // Input dirtiness is used to determine if a key has been pressed,
        // regardless if the input state changed at all.
        self.input_dirty = false;

        loop {
            // Poll for input from SDL.
            self.handle_input();

            // Return the key that was pressed to make the input state dirty.
            if self.input_dirty {
                break;
            }

            sleep(Duration::from_millis(INPUT_WAIT_DELAY));
        }

        self.last_input
    }

    /// Reads a 16 bit word from ram. This function is used mainly to read and
    /// execute instructions.
    #[inline(always)]
    pub fn read_word(&self, addr: u16) -> u16 {
        BigEndian::read_u16(&self.ram[addr as usize..])
    }

    /// Find the memory address of the requested character.
    #[inline(always)]
    pub fn get_font(&self, font: u8) -> u16 {
        FONT_OFFSET as u16 + font as u16 * CHARACTER_SIZE as u16
    }

    /// Draws a sprite to the display.
    #[inline(always)]
    pub fn draw(&mut self, x: usize, y: usize, sprite: Vec<u8>) -> u8 {
        let line = y * DISPLAY_WIDTH;
        let mut collision: u8 = 0;
        let mut values = vec![0 as u8; 8];

        for i in 0..sprite.len() {
            // Each byte in a sprite draws on one line.
            let offset = line + DISPLAY_WIDTH * i;

            // Organize the bits from the current sprite byte into a slice.
            for j in 0..values.len() {
                let bit = (sprite[i] >> j) & 0x01;
                values[8 - 1 - j] = bit;
            }

            // Loop through the bits in the current byte and set the display
            // values based on them.
            for j in 0..values.len() {
                let value = values[j];
                let pos: usize = x + j;
                let index: usize;

                // Draw a pixel in the sprite onto the display. If the pixel x
                // position is greater than the width of the display, the sprite
                // wraps around the display.
                if pos > DISPLAY_WIDTH {
                    // Wrap around to the left side to draw.
                    index = offset + pos - DISPLAY_WIDTH;
                } else {
                    // Draw at the current offset.
                    index = offset + pos;
                }

                if index >= 0 && index < DISPLAY_SIZE {
                    // Save the previous state of the pixel before setting it
                    // for collision detection.
                    let prev = self.display[index];

                    // Draw the bit to the display.
                    self.display[index] = value ^ prev;

                    // Check the previous state of the pixel and check if it
                    // was erased, if so then there was a sprite collision.
                    if prev == 1 && self.display[index] == 0 {
                        collision = 1;
                    }
                }
            }
        }

        // Draw to the SDL surface. Humans have these things called "eyes" and
        // they get upset when they cannot see things.
        self.draw_display();

        collision
    }

    /// Clears all pixels on the display by setting them all to an off state.
    pub fn clear_display(&mut self) {
        for i in 0..DISPLAY_SIZE {
            self.display[i] = 0;
        }
        self.draw_display();
    }

    /// Draw the display to the SDL surface. All pixels are white.
    fn draw_display(&mut self) {
        // Clear the screen to black.
        self.renderer.set_draw_color(Color::RGB(0, 0, 0));
        self.renderer.clear();

        // Draw the display to the SDL surface.
        self.renderer.set_draw_color(Color::RGB(255, 255, 255));
        for i in 0..DISPLAY_HEIGHT {
            let offset = DISPLAY_WIDTH * i;
            for j in 0..DISPLAY_WIDTH {
                if self.display[offset + j] == 1 {
                    self.renderer.draw_point(Point::new(j as i32, i as i32));
                }
            }
        }
        self.renderer.present();
    }

    /// Dumps the standard CHIP-8 fonts to ram.
    fn dump_fonts(&mut self) {
        // The characters 0-F to be stored in ram as a font for chip 8 programs.
        // Vectorception for ease of reading.
        let fonts = vec![
            vec![0xF0, 0x90, 0x90, 0x90, 0xF0], // 0
            vec![0x20, 0x60, 0x20, 0x20, 0x70], // 1
            vec![0xF0, 0x10, 0xf0, 0x80, 0xF0], // 2
            vec![0xF0, 0x10, 0xF0, 0x10, 0xF0], // 3
            vec![0x90, 0x90, 0xF0, 0x10, 0x10], // 4
            vec![0xF0, 0x80, 0xF0, 0x10, 0xF0], // 5
            vec![0xF0, 0x80, 0xF0, 0x90, 0xF0], // 6
            vec![0xF0, 0x10, 0x20, 0x40, 0x40], // 7
            vec![0xF0, 0x90, 0xF0, 0x90, 0xF0], // 8
            vec![0xF0, 0x90, 0xF0, 0x10, 0xF0], // 9
            vec![0xF0, 0x90, 0xF0, 0x90, 0x90], // A
            vec![0xE0, 0x90, 0xE0, 0x90, 0xE0], // B
            vec![0xF0, 0x80, 0x80, 0x80, 0xF0], // C
            vec![0xE0, 0x90, 0x90, 0x90, 0xE0], // D
            vec![0xF0, 0x80, 0xF0, 0x80, 0xF0], // E
            vec![0xF0, 0x80, 0xF0, 0x80, 0x80], // F
        ];

        for i in 0..CHARACTER_COUNT {
            // Find where the current character should be stored in memory.
            let start: usize = FONT_OFFSET + i * CHARACTER_SIZE;

            // Copy the current character into the calculated spot in memory.
            for j in 0..CHARACTER_SIZE {
                self.ram[start + j] = fonts[i][j];
            }
        }
    }
}

impl fmt::Debug for Interconnect {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "interconnect")
    }
}
<|endoftext|>