<commit_before>use core::cmp::min;
use core::mem::size_of;
use core::ptr;

use common::scheduler::*;

pub const PAGE_DIRECTORY: usize = 0x300000;
pub const PAGE_TABLE_SIZE: usize = 1024;
pub const PAGE_TABLES: usize = PAGE_DIRECTORY + PAGE_TABLE_SIZE * 4;
pub const PAGE_SIZE: usize = 4 * 1024;

pub const CLUSTER_ADDRESS: usize = PAGE_TABLES + PAGE_TABLE_SIZE * PAGE_TABLE_SIZE * 4 ;
pub const CLUSTER_COUNT: usize = 1024 * 1024; // 4 GiB
pub const CLUSTER_SIZE: usize = 4 * 1024; // Of 4 K chunks

#[repr(packed)]
struct MemoryMapEntry {
    base: u64,
    len: u64,
    class: u32,
    acpi: u32,
}

struct Memory {
    address: usize,
}

impl Memory {
    pub fn new(size: usize) -> Option<Self> {
        let alloc = alloc(size);
        if alloc > 0 {
            Some(Memory { address: alloc })
        }
        else { None }
    }

    pub fn renew(&self, size: usize) -> Option<Self> {
        let realloc = realloc(self.address, size);
        if realloc > 0 {
            Some(Memory { address: realloc })
        }
        else { None }
    }
}

impl Drop for Memory {
    fn drop(&mut self) {
        unalloc(self.address)
    }
}

const MEMORY_MAP: *const MemoryMapEntry = 0x500 as *const MemoryMapEntry;

pub unsafe fn cluster(number: usize) -> usize {
    if number < CLUSTER_COUNT {
        ptr::read((CLUSTER_ADDRESS + number * size_of::<usize>()) as *const usize)
    } else {
        0
    }
}

pub unsafe fn set_cluster(number: usize, address: usize) {
    if number < CLUSTER_COUNT {
        ptr::write((CLUSTER_ADDRESS + number * size_of::<usize>()) as *mut usize,
                   address);
    }
}

pub unsafe fn address_to_cluster(address: usize) -> usize {
    if address >= CLUSTER_ADDRESS + CLUSTER_COUNT * size_of::<usize>() {
        (address - CLUSTER_ADDRESS - CLUSTER_COUNT * size_of::<usize>()) / CLUSTER_SIZE
    } else {
        0
    }
}

pub unsafe fn cluster_to_address(number: usize) -> usize {
    CLUSTER_ADDRESS + CLUSTER_COUNT * size_of::<usize>() + number * CLUSTER_SIZE
}

pub unsafe fn cluster_init() {
    //First, set all clusters to the not present value
    for cluster in 0..CLUSTER_COUNT {
        set_cluster(cluster, 0xFFFFFFFF);
    }

    //Next, set all valid clusters to the free value
    //TODO: Optimize this function
    for i in 0..((0x5000 - 0x500) / size_of::<MemoryMapEntry>()) {
        let entry = &*MEMORY_MAP.offset(i as isize);
        if entry.len > 0 && entry.class == 1 {
            for cluster in 0..CLUSTER_COUNT {
                let address = cluster_to_address(cluster);
                if address as u64 >= entry.base &&
                   (address as u64 + CLUSTER_SIZE as u64) <= (entry.base + entry.len) {
                    set_cluster(cluster, 0);
                }
            }
        }
    }
}

pub unsafe fn alloc(size: usize) -> usize {
    let mut ret = 0;

    //Memory allocation must be atomic
    let reenable = start_no_ints();

    if size > 0 {
        let mut number = 0;
        let mut count = 0;

        for i in 0..CLUSTER_COUNT {
            if cluster(i) == 0 {
                if count == 0 {
                    number = i;
                }
                count += 1;
                if count * CLUSTER_SIZE > size {
                    break;
                }
            } else {
                count = 0;
            }
        }
        if count * CLUSTER_SIZE > size {
            let address = cluster_to_address(number);
            for i in number..number + count {
                set_cluster(i, address);
            }
            ret = address;
        }
    }

    //Memory allocation must be atomic
    end_no_ints(reenable);

    ret
}

pub unsafe fn alloc_aligned(size: usize, align: usize) -> usize {
    let mut ret = 0;

    //Memory allocation must be atomic
    let reenable = start_no_ints();

    if size > 0 {
        let mut number = 0;
        let mut count = 0;

        for i in 0..CLUSTER_COUNT {
            if cluster(i) == 0 && cluster_to_address(i) % align == 0 {
                if count == 0 {
                    number = i;
                }
                count += 1;
                if count * CLUSTER_SIZE > size {
                    break;
                }
            } else {
                count = 0;
            }
        }
        if count * CLUSTER_SIZE > size {
            let address = cluster_to_address(number);
            for i in number..number + count {
                set_cluster(i, address);
            }
            ret = address;
        }
    }

    //Memory allocation must be atomic
    end_no_ints(reenable);

    ret
}

pub unsafe fn alloc_type<T>() -> *mut T {
    alloc(size_of::<T>()) as *mut T
}

pub unsafe fn alloc_size(ptr: usize) -> usize {
    let mut size = 0;

    //Memory allocation must be atomic
    let reenable = start_no_ints();

    if ptr > 0 {
        for i in address_to_cluster(ptr)..CLUSTER_COUNT {
            if cluster(i) == ptr {
                size += CLUSTER_SIZE;
            } else {
                break;
            }
        }
    }

    //Memory allocation must be atomic
    end_no_ints(reenable);

    size
}

pub unsafe fn unalloc(ptr: usize) {
    //Memory allocation must be atomic
    let reenable = start_no_ints();

    if ptr > 0 {
        for i in address_to_cluster(ptr)..CLUSTER_COUNT {
            if cluster(i) == ptr {
                set_cluster(i, 0);
            } else {
                break;
            }
        }
    }

    //Memory allocation must be atomic
    end_no_ints(reenable);
}

pub unsafe fn realloc(ptr: usize, size: usize) -> usize {
    let mut ret = 0;

    //Memory allocation must be atomic
    let reenable = start_no_ints();

    if size == 0 {
        if ptr > 0 {
            unalloc(ptr);
        }
    } else {
        let old_size = alloc_size(ptr);
        if size <= old_size {
            ret = ptr;
        } else {
            ret = alloc(size);
            if ptr > 0 {
                if ret > 0 {
                    let copy_size = min(old_size, size);

                    ::memmove(ret as *mut u8, ptr as *const u8, copy_size);
                }
                unalloc(ptr);
            }
        }
    }

    end_no_ints(reenable);

    ret
}

pub unsafe fn realloc_inplace(ptr: usize, size: usize) -> usize {
    let old_size = alloc_size(ptr);
    if size <= old_size {
        size
    } else {
        old_size
    }
}

pub fn memory_used() -> usize {
    let mut ret = 0;
    unsafe {
        //Memory allocation must be atomic
        let reenable = start_no_ints();

        for i in 0..CLUSTER_COUNT {
            if cluster(i) != 0 && cluster(i) != 0xFFFFFFFF {
                ret += CLUSTER_SIZE;
            }
        }

        //Memory allocation must be atomic
        end_no_ints(reenable);
    }
    ret
}

pub fn memory_free() -> usize {
    let mut ret = 0;
    unsafe {
        //Memory allocation must be atomic
        let reenable = start_no_ints();

        for i in 0..CLUSTER_COUNT {
            if cluster(i) == 0 {
                ret += CLUSTER_SIZE;
            }
        }

        //Memory allocation must be atomic
        end_no_ints(reenable);
    }
    ret
}
<commit_msg>Fixes<commit_after>use core::cmp::min;
use core::mem::size_of;
use core::ptr;

use common::scheduler::*;

pub const PAGE_DIRECTORY: usize = 0x300000;
pub const PAGE_TABLE_SIZE: usize = 1024;
pub const PAGE_TABLES: usize = PAGE_DIRECTORY + PAGE_TABLE_SIZE * 4;
pub const PAGE_SIZE: usize = 4 * 1024;

pub const CLUSTER_ADDRESS: usize = PAGE_TABLES + PAGE_TABLE_SIZE * PAGE_TABLE_SIZE * 4 ;
pub const CLUSTER_COUNT: usize = 1024 * 1024; // 4 GiB
pub const CLUSTER_SIZE: usize = 4 * 1024; // Of 4 K chunks

#[repr(packed)]
struct MemoryMapEntry {
    base: u64,
    len: u64,
    class: u32,
    acpi: u32,
}

struct Memory {
    address: usize,
}

impl Memory {
    pub fn new(size: usize) -> Option<Self> {
        unsafe {
            let alloc = alloc(size);
            if alloc > 0 {
                Some(Memory { address: alloc })
            }
            else { None }
        }
    }

    pub fn renew(&self, size: usize) -> Option<Self> {
        unsafe {
            let realloc = realloc(self.address, size);
            if realloc > 0 {
                Some(Memory { address: realloc })
            }
            else { None }
        }
    }
}

impl Drop for Memory {
        fn drop(&mut self) {
            unsafe {
                unalloc(self.address)
            }
        }
}

const MEMORY_MAP: *const MemoryMapEntry = 0x500 as *const MemoryMapEntry;

pub unsafe fn cluster(number: usize) -> usize {
    if number < CLUSTER_COUNT {
        ptr::read((CLUSTER_ADDRESS + number * size_of::<usize>()) as *const usize)
    } else {
        0
    }
}

pub unsafe fn set_cluster(number: usize, address: usize) {
    if number < CLUSTER_COUNT {
        ptr::write((CLUSTER_ADDRESS + number * size_of::<usize>()) as *mut usize,
                   address);
    }
}

pub unsafe fn address_to_cluster(address: usize) -> usize {
    if address >= CLUSTER_ADDRESS + CLUSTER_COUNT * size_of::<usize>() {
        (address - CLUSTER_ADDRESS - CLUSTER_COUNT * size_of::<usize>()) / CLUSTER_SIZE
    } else {
        0
    }
}

pub unsafe fn cluster_to_address(number: usize) -> usize {
    CLUSTER_ADDRESS + CLUSTER_COUNT * size_of::<usize>() + number * CLUSTER_SIZE
}

pub unsafe fn cluster_init() {
    //First, set all clusters to the not present value
    for cluster in 0..CLUSTER_COUNT {
        set_cluster(cluster, 0xFFFFFFFF);
    }

    //Next, set all valid clusters to the free value
    //TODO: Optimize this function
    for i in 0..((0x5000 - 0x500) / size_of::<MemoryMapEntry>()) {
        let entry = &*MEMORY_MAP.offset(i as isize);
        if entry.len > 0 && entry.class == 1 {
            for cluster in 0..CLUSTER_COUNT {
                let address = cluster_to_address(cluster);
                if address as u64 >= entry.base &&
                   (address as u64 + CLUSTER_SIZE as u64) <= (entry.base + entry.len) {
                    set_cluster(cluster, 0);
                }
            }
        }
    }
}

pub unsafe fn alloc(size: usize) -> usize {
    let mut ret = 0;

    //Memory allocation must be atomic
    let reenable = start_no_ints();

    if size > 0 {
        let mut number = 0;
        let mut count = 0;

        for i in 0..CLUSTER_COUNT {
            if cluster(i) == 0 {
                if count == 0 {
                    number = i;
                }
                count += 1;
                if count * CLUSTER_SIZE > size {
                    break;
                }
            } else {
                count = 0;
            }
        }
        if count * CLUSTER_SIZE > size {
            let address = cluster_to_address(number);
            for i in number..number + count {
                set_cluster(i, address);
            }
            ret = address;
        }
    }

    //Memory allocation must be atomic
    end_no_ints(reenable);

    ret
}

pub unsafe fn alloc_aligned(size: usize, align: usize) -> usize {
    let mut ret = 0;

    //Memory allocation must be atomic
    let reenable = start_no_ints();

    if size > 0 {
        let mut number = 0;
        let mut count = 0;

        for i in 0..CLUSTER_COUNT {
            if cluster(i) == 0 && cluster_to_address(i) % align == 0 {
                if count == 0 {
                    number = i;
                }
                count += 1;
                if count * CLUSTER_SIZE > size {
                    break;
                }
            } else {
                count = 0;
            }
        }
        if count * CLUSTER_SIZE > size {
            let address = cluster_to_address(number);
            for i in number..number + count {
                set_cluster(i, address);
            }
            ret = address;
        }
    }

    //Memory allocation must be atomic
    end_no_ints(reenable);

    ret
}

pub unsafe fn alloc_type<T>() -> *mut T {
    alloc(size_of::<T>()) as *mut T
}

pub unsafe fn alloc_size(ptr: usize) -> usize {
    let mut size = 0;

    //Memory allocation must be atomic
    let reenable = start_no_ints();

    if ptr > 0 {
        for i in address_to_cluster(ptr)..CLUSTER_COUNT {
            if cluster(i) == ptr {
                size += CLUSTER_SIZE;
            } else {
                break;
            }
        }
    }

    //Memory allocation must be atomic
    end_no_ints(reenable);

    size
}

pub unsafe fn unalloc(ptr: usize) {
    //Memory allocation must be atomic
    let reenable = start_no_ints();

    if ptr > 0 {
        for i in address_to_cluster(ptr)..CLUSTER_COUNT {
            if cluster(i) == ptr {
                set_cluster(i, 0);
            } else {
                break;
            }
        }
    }

    //Memory allocation must be atomic
    end_no_ints(reenable);
}

pub unsafe fn realloc(ptr: usize, size: usize) -> usize {
    let mut ret = 0;

    //Memory allocation must be atomic
    let reenable = start_no_ints();

    if size == 0 {
        if ptr > 0 {
            unalloc(ptr);
        }
    } else {
        let old_size = alloc_size(ptr);
        if size <= old_size {
            ret = ptr;
        } else {
            ret = alloc(size);
            if ptr > 0 {
                if ret > 0 {
                    let copy_size = min(old_size, size);

                    ::memmove(ret as *mut u8, ptr as *const u8, copy_size);
                }
                unalloc(ptr);
            }
        }
    }

    end_no_ints(reenable);

    ret
}

pub unsafe fn realloc_inplace(ptr: usize, size: usize) -> usize {
    let old_size = alloc_size(ptr);
    if size <= old_size {
        size
    } else {
        old_size
    }
}

pub fn memory_used() -> usize {
    let mut ret = 0;
    unsafe {
        //Memory allocation must be atomic
        let reenable = start_no_ints();

        for i in 0..CLUSTER_COUNT {
            if cluster(i) != 0 && cluster(i) != 0xFFFFFFFF {
                ret += CLUSTER_SIZE;
            }
        }

        //Memory allocation must be atomic
        end_no_ints(reenable);
    }
    ret
}

pub fn memory_free() -> usize {
    let mut ret = 0;
    unsafe {
        //Memory allocation must be atomic
        let reenable = start_no_ints();

        for i in 0..CLUSTER_COUNT {
            if cluster(i) == 0 {
                ret += CLUSTER_SIZE;
            }
        }

        //Memory allocation must be atomic
        end_no_ints(reenable);
    }
    ret
}
<|endoftext|>


<commit_before>use character::CharacterDrawable;
use crossbeam_channel as channel;
use game::constants::{CHARACTER_X_SPEED, CHARACTER_Y_SPEED};
use graphics::{camera::CameraInputState, can_move_to_tile, DeltaTime, orientation::Orientation};
use shaders::Position;
use specs;
use specs::prelude::{Read, ReadStorage, WriteStorage};

#[derive(Clone, Debug)]
pub struct CharacterInputState {
  pub x_movement: f32,
  pub y_movement: f32,
  pub orientation: Orientation,
  pub is_colliding: bool,
  pub is_shooting: bool,
}

impl CharacterInputState {
  pub fn new() -> CharacterInputState {
    CharacterInputState {
      x_movement: 0.0,
      y_movement: 0.0,
      orientation: Orientation::Still,
      is_colliding: false,
      is_shooting: false,
    }
  }

  pub fn update(&mut self, camera: &mut CameraInputState, css: &CharacterControlSystem) {
    if css.y_move.is_none() && css.x_move.is_none() {
        self.orientation = Orientation::Still;
    } else if css.x_move.is_none() {
      if let Some(y) = css.y_move {
        let vert_move = Position::new([self.x_movement, self.y_movement + y]);
        if !self.is_colliding || can_move_to_tile(vert_move) {
          self.y_movement += y;
          camera.y_pos -= y;
          self.orientation = match y {
            y if y < 0.0 => Orientation::Up,
            y if y > 0.0 => Orientation::Down,
            _ => Orientation::Still,
          };
        }
      }
    } else if let Some(x) = css.x_move {
      let horizontal_move  = Position::new([self.x_movement + x, self.y_movement]);
      if let Some(y) = css.y_move {
        let diag_move = Position::new([self.x_movement + x, self.y_movement + y]);
        if !self.is_colliding || can_move_to_tile(diag_move) {
          self.x_movement += x / 1.5;
          self.y_movement += y / 1.5;
          camera.x_pos += x / 1.5;
          camera.y_pos -= y / 1.5;

          self.orientation = match (x, y) {
            (x, y) if x > 0.0 && y > 0.0 => Orientation::DownLeft,
            (x, y) if x > 0.0 && y < 0.0 => Orientation::UpLeft,
            (x, y) if x < 0.0 && y > 0.0 => Orientation::DownRight,
            (x, y) if x < 0.0 && y < 0.0 => Orientation::UpRight,
            _ => Orientation::Still,
          };
        }
      } else if css.y_move.is_none() && !self.is_colliding || can_move_to_tile(horizontal_move) {
        self.x_movement += x;
        camera.x_pos += x;
        self.orientation = match x {
          x if x < 0.0 => Orientation::Right,
          x if x > 0.0 => Orientation::Left,
          _ => Orientation::Still,
        };
      }
    }
    self.is_shooting = css.is_ctrl_pressed;
  }
}

impl Default for CharacterInputState {
  fn default() -> Self {
    CharacterInputState::new()
  }
}

impl specs::prelude::Component for CharacterInputState {
  type Storage = specs::storage::DenseVecStorage<CharacterInputState>;
}

#[derive(Debug)]
pub enum CharacterControl {
  Left,
  Right,
  Up,
  Down,
  XMoveStop,
  YMoveStop,
  CtrlPressed,
  CtrlReleased,
}

#[derive(Debug)]
pub struct CharacterControlSystem {
  queue: channel::Receiver<CharacterControl>,
  x_move: Option<f32>,
  y_move: Option<f32>,
  cool_down: f64,
  is_ctrl_pressed: bool,
}

impl CharacterControlSystem {
  pub fn new() -> (CharacterControlSystem, channel::Sender<CharacterControl>) {
    let (tx, rx) = channel::unbounded();
    (CharacterControlSystem {
      queue: rx,
      x_move: None,
      y_move: None,
      cool_down: 1.0,
      is_ctrl_pressed: false,
    }, tx)
  }
}

impl<'a> specs::prelude::System<'a> for CharacterControlSystem {
  #[cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
  type SystemData = (WriteStorage<'a, CharacterInputState>,
                     ReadStorage<'a, CharacterDrawable>,
                     WriteStorage<'a, CameraInputState>,
                     Read<'a, DeltaTime>);

  fn run(&mut self, (mut character_input, character, mut camera_input, d): Self::SystemData) {
    use specs::join::Join;
    use graphics::orientation::Stance;
    let delta = d.0;

    if self.cool_down == 0.0 {
      self.cool_down += 0.1;
    } else {
      self.cool_down = (self.cool_down - delta).max(0.0);
      while let Some(control) = self.queue.try_recv() {
        match control {
          CharacterControl::Up => self.y_move = Some(-CHARACTER_Y_SPEED),
          CharacterControl::Down => self.y_move = Some(CHARACTER_Y_SPEED),
          CharacterControl::YMoveStop => self.y_move = None,
          CharacterControl::Right => self.x_move = Some(-CHARACTER_X_SPEED),
          CharacterControl::Left => self.x_move = Some(CHARACTER_X_SPEED),
          CharacterControl::XMoveStop => self.x_move = None,
          CharacterControl::CtrlPressed => self.is_ctrl_pressed = true,
          CharacterControl::CtrlReleased => self.is_ctrl_pressed = false,
        }
      }

      for (ci, c, camera) in (&mut character_input, &character, &mut camera_input).join() {
        if c.stance != Stance::NormalDeath {
          ci.update(camera, self);
        }
      }
    }
  }
}
<commit_msg>Remove irrelevant linter ignore<commit_after>use character::CharacterDrawable;
use crossbeam_channel as channel;
use game::constants::{CHARACTER_X_SPEED, CHARACTER_Y_SPEED};
use graphics::{camera::CameraInputState, can_move_to_tile, DeltaTime, orientation::Orientation};
use shaders::Position;
use specs;
use specs::prelude::{Read, ReadStorage, WriteStorage};

#[derive(Clone, Debug)]
pub struct CharacterInputState {
  pub x_movement: f32,
  pub y_movement: f32,
  pub orientation: Orientation,
  pub is_colliding: bool,
  pub is_shooting: bool,
}

impl CharacterInputState {
  pub fn new() -> CharacterInputState {
    CharacterInputState {
      x_movement: 0.0,
      y_movement: 0.0,
      orientation: Orientation::Still,
      is_colliding: false,
      is_shooting: false,
    }
  }

  pub fn update(&mut self, camera: &mut CameraInputState, css: &CharacterControlSystem) {
    if css.y_move.is_none() && css.x_move.is_none() {
        self.orientation = Orientation::Still;
    } else if css.x_move.is_none() {
      if let Some(y) = css.y_move {
        let vert_move = Position::new([self.x_movement, self.y_movement + y]);
        if !self.is_colliding || can_move_to_tile(vert_move) {
          self.y_movement += y;
          camera.y_pos -= y;
          self.orientation = match y {
            y if y < 0.0 => Orientation::Up,
            y if y > 0.0 => Orientation::Down,
            _ => Orientation::Still,
          };
        }
      }
    } else if let Some(x) = css.x_move {
      let horizontal_move  = Position::new([self.x_movement + x, self.y_movement]);
      if let Some(y) = css.y_move {
        let diag_move = Position::new([self.x_movement + x, self.y_movement + y]);
        if !self.is_colliding || can_move_to_tile(diag_move) {
          self.x_movement += x / 1.5;
          self.y_movement += y / 1.5;
          camera.x_pos += x / 1.5;
          camera.y_pos -= y / 1.5;

          self.orientation = match (x, y) {
            (x, y) if x > 0.0 && y > 0.0 => Orientation::DownLeft,
            (x, y) if x > 0.0 && y < 0.0 => Orientation::UpLeft,
            (x, y) if x < 0.0 && y > 0.0 => Orientation::DownRight,
            (x, y) if x < 0.0 && y < 0.0 => Orientation::UpRight,
            _ => Orientation::Still,
          };
        }
      } else if css.y_move.is_none() && !self.is_colliding || can_move_to_tile(horizontal_move) {
        self.x_movement += x;
        camera.x_pos += x;
        self.orientation = match x {
          x if x < 0.0 => Orientation::Right,
          x if x > 0.0 => Orientation::Left,
          _ => Orientation::Still,
        };
      }
    }
    self.is_shooting = css.is_ctrl_pressed;
  }
}

impl Default for CharacterInputState {
  fn default() -> Self {
    CharacterInputState::new()
  }
}

impl specs::prelude::Component for CharacterInputState {
  type Storage = specs::storage::DenseVecStorage<CharacterInputState>;
}

#[derive(Debug)]
pub enum CharacterControl {
  Left,
  Right,
  Up,
  Down,
  XMoveStop,
  YMoveStop,
  CtrlPressed,
  CtrlReleased,
}

#[derive(Debug)]
pub struct CharacterControlSystem {
  queue: channel::Receiver<CharacterControl>,
  x_move: Option<f32>,
  y_move: Option<f32>,
  cool_down: f64,
  is_ctrl_pressed: bool,
}

impl CharacterControlSystem {
  pub fn new() -> (CharacterControlSystem, channel::Sender<CharacterControl>) {
    let (tx, rx) = channel::unbounded();
    (CharacterControlSystem {
      queue: rx,
      x_move: None,
      y_move: None,
      cool_down: 1.0,
      is_ctrl_pressed: false,
    }, tx)
  }
}

impl<'a> specs::prelude::System<'a> for CharacterControlSystem {
  type SystemData = (WriteStorage<'a, CharacterInputState>,
                     ReadStorage<'a, CharacterDrawable>,
                     WriteStorage<'a, CameraInputState>,
                     Read<'a, DeltaTime>);

  fn run(&mut self, (mut character_input, character, mut camera_input, d): Self::SystemData) {
    use specs::join::Join;
    use graphics::orientation::Stance;
    let delta = d.0;

    if self.cool_down == 0.0 {
      self.cool_down += 0.1;
    } else {
      self.cool_down = (self.cool_down - delta).max(0.0);
      while let Some(control) = self.queue.try_recv() {
        match control {
          CharacterControl::Up => self.y_move = Some(-CHARACTER_Y_SPEED),
          CharacterControl::Down => self.y_move = Some(CHARACTER_Y_SPEED),
          CharacterControl::YMoveStop => self.y_move = None,
          CharacterControl::Right => self.x_move = Some(-CHARACTER_X_SPEED),
          CharacterControl::Left => self.x_move = Some(CHARACTER_X_SPEED),
          CharacterControl::XMoveStop => self.x_move = None,
          CharacterControl::CtrlPressed => self.is_ctrl_pressed = true,
          CharacterControl::CtrlReleased => self.is_ctrl_pressed = false,
        }
      }

      for (ci, c, camera) in (&mut character_input, &character, &mut camera_input).join() {
        if c.stance != Stance::NormalDeath {
          ci.update(camera, self);
        }
      }
    }
  }
}
<|endoftext|>


<commit_before>use super::header::{Header, ImageType, ALPHA_BIT_MASK, SCREEN_ORIGIN_BIT_MASK};
use crate::{
    color::{ColorType, ExtendedColorType},
    error::{ImageError, ImageResult, UnsupportedError, UnsupportedErrorKind},
    image::{ImageDecoder, ImageFormat, ImageReadBuffer},
};
use byteorder::ReadBytesExt;
use std::{
    convert::TryFrom,
    io::{self, Read, Seek},
};

struct ColorMap {
    /// sizes in bytes
    start_offset: usize,
    entry_size: usize,
    bytes: Vec<u8>,
}

impl ColorMap {
    pub(crate) fn from_reader(
        r: &mut dyn Read,
        start_offset: u16,
        num_entries: u16,
        bits_per_entry: u8,
    ) -> ImageResult<ColorMap> {
        let bytes_per_entry = (bits_per_entry as usize + 7) / 8;

        let mut bytes = vec![0; bytes_per_entry * num_entries as usize];
        r.read_exact(&mut bytes)?;

        Ok(ColorMap {
            entry_size: bytes_per_entry,
            start_offset: start_offset as usize,
            bytes,
        })
    }

    /// Get one entry from the color map
    pub(crate) fn get(&self, index: usize) -> &[u8] {
        let entry = self.start_offset + self.entry_size * index;
        &self.bytes[entry..entry + self.entry_size]
    }
}

/// The representation of a TGA decoder
pub struct TgaDecoder<R> {
    r: R,

    width: usize,
    height: usize,
    bytes_per_pixel: usize,
    has_loaded_metadata: bool,

    image_type: ImageType,
    color_type: ColorType,

    header: Header,
    color_map: Option<ColorMap>,

    // Used in read_scanline
    line_read: Option<usize>,
    line_remain_buff: Vec<u8>,
}

impl<R: Read + Seek> TgaDecoder<R> {
    /// Create a new decoder that decodes from the stream `r`
    pub fn new(r: R) -> ImageResult<TgaDecoder<R>> {
        let mut decoder = TgaDecoder {
            r,

            width: 0,
            height: 0,
            bytes_per_pixel: 0,
            has_loaded_metadata: false,

            image_type: ImageType::Unknown,
            color_type: ColorType::L8,

            header: Header::default(),
            color_map: None,

            line_read: None,
            line_remain_buff: Vec::new(),
        };
        decoder.read_metadata()?;
        Ok(decoder)
    }

    fn read_header(&mut self) -> ImageResult<()> {
        self.header = Header::from_reader(&mut self.r)?;
        self.image_type = ImageType::new(self.header.image_type);
        self.width = self.header.image_width as usize;
        self.height = self.header.image_height as usize;
        self.bytes_per_pixel = (self.header.pixel_depth as usize + 7) / 8;
        Ok(())
    }

    fn read_metadata(&mut self) -> ImageResult<()> {
        if !self.has_loaded_metadata {
            self.read_header()?;
            self.read_image_id()?;
            self.read_color_map()?;
            self.read_color_information()?;
            self.has_loaded_metadata = true;
        }
        Ok(())
    }

    /// Loads the color information for the decoder
    ///
    /// To keep things simple, we won't handle bit depths that aren't divisible
    /// by 8 and are larger than 32.
    fn read_color_information(&mut self) -> ImageResult<()> {
        if self.header.pixel_depth % 8 != 0 || self.header.pixel_depth > 32 {
            // Bit depth must be divisible by 8, and must be less than or equal
            // to 32.
            return Err(ImageError::Unsupported(
                UnsupportedError::from_format_and_kind(
                    ImageFormat::Tga.into(),
                    UnsupportedErrorKind::Color(ExtendedColorType::Unknown(
                        self.header.pixel_depth,
                    )),
                ),
            ));
        }

        let num_alpha_bits = self.header.image_desc & ALPHA_BIT_MASK;

        let other_channel_bits = if self.header.map_type != 0 {
            self.header.map_entry_size
        } else {
            if num_alpha_bits > self.header.pixel_depth {
                return Err(ImageError::Unsupported(
                    UnsupportedError::from_format_and_kind(
                        ImageFormat::Tga.into(),
                        UnsupportedErrorKind::Color(ExtendedColorType::Unknown(
                            self.header.pixel_depth,
                        )),
                    ),
                ));
            }

            self.header.pixel_depth - num_alpha_bits
        };
        let color = self.image_type.is_color();

        match (num_alpha_bits, other_channel_bits, color) {
            // really, the encoding is BGR and BGRA, this is fixed
            // up with `TgaDecoder::reverse_encoding`.
            (0, 32, true) => self.color_type = ColorType::Rgba8,
            (8, 24, true) => self.color_type = ColorType::Rgba8,
            (0, 24, true) => self.color_type = ColorType::Rgb8,
            (8, 8, false) => self.color_type = ColorType::La8,
            (0, 8, false) => self.color_type = ColorType::L8,
            _ => {
                return Err(ImageError::Unsupported(
                    UnsupportedError::from_format_and_kind(
                        ImageFormat::Tga.into(),
                        UnsupportedErrorKind::Color(ExtendedColorType::Unknown(
                            self.header.pixel_depth,
                        )),
                    ),
                ))
            }
        }
        Ok(())
    }

    /// Read the image id field
    ///
    /// We're not interested in this field, so this function skips it if it
    /// is present
    fn read_image_id(&mut self) -> ImageResult<()> {
        self.r
            .seek(io::SeekFrom::Current(i64::from(self.header.id_length)))?;
        Ok(())
    }

    fn read_color_map(&mut self) -> ImageResult<()> {
        if self.header.map_type == 1 {
            self.color_map = Some(ColorMap::from_reader(
                &mut self.r,
                self.header.map_origin,
                self.header.map_length,
                self.header.map_entry_size,
            )?);
        }
        Ok(())
    }

    /// Expands indices into its mapped color
    fn expand_color_map(&self, pixel_data: &[u8]) -> Vec<u8> {
        #[inline]
        fn bytes_to_index(bytes: &[u8]) -> usize {
            let mut result = 0usize;
            for byte in bytes.iter() {
                result = result << 8 | *byte as usize;
            }
            result
        }

        let bytes_per_entry = (self.header.map_entry_size as usize + 7) / 8;
        let mut result = Vec::with_capacity(self.width * self.height * bytes_per_entry);

        let color_map = self.color_map.as_ref().unwrap();

        for chunk in pixel_data.chunks(self.bytes_per_pixel) {
            let index = bytes_to_index(chunk);
            result.extend(color_map.get(index).iter().cloned());
        }

        result
    }

    /// Reads a run length encoded data for given number of bytes
    fn read_encoded_data(&mut self, num_bytes: usize) -> io::Result<Vec<u8>> {
        let mut pixel_data = Vec::with_capacity(num_bytes);

        while pixel_data.len() < num_bytes {
            let run_packet = self.r.read_u8()?;
            // If the highest bit in `run_packet` is set, then we repeat pixels
            //
            // Note: the TGA format adds 1 to both counts because having a count
            // of 0 would be pointless.
            if (run_packet & 0x80) != 0 {
                // high bit set, so we will repeat the data
                let repeat_count = ((run_packet & !0x80) + 1) as usize;
                let mut data = Vec::with_capacity(self.bytes_per_pixel);
                self.r
                    .by_ref()
                    .take(self.bytes_per_pixel as u64)
                    .read_to_end(&mut data)?;
                for _ in 0usize..repeat_count {
                    pixel_data.extend(data.iter().cloned());
                }
            } else {
                // not set, so `run_packet+1` is the number of non-encoded pixels
                let num_raw_bytes = (run_packet + 1) as usize * self.bytes_per_pixel;
                self.r
                    .by_ref()
                    .take(num_raw_bytes as u64)
                    .read_to_end(&mut pixel_data)?;
            }
        }

        Ok(pixel_data)
    }

    /// Reads a run length encoded packet
    fn read_all_encoded_data(&mut self) -> ImageResult<Vec<u8>> {
        let num_bytes = self.width * self.height * self.bytes_per_pixel;

        Ok(self.read_encoded_data(num_bytes)?)
    }

    /// Reads a run length encoded line
    fn read_encoded_line(&mut self) -> io::Result<Vec<u8>> {
        let line_num_bytes = self.width * self.bytes_per_pixel;
        let remain_len = self.line_remain_buff.len();

        if remain_len >= line_num_bytes {
            let remain_buf = self.line_remain_buff.clone();

            self.line_remain_buff = remain_buf[line_num_bytes..].to_vec();
            return Ok(remain_buf[0..line_num_bytes].to_vec());
        }

        let num_bytes = line_num_bytes - remain_len;

        let line_data = self.read_encoded_data(num_bytes)?;

        let mut pixel_data = Vec::with_capacity(line_num_bytes);
        pixel_data.append(&mut self.line_remain_buff);
        pixel_data.extend_from_slice(&line_data[..num_bytes]);

        // put the remain data to line_remain_buff
        self.line_remain_buff = line_data[num_bytes..].to_vec();

        Ok(pixel_data)
    }

    /// Reverse from BGR encoding to RGB encoding
    ///
    /// TGA files are stored in the BGRA encoding. This function swaps
    /// the blue and red bytes in the `pixels` array.
    fn reverse_encoding(&mut self, pixels: &mut [u8]) {
        // We only need to reverse the encoding of color images
        match self.color_type {
            ColorType::Rgb8 | ColorType::Rgba8 => {
                for chunk in pixels.chunks_mut(self.bytes_per_pixel) {
                    chunk.swap(0, 2);
                }
            }
            _ => {}
        }
    }

    /// Flip the image vertically depending on the screen origin bit
    ///
    /// The bit in position 5 of the image descriptor byte is the screen origin bit.
    /// If it's 1, the origin is in the top left corner.
    /// If it's 0, the origin is in the bottom left corner.
    /// This function checks the bit, and if it's 0, flips the image vertically.
    fn flip_vertically(&mut self, pixels: &mut [u8]) {
        if self.is_flipped_vertically() {
            let num_bytes = pixels.len();

            let width_bytes = num_bytes / self.height;

            // Flip the image vertically.
            for vertical_index in 0..(self.height / 2) {
                let vertical_target = (self.height - vertical_index) * width_bytes - width_bytes;

                for horizontal_index in 0..width_bytes {
                    let source = vertical_index * width_bytes + horizontal_index;
                    let target = vertical_target + horizontal_index;

                    pixels.swap(target, source);
                }
            }
        }
    }

    /// Check whether the image is vertically flipped
    ///
    /// The bit in position 5 of the image descriptor byte is the screen origin bit.
    /// If it's 1, the origin is in the top left corner.
    /// If it's 0, the origin is in the bottom left corner.
    /// This function checks the bit, and if it's 0, flips the image vertically.
    fn is_flipped_vertically(&self) -> bool {
        let screen_origin_bit = SCREEN_ORIGIN_BIT_MASK & self.header.image_desc != 0;
        !screen_origin_bit
    }

    fn read_scanline(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        if let Some(line_read) = self.line_read {
            if line_read == self.height {
                return Ok(0);
            }
        }

        // read the pixels from the data region
        let mut pixel_data = if self.image_type.is_encoded() {
            self.read_encoded_line()?
        } else {
            let num_raw_bytes = self.width * self.bytes_per_pixel;
            let mut buf = vec![0; num_raw_bytes];
            self.r.by_ref().read_exact(&mut buf)?;
            buf
        };

        // expand the indices using the color map if necessary
        if self.image_type.is_color_mapped() {
            pixel_data = self.expand_color_map(&pixel_data)
        }
        self.reverse_encoding(&mut pixel_data);

        // copy to the output buffer
        buf[..pixel_data.len()].copy_from_slice(&pixel_data);

        self.line_read = Some(self.line_read.unwrap_or(0) + 1);

        Ok(pixel_data.len())
    }
}

impl<'a, R: 'a + Read + Seek> ImageDecoder<'a> for TgaDecoder<R> {
    type Reader = TGAReader<R>;

    fn dimensions(&self) -> (u32, u32) {
        (self.width as u32, self.height as u32)
    }

    fn color_type(&self) -> ColorType {
        self.color_type
    }

    fn scanline_bytes(&self) -> u64 {
        // This cannot overflow because TGA has a maximum width of u16::MAX_VALUE and
        // `bytes_per_pixel` is a u8.
        u64::from(self.color_type.bytes_per_pixel()) * self.width as u64
    }

    fn into_reader(self) -> ImageResult<Self::Reader> {
        Ok(TGAReader {
            buffer: ImageReadBuffer::new(self.scanline_bytes(), self.total_bytes()),
            decoder: self,
        })
    }

    fn read_image(mut self, buf: &mut [u8]) -> ImageResult<()> {
        assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes()));

        // read the pixels from the data region
        let len = if self.image_type.is_encoded() {
            let pixel_data = self.read_all_encoded_data()?;
            buf[0..pixel_data.len()].copy_from_slice(&pixel_data);
            pixel_data.len()
        } else {
            let num_raw_bytes = self.width * self.height * self.bytes_per_pixel;
            self.r.by_ref().read_exact(&mut buf[0..num_raw_bytes])?;
            num_raw_bytes
        };

        // expand the indices using the color map if necessary
        if self.image_type.is_color_mapped() {
            let pixel_data = self.expand_color_map(&buf[0..len]);
            buf.copy_from_slice(&pixel_data);
        }

        self.reverse_encoding(buf);

        self.flip_vertically(buf);

        Ok(())
    }
}

pub struct TGAReader<R> {
    buffer: ImageReadBuffer,
    decoder: TgaDecoder<R>,
}
impl<R: Read + Seek> Read for TGAReader<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let decoder = &mut self.decoder;
        self.buffer.read(buf, |buf| decoder.read_scanline(buf))
    }
}
<commit_msg>Allow loading alpha-only TGAs as L8<commit_after>use super::header::{Header, ImageType, ALPHA_BIT_MASK, SCREEN_ORIGIN_BIT_MASK};
use crate::{
    color::{ColorType, ExtendedColorType},
    error::{ImageError, ImageResult, UnsupportedError, UnsupportedErrorKind},
    image::{ImageDecoder, ImageFormat, ImageReadBuffer},
};
use byteorder::ReadBytesExt;
use std::{
    convert::TryFrom,
    io::{self, Read, Seek},
};

struct ColorMap {
    /// sizes in bytes
    start_offset: usize,
    entry_size: usize,
    bytes: Vec<u8>,
}

impl ColorMap {
    pub(crate) fn from_reader(
        r: &mut dyn Read,
        start_offset: u16,
        num_entries: u16,
        bits_per_entry: u8,
    ) -> ImageResult<ColorMap> {
        let bytes_per_entry = (bits_per_entry as usize + 7) / 8;

        let mut bytes = vec![0; bytes_per_entry * num_entries as usize];
        r.read_exact(&mut bytes)?;

        Ok(ColorMap {
            entry_size: bytes_per_entry,
            start_offset: start_offset as usize,
            bytes,
        })
    }

    /// Get one entry from the color map
    pub(crate) fn get(&self, index: usize) -> &[u8] {
        let entry = self.start_offset + self.entry_size * index;
        &self.bytes[entry..entry + self.entry_size]
    }
}

/// The representation of a TGA decoder
pub struct TgaDecoder<R> {
    r: R,

    width: usize,
    height: usize,
    bytes_per_pixel: usize,
    has_loaded_metadata: bool,

    image_type: ImageType,
    color_type: ColorType,

    header: Header,
    color_map: Option<ColorMap>,

    // Used in read_scanline
    line_read: Option<usize>,
    line_remain_buff: Vec<u8>,
}

impl<R: Read + Seek> TgaDecoder<R> {
    /// Create a new decoder that decodes from the stream `r`
    pub fn new(r: R) -> ImageResult<TgaDecoder<R>> {
        let mut decoder = TgaDecoder {
            r,

            width: 0,
            height: 0,
            bytes_per_pixel: 0,
            has_loaded_metadata: false,

            image_type: ImageType::Unknown,
            color_type: ColorType::L8,

            header: Header::default(),
            color_map: None,

            line_read: None,
            line_remain_buff: Vec::new(),
        };
        decoder.read_metadata()?;
        Ok(decoder)
    }

    fn read_header(&mut self) -> ImageResult<()> {
        self.header = Header::from_reader(&mut self.r)?;
        self.image_type = ImageType::new(self.header.image_type);
        self.width = self.header.image_width as usize;
        self.height = self.header.image_height as usize;
        self.bytes_per_pixel = (self.header.pixel_depth as usize + 7) / 8;
        Ok(())
    }

    fn read_metadata(&mut self) -> ImageResult<()> {
        if !self.has_loaded_metadata {
            self.read_header()?;
            self.read_image_id()?;
            self.read_color_map()?;
            self.read_color_information()?;
            self.has_loaded_metadata = true;
        }
        Ok(())
    }

    /// Loads the color information for the decoder
    ///
    /// To keep things simple, we won't handle bit depths that aren't divisible
    /// by 8 and are larger than 32.
    fn read_color_information(&mut self) -> ImageResult<()> {
        if self.header.pixel_depth % 8 != 0 || self.header.pixel_depth > 32 {
            // Bit depth must be divisible by 8, and must be less than or equal
            // to 32.
            return Err(ImageError::Unsupported(
                UnsupportedError::from_format_and_kind(
                    ImageFormat::Tga.into(),
                    UnsupportedErrorKind::Color(ExtendedColorType::Unknown(
                        self.header.pixel_depth,
                    )),
                ),
            ));
        }

        let num_alpha_bits = self.header.image_desc & ALPHA_BIT_MASK;

        let other_channel_bits = if self.header.map_type != 0 {
            self.header.map_entry_size
        } else {
            if num_alpha_bits > self.header.pixel_depth {
                return Err(ImageError::Unsupported(
                    UnsupportedError::from_format_and_kind(
                        ImageFormat::Tga.into(),
                        UnsupportedErrorKind::Color(ExtendedColorType::Unknown(
                            self.header.pixel_depth,
                        )),
                    ),
                ));
            }

            self.header.pixel_depth - num_alpha_bits
        };
        let color = self.image_type.is_color();

        match (num_alpha_bits, other_channel_bits, color) {
            // really, the encoding is BGR and BGRA, this is fixed
            // up with `TgaDecoder::reverse_encoding`.
            (0, 32, true) => self.color_type = ColorType::Rgba8,
            (8, 24, true) => self.color_type = ColorType::Rgba8,
            (0, 24, true) => self.color_type = ColorType::Rgb8,
            (8, 8, false) => self.color_type = ColorType::La8,
            (0, 8, false) => self.color_type = ColorType::L8,
            (8, 0, false) => self.color_type = ColorType::L8, // alpha-only image is treated as L8
            _ => {
                return Err(ImageError::Unsupported(
                    UnsupportedError::from_format_and_kind(
                        ImageFormat::Tga.into(),
                        UnsupportedErrorKind::Color(ExtendedColorType::Unknown(
                            self.header.pixel_depth,
                        )),
                    ),
                ))
            }
        }
        Ok(())
    }

    /// Read the image id field
    ///
    /// We're not interested in this field, so this function skips it if it
    /// is present
    fn read_image_id(&mut self) -> ImageResult<()> {
        self.r
            .seek(io::SeekFrom::Current(i64::from(self.header.id_length)))?;
        Ok(())
    }

    fn read_color_map(&mut self) -> ImageResult<()> {
        if self.header.map_type == 1 {
            self.color_map = Some(ColorMap::from_reader(
                &mut self.r,
                self.header.map_origin,
                self.header.map_length,
                self.header.map_entry_size,
            )?);
        }
        Ok(())
    }

    /// Expands indices into its mapped color
    fn expand_color_map(&self, pixel_data: &[u8]) -> Vec<u8> {
        #[inline]
        fn bytes_to_index(bytes: &[u8]) -> usize {
            let mut result = 0usize;
            for byte in bytes.iter() {
                result = result << 8 | *byte as usize;
            }
            result
        }

        let bytes_per_entry = (self.header.map_entry_size as usize + 7) / 8;
        let mut result = Vec::with_capacity(self.width * self.height * bytes_per_entry);

        let color_map = self.color_map.as_ref().unwrap();

        for chunk in pixel_data.chunks(self.bytes_per_pixel) {
            let index = bytes_to_index(chunk);
            result.extend(color_map.get(index).iter().cloned());
        }

        result
    }

    /// Reads a run length encoded data for given number of bytes
    fn read_encoded_data(&mut self, num_bytes: usize) -> io::Result<Vec<u8>> {
        let mut pixel_data = Vec::with_capacity(num_bytes);

        while pixel_data.len() < num_bytes {
            let run_packet = self.r.read_u8()?;
            // If the highest bit in `run_packet` is set, then we repeat pixels
            //
            // Note: the TGA format adds 1 to both counts because having a count
            // of 0 would be pointless.
            if (run_packet & 0x80) != 0 {
                // high bit set, so we will repeat the data
                let repeat_count = ((run_packet & !0x80) + 1) as usize;
                let mut data = Vec::with_capacity(self.bytes_per_pixel);
                self.r
                    .by_ref()
                    .take(self.bytes_per_pixel as u64)
                    .read_to_end(&mut data)?;
                for _ in 0usize..repeat_count {
                    pixel_data.extend(data.iter().cloned());
                }
            } else {
                // not set, so `run_packet+1` is the number of non-encoded pixels
                let num_raw_bytes = (run_packet + 1) as usize * self.bytes_per_pixel;
                self.r
                    .by_ref()
                    .take(num_raw_bytes as u64)
                    .read_to_end(&mut pixel_data)?;
            }
        }

        Ok(pixel_data)
    }

    /// Reads a run length encoded packet
    fn read_all_encoded_data(&mut self) -> ImageResult<Vec<u8>> {
        let num_bytes = self.width * self.height * self.bytes_per_pixel;

        Ok(self.read_encoded_data(num_bytes)?)
    }

    /// Reads a run length encoded line
    fn read_encoded_line(&mut self) -> io::Result<Vec<u8>> {
        let line_num_bytes = self.width * self.bytes_per_pixel;
        let remain_len = self.line_remain_buff.len();

        if remain_len >= line_num_bytes {
            let remain_buf = self.line_remain_buff.clone();

            self.line_remain_buff = remain_buf[line_num_bytes..].to_vec();
            return Ok(remain_buf[0..line_num_bytes].to_vec());
        }

        let num_bytes = line_num_bytes - remain_len;

        let line_data = self.read_encoded_data(num_bytes)?;

        let mut pixel_data = Vec::with_capacity(line_num_bytes);
        pixel_data.append(&mut self.line_remain_buff);
        pixel_data.extend_from_slice(&line_data[..num_bytes]);

        // put the remain data to line_remain_buff
        self.line_remain_buff = line_data[num_bytes..].to_vec();

        Ok(pixel_data)
    }

    /// Reverse from BGR encoding to RGB encoding
    ///
    /// TGA files are stored in the BGRA encoding. This function swaps
    /// the blue and red bytes in the `pixels` array.
    fn reverse_encoding(&mut self, pixels: &mut [u8]) {
        // We only need to reverse the encoding of color images
        match self.color_type {
            ColorType::Rgb8 | ColorType::Rgba8 => {
                for chunk in pixels.chunks_mut(self.bytes_per_pixel) {
                    chunk.swap(0, 2);
                }
            }
            _ => {}
        }
    }

    /// Flip the image vertically depending on the screen origin bit
    ///
    /// The bit in position 5 of the image descriptor byte is the screen origin bit.
    /// If it's 1, the origin is in the top left corner.
    /// If it's 0, the origin is in the bottom left corner.
    /// This function checks the bit, and if it's 0, flips the image vertically.
    fn flip_vertically(&mut self, pixels: &mut [u8]) {
        if self.is_flipped_vertically() {
            let num_bytes = pixels.len();

            let width_bytes = num_bytes / self.height;

            // Flip the image vertically.
            for vertical_index in 0..(self.height / 2) {
                let vertical_target = (self.height - vertical_index) * width_bytes - width_bytes;

                for horizontal_index in 0..width_bytes {
                    let source = vertical_index * width_bytes + horizontal_index;
                    let target = vertical_target + horizontal_index;

                    pixels.swap(target, source);
                }
            }
        }
    }

    /// Check whether the image is vertically flipped
    ///
    /// The bit in position 5 of the image descriptor byte is the screen origin bit.
    /// If it's 1, the origin is in the top left corner.
    /// If it's 0, the origin is in the bottom left corner.
    /// This function checks the bit, and if it's 0, flips the image vertically.
    fn is_flipped_vertically(&self) -> bool {
        let screen_origin_bit = SCREEN_ORIGIN_BIT_MASK & self.header.image_desc != 0;
        !screen_origin_bit
    }

    fn read_scanline(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        if let Some(line_read) = self.line_read {
            if line_read == self.height {
                return Ok(0);
            }
        }

        // read the pixels from the data region
        let mut pixel_data = if self.image_type.is_encoded() {
            self.read_encoded_line()?
        } else {
            let num_raw_bytes = self.width * self.bytes_per_pixel;
            let mut buf = vec![0; num_raw_bytes];
            self.r.by_ref().read_exact(&mut buf)?;
            buf
        };

        // expand the indices using the color map if necessary
        if self.image_type.is_color_mapped() {
            pixel_data = self.expand_color_map(&pixel_data)
        }
        self.reverse_encoding(&mut pixel_data);

        // copy to the output buffer
        buf[..pixel_data.len()].copy_from_slice(&pixel_data);

        self.line_read = Some(self.line_read.unwrap_or(0) + 1);

        Ok(pixel_data.len())
    }
}

impl<'a, R: 'a + Read + Seek> ImageDecoder<'a> for TgaDecoder<R> {
    type Reader = TGAReader<R>;

    fn dimensions(&self) -> (u32, u32) {
        (self.width as u32, self.height as u32)
    }

    fn color_type(&self) -> ColorType {
        self.color_type
    }

    fn scanline_bytes(&self) -> u64 {
        // This cannot overflow because TGA has a maximum width of u16::MAX_VALUE and
        // `bytes_per_pixel` is a u8.
        u64::from(self.color_type.bytes_per_pixel()) * self.width as u64
    }

    fn into_reader(self) -> ImageResult<Self::Reader> {
        Ok(TGAReader {
            buffer: ImageReadBuffer::new(self.scanline_bytes(), self.total_bytes()),
            decoder: self,
        })
    }

    fn read_image(mut self, buf: &mut [u8]) -> ImageResult<()> {
        assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes()));

        // read the pixels from the data region
        let len = if self.image_type.is_encoded() {
            let pixel_data = self.read_all_encoded_data()?;
            buf[0..pixel_data.len()].copy_from_slice(&pixel_data);
            pixel_data.len()
        } else {
            let num_raw_bytes = self.width * self.height * self.bytes_per_pixel;
            self.r.by_ref().read_exact(&mut buf[0..num_raw_bytes])?;
            num_raw_bytes
        };

        // expand the indices using the color map if necessary
        if self.image_type.is_color_mapped() {
            let pixel_data = self.expand_color_map(&buf[0..len]);
            buf.copy_from_slice(&pixel_data);
        }

        self.reverse_encoding(buf);

        self.flip_vertically(buf);

        Ok(())
    }
}

pub struct TGAReader<R> {
    buffer: ImageReadBuffer,
    decoder: TgaDecoder<R>,
}
impl<R: Read + Seek> Read for TGAReader<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let decoder = &mut self.decoder;
        self.buffer.read(buf, |buf| decoder.read_scanline(buf))
    }
}
<|endoftext|>


<commit_before>use types::NumPlies;

use super::super::color::{White, Black};
use super::super::piece::Piece::{self, WK, WR, BK, BR};
use super::super::piece::Pawn;
use super::super::square::{Square, File, Rank};
use super::super::moves::Move;
use super::super::castle::{Kingside, Queenside};

use super::{Position, ExtraData};

pub fn make_move(p: &mut Position, m: &Move) {

    debug!("make_move with move {:?}", *m);

    debug!("before: position is {:?}", *p);

    let from = m.from();
    let to = m.to();
    let curr_piece = p.at(from).unwrap();
    let curr_color = p.side_to_move();

    if m.capture_normal().is_some() || m.is_en_passant() || curr_piece.piece_type() == Pawn {
        p.set_ply_count(NumPlies(0));
    } else {
        let NumPlies(temp) = p.ply_count();
        p.set_ply_count(NumPlies(temp+1));
    }

    if let Some(castle_side) = m.castle() {

        //no en passant
        p.set_en_passant(None);

        let (rook_from, rook_to) = match (curr_color, castle_side) {
            (White, Kingside ) => (Square::new(File(7), Rank(0)), Square::new(File(5), Rank(0))),
            (White, Queenside) => (Square::new(File(0), Rank(0)), Square::new(File(3), Rank(0))),
            (Black, Kingside ) => (Square::new(File(7), Rank(7)), Square::new(File(5), Rank(7))),
            (Black, Queenside) => (Square::new(File(0), Rank(7)), Square::new(File(3), Rank(7))),
        };

        p.remove_at(from, curr_piece);
        p.set_at(to, curr_piece);
        let curr_rook = p.at(rook_from).unwrap();
        p.remove_at(rook_from, curr_rook);
        p.set_at(rook_to, curr_rook);

    } else if m.is_en_passant() {

        //no en passant after this
        p.set_en_passant(None);

        let captured = Square::new(to.file(), from.rank());
        let captured_piece = Piece::new(p.side_to_move().invert(), Pawn);

        p.remove_at(captured, captured_piece);
        p.remove_at(from, curr_piece);
        p.set_at(to, curr_piece);

    } else if let Some(promote_piece) = m.promote() {
        //no en passant
        p.set_en_passant(None);

        //change the board and promote
        if let Some(captured_piece) = m.capture_normal() {
            p.remove_at(to, captured_piece);
        }
        p.remove_at(from, curr_piece);
        p.set_at(to, Piece::new(curr_color, promote_piece));
    } else {

        if m.is_pawn_double_move() {
            p.set_en_passant(Some(to.file()));
        } else {
            p.set_en_passant(None);
        }

        //change the board
        if let Some(captured_piece) = m.capture_normal() {
            p.remove_at(to, captured_piece);
        }
        p.remove_at(from, curr_piece);
        p.set_at(to, curr_piece);
    }

    //castling
    if p.at(Square::new(File(4), Rank(0))) != Some(WK) {
        p.set_castle(Queenside, White, false);
        p.set_castle(Kingside , White, false);
    }
    if p.at(Square::new(File(0), Rank(0))) != Some(WR) {
        p.set_castle(Queenside, White, false);
    }
    if p.at(Square::new(File(7), Rank(0))) != Some(WR) {
        p.set_castle(Kingside , White, false);
    }
    if p.at(Square::new(File(4), Rank(7))) != Some(BK) {
        p.set_castle(Queenside, Black, false);
        p.set_castle(Kingside , Black, false);
    }
    if p.at(Square::new(File(0), Rank(7))) != Some(BR) {
        p.set_castle(Queenside, Black, false);
    }
    if p.at(Square::new(File(7), Rank(7))) != Some(BR) {
        p.set_castle(Kingside , Black, false);
    }

    p.swap_side_to_move();

    debug!("after : position is {:?}", *p);
}

pub fn unmake_move(p: &mut Position, m: &Move, extra_data: ExtraData) {
    let from = m.from();
    let to = m.to();
    let curr_piece = p.at(to).unwrap();
    let curr_color = p.side_to_move().invert();

    if let Some(castle_side) = m.castle() {

        let (rook_from, rook_to) = match (curr_color, castle_side) {
            (White, Kingside ) => (Square::new(File(7), Rank(0)), Square::new(File(5), Rank(0))),
            (White, Queenside) => (Square::new(File(0), Rank(0)), Square::new(File(3), Rank(0))),
            (Black, Kingside ) => (Square::new(File(7), Rank(7)), Square::new(File(5), Rank(7))),
            (Black, Queenside) => (Square::new(File(0), Rank(7)), Square::new(File(3), Rank(7))),
        };

        p.remove_at(to, curr_piece);
        p.set_at(from, curr_piece);
        let curr_rook = p.at(rook_to).unwrap();
        p.remove_at(rook_to, curr_rook);
        p.set_at(rook_from, curr_rook);

    } else if m.is_en_passant() {

        let captured = Square::new(to.file(), from.rank());
        let captured_piece = Piece::new(curr_color.invert(), Pawn);

        p.set_at(captured, captured_piece);
        p.remove_at(to, curr_piece);
        p.set_at(from, curr_piece);

    } else if let Some(promote_piece) = m.promote() {

        p.remove_at(to, Piece::new(curr_color, promote_piece));
        p.set_at(to, curr_piece);
        if let Some(captured_piece) = m.capture_normal() {
            p.set_at(to, captured_piece);
        }

    } else {

        p.remove_at(to, curr_piece);
        p.set_at(from, curr_piece);
        if let Some(captured_piece) = m.capture_normal() {
            p.set_at(to, captured_piece);
        }

    }

    p.set_extra_data(extra_data);
    p.swap_side_to_move();
}
<commit_msg>Edit debug logging in make_move() and unmake_move()<commit_after>use types::NumPlies;

use super::super::color::{White, Black};
use super::super::piece::Piece::{self, WK, WR, BK, BR};
use super::super::piece::Pawn;
use super::super::square::{Square, File, Rank};
use super::super::moves::Move;
use super::super::castle::{Kingside, Queenside};

use super::{Position, ExtraData};

pub fn make_move(p: &mut Position, m: &Move) {

    debug!("make_move(): {:?}", *m);

    debug!("before: {:?}", *p);

    let from = m.from();
    let to = m.to();
    let curr_piece = p.at(from).unwrap();
    let curr_color = p.side_to_move();

    if m.capture_normal().is_some() || m.is_en_passant() || curr_piece.piece_type() == Pawn {
        p.set_ply_count(NumPlies(0));
    } else {
        let NumPlies(temp) = p.ply_count();
        p.set_ply_count(NumPlies(temp+1));
    }

    if let Some(castle_side) = m.castle() {

        //no en passant
        p.set_en_passant(None);

        let (rook_from, rook_to) = match (curr_color, castle_side) {
            (White, Kingside ) => (Square::new(File(7), Rank(0)), Square::new(File(5), Rank(0))),
            (White, Queenside) => (Square::new(File(0), Rank(0)), Square::new(File(3), Rank(0))),
            (Black, Kingside ) => (Square::new(File(7), Rank(7)), Square::new(File(5), Rank(7))),
            (Black, Queenside) => (Square::new(File(0), Rank(7)), Square::new(File(3), Rank(7))),
        };

        p.remove_at(from, curr_piece);
        p.set_at(to, curr_piece);
        let curr_rook = p.at(rook_from).unwrap();
        p.remove_at(rook_from, curr_rook);
        p.set_at(rook_to, curr_rook);

    } else if m.is_en_passant() {

        //no en passant after this
        p.set_en_passant(None);

        let captured = Square::new(to.file(), from.rank());
        let captured_piece = Piece::new(p.side_to_move().invert(), Pawn);

        p.remove_at(captured, captured_piece);
        p.remove_at(from, curr_piece);
        p.set_at(to, curr_piece);

    } else if let Some(promote_piece) = m.promote() {
        //no en passant
        p.set_en_passant(None);

        //change the board and promote
        if let Some(captured_piece) = m.capture_normal() {
            p.remove_at(to, captured_piece);
        }
        p.remove_at(from, curr_piece);
        p.set_at(to, Piece::new(curr_color, promote_piece));
    } else {

        if m.is_pawn_double_move() {
            p.set_en_passant(Some(to.file()));
        } else {
            p.set_en_passant(None);
        }

        //change the board
        if let Some(captured_piece) = m.capture_normal() {
            p.remove_at(to, captured_piece);
        }
        p.remove_at(from, curr_piece);
        p.set_at(to, curr_piece);
    }

    //castling
    if p.at(Square::new(File(4), Rank(0))) != Some(WK) {
        p.set_castle(Queenside, White, false);
        p.set_castle(Kingside , White, false);
    }
    if p.at(Square::new(File(0), Rank(0))) != Some(WR) {
        p.set_castle(Queenside, White, false);
    }
    if p.at(Square::new(File(7), Rank(0))) != Some(WR) {
        p.set_castle(Kingside , White, false);
    }
    if p.at(Square::new(File(4), Rank(7))) != Some(BK) {
        p.set_castle(Queenside, Black, false);
        p.set_castle(Kingside , Black, false);
    }
    if p.at(Square::new(File(0), Rank(7))) != Some(BR) {
        p.set_castle(Queenside, Black, false);
    }
    if p.at(Square::new(File(7), Rank(7))) != Some(BR) {
        p.set_castle(Kingside , Black, false);
    }

    p.swap_side_to_move();

    debug!("after : {:?}", *p);
}

pub fn unmake_move(p: &mut Position, m: &Move, extra_data: ExtraData) {

    debug!("unmake_move(): {:?}", *m);
    debug!("{:?}", extra_data);

    debug!("before: {:?}", *p);

    let from = m.from();
    let to = m.to();
    let curr_piece = p.at(to).unwrap();
    let curr_color = p.side_to_move().invert();

    if let Some(castle_side) = m.castle() {

        let (rook_from, rook_to) = match (curr_color, castle_side) {
            (White, Kingside ) => (Square::new(File(7), Rank(0)), Square::new(File(5), Rank(0))),
            (White, Queenside) => (Square::new(File(0), Rank(0)), Square::new(File(3), Rank(0))),
            (Black, Kingside ) => (Square::new(File(7), Rank(7)), Square::new(File(5), Rank(7))),
            (Black, Queenside) => (Square::new(File(0), Rank(7)), Square::new(File(3), Rank(7))),
        };

        p.remove_at(to, curr_piece);
        p.set_at(from, curr_piece);
        let curr_rook = p.at(rook_to).unwrap();
        p.remove_at(rook_to, curr_rook);
        p.set_at(rook_from, curr_rook);

    } else if m.is_en_passant() {

        let captured = Square::new(to.file(), from.rank());
        let captured_piece = Piece::new(curr_color.invert(), Pawn);

        p.set_at(captured, captured_piece);
        p.remove_at(to, curr_piece);
        p.set_at(from, curr_piece);

    } else if let Some(promote_piece) = m.promote() {

        p.remove_at(to, Piece::new(curr_color, promote_piece));
        p.set_at(to, curr_piece);
        if let Some(captured_piece) = m.capture_normal() {
            p.set_at(to, captured_piece);
        }

    } else {

        p.remove_at(to, curr_piece);
        p.set_at(from, curr_piece);
        if let Some(captured_piece) = m.capture_normal() {
            p.set_at(to, captured_piece);
        }

    }

    p.set_extra_data(extra_data);
    p.swap_side_to_move();

    debug!("after : {:?}", *p);

}
<|endoftext|>


<commit_before>//! A pass is a type of query over the grammar that may be depended on by other passes.
//! This allows us to build each different type of pass in isolation, and then combine them
//! with automatic dependency resolution.

pub mod firsts;
pub mod follows;
pub mod nullable;

use std::{
  any::{Any, TypeId},
  cell::RefCell,
  collections::BTreeMap,
  rc::Rc,
};

use super::{ElemTypes, Grammar};

pub trait BasePassError {
  fn as_any(&self) -> &(dyn std::any::Any + 'static);
  fn as_err(&self) -> &(dyn std::error::Error + 'static);
}

impl<T> BasePassError for T
where
  T: std::any::Any + std::error::Error + 'static,
{
  fn as_any(&self) -> &(dyn Any + 'static) {
    self
  }

  fn as_err(&self) -> &(dyn std::error::Error + 'static) {
    self
  }
}

struct BoxPassError(Box<dyn BasePassError>);

enum PassError<E, P>
where
  P: Pass<E>,
  E: ElemTypes,
{
  ThisPass(P::Error),
  PrevPass(Box<dyn BasePassError>),
}

pub trait Pass<E>
where
  E: ElemTypes,
{
  type Value: Any + 'static;
  type Error;

  fn run_pass(
    pass_map: &PassContext<E>,
  ) -> Result<Self::Value, Self::Error>;
}

/// A map from passes to their associated results.
pub struct PassContext<'a, E>
where
  E: ElemTypes,
{
  grammar: &'a Grammar<E>,
  passes: RefCell<BTreeMap<TypeId, Rc<dyn Any + 'static>>>,
}

impl<'a, E> PassContext<'a, E>
where
  E: ElemTypes,
{
  // Create a new pass map, where passes derive from the given grammar and other passes.
  pub fn new(grammar: &'a Grammar<E>) -> Self {
    PassContext {
      grammar,
      passes: RefCell::new(BTreeMap::new()),
    }
  }

  /// Returns the underlying grammar.
  pub fn grammar(&self) -> &'a Grammar<E> {
    self.grammar
  }

  /// Returns the result of the given pass. Computes it if it hasn't been computed yet. Passes can
  /// depend on other passes.
  pub fn get_pass<P>(&self) -> Result<Rc<P::Value>, P::Error>
  where
    P: Pass<E> + 'static,
  {
    let pass_type = TypeId::of::<P>();

    let contains_key = {
      let guard = self.passes.borrow();
      guard.contains_key(&pass_type)
    };

    if !contains_key {
      let value = P::run_pass(self)?;
      let mut guard = self.passes.borrow_mut();
      guard.insert(pass_type, Rc::new(value));
    };

    let any_pass_ref = {
      let guard = self.passes.borrow();
      guard.get(&pass_type).expect("existence already checked").clone()
    };

    Ok(any_pass_ref.downcast::<P::Value>().expect("type already verified"))
  }
}
<commit_msg>Add detection of infinite loops in a pass context.<commit_after>//! A pass is a type of query over the grammar that may be depended on by other passes.
//! This allows us to build each different type of pass in isolation, and then combine them
//! with automatic dependency resolution.

pub mod firsts;
pub mod follows;
pub mod nullable;

use std::{
  any::{Any, TypeId},
  cell::RefCell,
  collections::BTreeMap,
  rc::Rc,
};

use super::{ElemTypes, Grammar};

pub trait BasePassError {
  fn as_any(&self) -> &(dyn std::any::Any + 'static);
  fn as_err(&self) -> &(dyn std::error::Error + 'static);
}

impl<T> BasePassError for T
where
  T: std::any::Any + std::error::Error + 'static,
{
  fn as_any(&self) -> &(dyn Any + 'static) {
    self
  }

  fn as_err(&self) -> &(dyn std::error::Error + 'static) {
    self
  }
}

struct BoxPassError(Box<dyn BasePassError>);

enum PassError<E, P>
where
  P: Pass<E>,
  E: ElemTypes,
{
  ThisPass(P::Error),
  PrevPass(Box<dyn BasePassError>),
  RecursionDetected,
}

struct NoCurrentValue;

pub trait Pass<E>
where
  E: ElemTypes,
{
  type Value: Any + 'static;
  type Error;

  fn run_pass(pass_map: &PassContext<E>) -> Result<Self::Value, Self::Error>;
}

/// A map from passes to their associated results.
pub struct PassContext<'a, E>
where
  E: ElemTypes,
{
  grammar: &'a Grammar<E>,
  passes: RefCell<BTreeMap<TypeId, Rc<dyn Any + 'static>>>,
}

impl<'a, E> PassContext<'a, E>
where
  E: ElemTypes,
{
  // Create a new pass map, where passes derive from the given grammar and other passes.
  pub fn new(grammar: &'a Grammar<E>) -> Self {
    PassContext {
      grammar,
      passes: RefCell::new(BTreeMap::new()),
    }
  }

  /// Returns the underlying grammar.
  pub fn grammar(&self) -> &'a Grammar<E> {
    self.grammar
  }

  /// Returns the result of the given pass. Computes it if it hasn't been computed yet. Passes can
  /// depend on other passes.
  pub fn get_pass<P>(&self) -> Result<Rc<P::Value>, P::Error>
  where
    P: Pass<E> + 'static,
  {
    let pass_type = TypeId::of::<P>();

    let contains_key = {
      let guard = self.passes.borrow();
      match guard.get(&pass_type) {
        // Check if we already have the result.
        //
        Some(pass) => {
          if pass.downcast_ref::<NoCurrentValue>().is_some() {
            panic!("Detected recursive loop in pass dependencies.")
          } else {
            true
          }
        }
        None => false,
      }
    };

    if !contains_key {
      {
        // Insert a NoCurrentRef as the current value to mark it as in process. This
        // helps us avoid infinite recursion.
        let mut guard = self.passes.borrow_mut();
        guard.insert(pass_type, Rc::new(NoCurrentValue));
      }
      let value = P::run_pass(self)?;
      let mut guard = self.passes.borrow_mut();
      guard.insert(pass_type, Rc::new(value));
    };

    let any_pass_ref = {
      let guard = self.passes.borrow();
      guard
        .get(&pass_type)
        .expect("existence already checked")
        .clone()
    };

    Ok(
      any_pass_ref
        .downcast::<P::Value>()
        .expect("type already verified"),
    )
  }
}
<|endoftext|>