<commit_before>extern crate nalgebra as na;
extern crate ncollide2d;
extern crate nphysics2d;
extern crate nphysics_testbed2d;

use std::f32::consts::PI;
use na::{Isometry2, Point2, Translation2, Vector2};
use ncollide2d::shape::{Ball, Cuboid, Plane, ShapeHandle};
use nphysics2d::world::World;
use nphysics2d::object::{BodyHandle, BodyStatus};
use nphysics2d::joint::RevoluteJoint;
use nphysics2d::math::{Inertia, Velocity};
use nphysics2d::volumetric::Volumetric;
use nphysics_testbed2d::Testbed;

const COLLIDER_MARGIN: f32 = 0.01;

fn main() {
    /*
     * World
     */
    let mut world = World::new();
    world.set_gravity(Vector2::new(0.0, 9.81));

    /*
     * Plane
     */
    let ground_shape = ShapeHandle::new(Cuboid::new(Vector2::new(20.0, 20.0)));
    let ground_pos = Isometry2::new(Vector2::y() * 20.0, na::zero());
    world.add_collider(
        COLLIDER_MARGIN,
        ground_shape,
        BodyHandle::ground(),
        ground_pos,
        Material::default(),
    );

    /*
     * Create the boxes
     */
    let num = 8;
    let rad = 0.2;
    let mut parent = BodyHandle::ground();

    let revo = RevoluteJoint::new(0.0);
    let geom = ShapeHandle::new(Ball::new(rad));
    let inertia = geom.inertia(5.0);

    for j in 0usize..num {
        /*
         * Create the rigid body.
         */
        let mut body_shift = Vector2::zeros();
        if j == 0 {
            body_shift.y = -8.0;
        }

        parent = world.add_multibody_link(
            parent,
            revo,
            body_shift,
            Vector2::new(-rad * 3.0, 0.0),
            inertia,
        );

        /*
         * Create the collider.
         */
        world.add_collider(COLLIDER_MARGIN, geom.clone(), parent, Isometry2::identity());
    }

    // Setup damping for the whole multibody.
    world.multibody_mut(parent).unwrap().damping_mut().fill(0.1);

    /*
     * Create the boxes
     */
    let num = 10;
    let rad = 0.2;
    let shift   = rad * 2.0 /*+ 1.0e-4*/;
    let centerx = shift * (num as f32) / 2.0;
    let centery = shift / 2.0 + 3.04;
    let centerz = shift * (num as f32) / 2.0;

    let geom = ShapeHandle::new(Cuboid::new(Vector2::repeat(rad - COLLIDER_MARGIN)));
    let inertia = geom.inertia(1.0);

    for i in 0usize..num {
        for j in 0usize..num {
            let x = i as f32 * shift - centerx;
            let y = j as f32 * shift + centery;

            /*
             * Create the rigid body.
             */
            let pos = Isometry2::new(Vector2::new(x, -y), na::zero());
            let handle = world.add_rigid_body(pos, inertia);

            // if j == 5 {
            //     let mut rb = world.rigid_body_mut(handle).unwrap();
            //     rb.set_status(BodyStatus::Disabled);
            // }

            // if j == 7 {
            //     let mut rb = world.rigid_body_mut(handle).unwrap();
            //     rb.set_status(BodyStatus::Static);
            // }

            /*
             * Create the collider.
             */
            world.add_collider(COLLIDER_MARGIN, geom.clone(), handle, Isometry2::identity());
        }
    }

    /*
     * Setup a kinematic rigid body.
     */
    let geom = ShapeHandle::new(Cuboid::new(Vector2::new(rad * 10.0, rad)));
    let pos = Isometry2::new(Vector2::new(0.0, -1.5), na::zero());
    let platform_handle = world.add_rigid_body(pos, Inertia::zero());
    {
        let rb = world.rigid_body_mut(platform_handle).unwrap();
        rb.set_status(BodyStatus::Kinematic);
        rb.set_velocity(Velocity::linear(1.0, 0.0));
    }
    world.add_collider(
        COLLIDER_MARGIN,
        geom.clone(),
        platform_handle,
        Isometry2::identity(),
    );

    // /*
    //  * Setup a kinematic multibody.
    //  */
    // let geom      = ShapeHandle::new(Ball::new(rad - COLLIDER_MARGIN));
    // let joint     = RevoluteJoint::new(0.0);
    // let inertia   = Inertia::zero();
    // let joint_pos = Isometry2::new(Vector2::new(5.0, -2.0), na::zero());
    // let handle    = world.add_multibody_link(BodyHandle::ground(), joint, Vector2::new(2.0, 0.0), joint_pos, inertia);

    // {
    //     let mut mb = world.multibody_mut(handle).unwrap();
    //     mb.generalized_velocity_mut()[0] = 3.0;
    //     mb.set_status(BodyStatus::Kinematic);
    // }

    // world.add_collider(COLLIDER_MARGIN, geom, handle, Isometry2::identity(), true);

    /*
     * Setup a motorized multibody.
     */
    let geom = ShapeHandle::new(Ball::new(2.0 * rad - COLLIDER_MARGIN));
    let mut joint = RevoluteJoint::new(0.0);
    joint.set_desired_angular_motor_velocity(-2.0);
    joint.set_max_angular_motor_torque(2.0);
    joint.enable_angular_motor();
    let inertia = geom.inertia(1.0);
    let handle = world.add_multibody_link(
        BodyHandle::ground(),
        joint,
        Vector2::new(-4.0, -3.0),
        Vector2::x() * 2.0,
        inertia,
    );

    world.add_collider(COLLIDER_MARGIN, geom, handle, Isometry2::identity());

    /*
     * Setup a callback to control the platform.
     */
    let mut testbed = Testbed::new(world);
    testbed.add_callback(move |world, time| {
        let platform = world.rigid_body_mut(platform_handle).unwrap();
        let platform_x = platform.position().translation.vector.x;

        let mut vel = *platform.velocity();
        vel.linear.y = (time * 5.0).sin() * 0.8;

        if platform_x >= rad * 10.0 {
            vel.linear.x = -1.0;
        }
        if platform_x <= -rad * 10.0 {
            vel.linear.x = 1.0;
        }

        platform.set_velocity(vel);
    });

    /*
     * Run the simulation.
     */
    testbed.run();
}
<commit_msg>Fix 2D body status demo.<commit_after>extern crate nalgebra as na;
extern crate ncollide2d;
extern crate nphysics2d;
extern crate nphysics_testbed2d;

use na::{Isometry2, Point2, Translation2, Vector2};
use ncollide2d::shape::{Ball, Cuboid, Plane, ShapeHandle};
use nphysics2d::joint::RevoluteJoint;
use nphysics2d::math::{Inertia, Velocity};
use nphysics2d::object::{BodyHandle, BodyStatus, Material};
use nphysics2d::volumetric::Volumetric;
use nphysics2d::world::World;
use nphysics_testbed2d::Testbed;
use std::f32::consts::PI;

const COLLIDER_MARGIN: f32 = 0.01;

fn main() {
    /*
     * World
     */
    let mut world = World::new();
    world.set_gravity(Vector2::new(0.0, 9.81));

    /*
     * Plane
     */
    let ground_shape = ShapeHandle::new(Cuboid::new(Vector2::new(20.0, 20.0)));
    let ground_pos = Isometry2::new(Vector2::y() * 20.0, na::zero());
    world.add_collider(
        COLLIDER_MARGIN,
        ground_shape,
        BodyHandle::ground(),
        ground_pos,
        Material::default(),
    );

    /*
     * Create the boxes
     */
    let num = 8;
    let rad = 0.2;
    let mut parent = BodyHandle::ground();

    let revo = RevoluteJoint::new(0.0);
    let geom = ShapeHandle::new(Ball::new(rad));
    let inertia = geom.inertia(5.0);
    let center_of_mass = geom.center_of_mass();

    for j in 0usize..num {
        /*
         * Create the rigid body.
         */
        let mut body_shift = Vector2::zeros();
        if j == 0 {
            body_shift.y = -8.0;
        }

        parent = world.add_multibody_link(
            parent,
            revo,
            body_shift,
            Vector2::new(-rad * 3.0, 0.0),
            inertia,
            center_of_mass,
        );

        /*
         * Create the collider.
         */
        world.add_collider(
            COLLIDER_MARGIN,
            geom.clone(),
            parent,
            Isometry2::identity(),
            Material::default(),
        );
    }

    // Setup damping for the whole multibody.
    world.multibody_mut(parent).unwrap().damping_mut().fill(0.1);

    /*
     * Create the boxes
     */
    let num = 10;
    let rad = 0.2;
    let shift   = rad * 2.0 /*+ 1.0e-4*/;
    let centerx = shift * (num as f32) / 2.0;
    let centery = shift / 2.0 + 3.04;
    let centerz = shift * (num as f32) / 2.0;

    let geom = ShapeHandle::new(Cuboid::new(Vector2::repeat(rad - COLLIDER_MARGIN)));
    let inertia = geom.inertia(1.0);
    let center_of_mass = geom.center_of_mass();

    for i in 0usize..num {
        for j in 0usize..num {
            let x = i as f32 * shift - centerx;
            let y = j as f32 * shift + centery;

            /*
             * Create the rigid body.
             */
            let pos = Isometry2::new(Vector2::new(x, -y), na::zero());
            let handle = world.add_rigid_body(pos, inertia, center_of_mass);

            // if j == 5 {
            //     let mut rb = world.rigid_body_mut(handle).unwrap();
            //     rb.set_status(BodyStatus::Disabled);
            // }

            // if j == 7 {
            //     let mut rb = world.rigid_body_mut(handle).unwrap();
            //     rb.set_status(BodyStatus::Static);
            // }

            /*
             * Create the collider.
             */
            world.add_collider(
                COLLIDER_MARGIN,
                geom.clone(),
                handle,
                Isometry2::identity(),
                Material::default(),
            );
        }
    }

    /*
     * Setup a kinematic rigid body.
     */
    let geom = ShapeHandle::new(Cuboid::new(Vector2::new(rad * 10.0, rad)));
    let pos = Isometry2::new(Vector2::new(0.0, -1.5), na::zero());
    let platform_handle = world.add_rigid_body(pos, Inertia::zero(), Point2::origin());
    {
        let rb = world.rigid_body_mut(platform_handle).unwrap();
        rb.set_status(BodyStatus::Kinematic);
        rb.set_velocity(Velocity::linear(1.0, 0.0));
    }
    world.add_collider(
        COLLIDER_MARGIN,
        geom.clone(),
        platform_handle,
        Isometry2::identity(),
        Material::default(),
    );

    // /*
    //  * Setup a kinematic multibody.
    //  */
    // let geom      = ShapeHandle::new(Ball::new(rad - COLLIDER_MARGIN));
    // let joint     = RevoluteJoint::new(0.0);
    // let inertia   = Inertia::zero();
    // let joint_pos = Isometry2::new(Vector2::new(5.0, -2.0), na::zero());
    // let handle    = world.add_multibody_link(BodyHandle::ground(), joint, Vector2::new(2.0, 0.0), joint_pos, inertia);

    // {
    //     let mut mb = world.multibody_mut(handle).unwrap();
    //     mb.generalized_velocity_mut()[0] = 3.0;
    //     mb.set_status(BodyStatus::Kinematic);
    // }

    // world.add_collider(COLLIDER_MARGIN, geom, handle, Isometry2::identity(), true);

    /*
     * Setup a motorized multibody.
     */
    let geom = ShapeHandle::new(Ball::new(2.0 * rad - COLLIDER_MARGIN));
    let mut joint = RevoluteJoint::new(0.0);
    joint.set_desired_angular_motor_velocity(-2.0);
    joint.set_max_angular_motor_torque(2.0);
    joint.enable_angular_motor();
    let inertia = geom.inertia(1.0);
    let center_of_mass = geom.center_of_mass();
    let handle = world.add_multibody_link(
        BodyHandle::ground(),
        joint,
        Vector2::new(-4.0, -3.0),
        Vector2::x() * 2.0,
        inertia,
        center_of_mass,
    );

    world.add_collider(
        COLLIDER_MARGIN,
        geom,
        handle,
        Isometry2::identity(),
        Material::default(),
    );

    /*
     * Setup a callback to control the platform.
     */
    let mut testbed = Testbed::new(world);
    testbed.add_callback(move |world, time| {
        let platform = world.rigid_body_mut(platform_handle).unwrap();
        let platform_x = platform.position().translation.vector.x;

        let mut vel = *platform.velocity();
        vel.linear.y = (time * 5.0).sin() * 0.8;

        if platform_x >= rad * 10.0 {
            vel.linear.x = -1.0;
        }
        if platform_x <= -rad * 10.0 {
            vel.linear.x = 1.0;
        }

        platform.set_velocity(vel);
    });

    /*
     * Run the simulation.
     */
    testbed.run();
}
<|endoftext|>


<commit_before>use std::time::Instant;

use gfx;
use specs;
use specs::prelude::{Read, WriteStorage};

use crate::bullet;
use crate::character;
use crate::critter::CharacterSprite;
use crate::game::constants::{CURRENT_AMMO_TEXT, HUD_TEXTS, VERSION_NUMBER_TEXT};
use crate::gfx_app::{ColorFormat, DepthFormat};
use crate::gfx_app::renderer::EncoderQueue;
use crate::graphics::{DeltaTime, orientation::Stance};
use crate::graphics::Drawables;
use crate::hud;
use crate::terrain;
use crate::terrain_object;
use crate::terrain_object::TerrainTexture;
use crate::zombie;

pub struct DrawSystem<D: gfx::Device> {
  render_target_view: gfx::handle::RenderTargetView<D::Resources, ColorFormat>,
  depth_stencil_view: gfx::handle::DepthStencilView<D::Resources, DepthFormat>,
  terrain_system: terrain::TerrainDrawSystem<D::Resources>,
  character_system: character::CharacterDrawSystem<D::Resources>,
  zombie_system: zombie::ZombieDrawSystem<D::Resources>,
  bullet_system: bullet::BulletDrawSystem<D::Resources>,
  terrain_object_system: [terrain_object::TerrainObjectDrawSystem<D::Resources>; 3],
  text_system: [hud::TextDrawSystem<D::Resources>; 3],
  encoder_queue: EncoderQueue<D>,
  game_time: Instant,
  frames: u32,
  cool_down: f64,
  run_cool_down: f64,
  fire_cool_down: f64,
}

impl<D: gfx::Device> DrawSystem<D> {
  pub fn new<F>(factory: &mut F,
                rtv: &gfx::handle::RenderTargetView<D::Resources, ColorFormat>,
                dsv: &gfx::handle::DepthStencilView<D::Resources, DepthFormat>,
                encoder_queue: EncoderQueue<D>)
                -> DrawSystem<D>
    where F: gfx::Factory<D::Resources> {
    DrawSystem {
      render_target_view: rtv.clone(),
      depth_stencil_view: dsv.clone(),
      terrain_system: terrain::TerrainDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      character_system: character::CharacterDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      zombie_system: zombie::ZombieDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      bullet_system: bullet::BulletDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      terrain_object_system: [
        terrain_object::TerrainObjectDrawSystem::new(factory, rtv.clone(), dsv.clone(), TerrainTexture::Ammo),
        terrain_object::TerrainObjectDrawSystem::new(factory, rtv.clone(), dsv.clone(), TerrainTexture::House),
        terrain_object::TerrainObjectDrawSystem::new(factory, rtv.clone(), dsv.clone(), TerrainTexture::Tree)
      ],
      text_system: [
        hud::TextDrawSystem::new(factory, &HUD_TEXTS, VERSION_NUMBER_TEXT, rtv.clone(), dsv.clone()),
        hud::TextDrawSystem::new(factory, &HUD_TEXTS, CURRENT_AMMO_TEXT, rtv.clone(), dsv.clone()),
        hud::TextDrawSystem::new(factory, &HUD_TEXTS, CURRENT_AMMO_TEXT, rtv.clone(), dsv.clone())
      ],
      encoder_queue,
      game_time: Instant::now(),
      frames: 0,
      cool_down: 1.0,
      run_cool_down: 1.0,
      fire_cool_down: 1.0,
    }
  }
}

impl<'a, D> specs::prelude::System<'a> for DrawSystem<D>
  where D: gfx::Device,
        D::CommandBuffer: Send {
  type SystemData = (WriteStorage<'a, terrain::TerrainDrawable>,
                     WriteStorage<'a, character::CharacterDrawable>,
                     WriteStorage<'a, CharacterSprite>,
                     WriteStorage<'a, hud::hud_objects::HudObjects>,
                     WriteStorage<'a, zombie::zombies::Zombies>,
                     WriteStorage<'a, bullet::bullets::Bullets>,
                     WriteStorage<'a, terrain_object::terrain_objects::TerrainObjects>,
                     Read<'a, DeltaTime>);

  fn run(&mut self, (mut terrain, mut character, mut character_sprite, mut hud_objects, mut zombies, mut bullets, mut terrain_objects, dt): Self::SystemData) {
    use specs::join::Join;
    let mut encoder = self.encoder_queue.receiver
      .recv()
      .expect("Encoder error");

    let delta = dt.0;

    if self.cool_down == 0.0 {
      self.cool_down += 0.05;
    }
    if self.fire_cool_down == 0.0 {
      self.fire_cool_down += 0.2;
    }
    if self.run_cool_down == 0.0 {
      self.run_cool_down += 0.02;
    }
    self.cool_down = (self.cool_down - delta).max(0.0);
    self.run_cool_down = (self.run_cool_down - delta).max(0.0);
    self.fire_cool_down = (self.fire_cool_down - delta).max(0.0);

    let current_time = Instant::now();
    self.frames += 1;
    if cfg!(feature = "framerate") && (current_time.duration_since(self.game_time).as_secs()) >= 1 {
      println!("{:?} ms/frames", 1000.0 / f64::from(self.frames));
      self.frames = 0;
      self.game_time = Instant::now();
    }

    encoder.clear(&self.render_target_view, [16.0 / 256.0, 16.0 / 256.0, 20.0 / 256.0, 1.0]);
    encoder.clear_depth(&self.depth_stencil_view, 1.0);

    for (t, c, cs, hds, zs, bs, obj) in (&mut terrain, &mut character, &mut character_sprite, &mut hud_objects,
                                         &mut zombies, &mut bullets, &mut terrain_objects).join() {
      self.terrain_system.draw(t, &mut encoder);

      for hud in &mut hds.objects {
        self.text_system[0].draw(hud, &mut encoder);
        self.text_system[1].draw(hud, &mut encoder);
      }

      if self.cool_down == 0.0 {
        if c.stance == Stance::Walking {
          cs.update_run();
        }
        for z in &mut zs.zombies {
          match z.stance {
            Stance::NormalDeath => z.update_death_idx(5),
            Stance::CriticalDeath => z.update_death_idx(7),
            Stance::Walking => z.update_alive_idx(7),
            Stance::Still => z.update_alive_idx(3),
            _ => ()
          };
        }
      } else if self.fire_cool_down == 0.0 && c.stance == Stance::Firing {
        cs.update_fire();
      }

      if self.run_cool_down == 0.0 {
        for z in &mut zs.zombies {
          if let Stance::Running = z.stance {
            z.update_alive_idx(7)
          }
        }
      }

      let mut drawables: Vec<Drawables> = vec![];
      drawables.append(&mut bs.bullets.iter().map(|b| Drawables::Bullet(b)).collect());
      drawables.append(&mut zs.zombies.iter_mut().map(|z| Drawables::Zombie(z)).collect());

      for o in &obj.objects {
        match o.object_type {
          TerrainTexture::Ammo => drawables.push(Drawables::TerrainAmmo(o)),
          TerrainTexture::House => drawables.push(Drawables::TerrainHouse(o)),
          TerrainTexture::Tree => drawables.push(Drawables::TerrainTree(o)),
        };
      }

      drawables.push(Drawables::Character(c));

      drawables.sort_by(|a, b| {
        Drawables::get_vertical_pos(b)
          .partial_cmp(&Drawables::get_vertical_pos(a))
          .expect("Z-axis sorting failed")
      });

      for e in &mut drawables {
        match *e {
          Drawables::Bullet(ref e) => { self.bullet_system.draw(e, &mut encoder) }
          Drawables::Zombie(ref mut e) => { self.zombie_system.draw(e, &mut encoder) }
          Drawables::TerrainAmmo(ref mut e) => { self.terrain_object_system[0].draw(e, &mut encoder) }
          Drawables::TerrainHouse(ref mut e) => { self.terrain_object_system[1].draw(e, &mut encoder) }
          Drawables::TerrainTree(ref mut e) => { self.terrain_object_system[2].draw(e, &mut encoder) }
          Drawables::Character(ref mut e) => { self.character_system.draw(e, cs, &mut encoder) }
        }
      }
    }

    self.encoder_queue.sender.send(encoder).expect("Encoder queue update error");
  }
}
<commit_msg>Extract coolddowns updates to new function<commit_after>use std::time::Instant;

use gfx;
use specs;
use specs::prelude::{Read, WriteStorage};

use crate::bullet;
use crate::character;
use crate::critter::CharacterSprite;
use crate::game::constants::{CURRENT_AMMO_TEXT, HUD_TEXTS, VERSION_NUMBER_TEXT};
use crate::gfx_app::{ColorFormat, DepthFormat};
use crate::gfx_app::renderer::EncoderQueue;
use crate::graphics::{DeltaTime, orientation::Stance};
use crate::graphics::Drawables;
use crate::hud;
use crate::terrain;
use crate::terrain_object;
use crate::terrain_object::TerrainTexture;
use crate::zombie;

pub struct DrawSystem<D: gfx::Device> {
  render_target_view: gfx::handle::RenderTargetView<D::Resources, ColorFormat>,
  depth_stencil_view: gfx::handle::DepthStencilView<D::Resources, DepthFormat>,
  terrain_system: terrain::TerrainDrawSystem<D::Resources>,
  character_system: character::CharacterDrawSystem<D::Resources>,
  zombie_system: zombie::ZombieDrawSystem<D::Resources>,
  bullet_system: bullet::BulletDrawSystem<D::Resources>,
  terrain_object_system: [terrain_object::TerrainObjectDrawSystem<D::Resources>; 3],
  text_system: [hud::TextDrawSystem<D::Resources>; 3],
  encoder_queue: EncoderQueue<D>,
  game_time: Instant,
  frames: u32,
  cool_down: f64,
  run_cool_down: f64,
  fire_cool_down: f64,
}

impl<D: gfx::Device> DrawSystem<D> {
  pub fn new<F>(factory: &mut F,
                rtv: &gfx::handle::RenderTargetView<D::Resources, ColorFormat>,
                dsv: &gfx::handle::DepthStencilView<D::Resources, DepthFormat>,
                encoder_queue: EncoderQueue<D>)
                -> DrawSystem<D>
    where F: gfx::Factory<D::Resources> {
    DrawSystem {
      render_target_view: rtv.clone(),
      depth_stencil_view: dsv.clone(),
      terrain_system: terrain::TerrainDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      character_system: character::CharacterDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      zombie_system: zombie::ZombieDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      bullet_system: bullet::BulletDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      terrain_object_system: [
        terrain_object::TerrainObjectDrawSystem::new(factory, rtv.clone(), dsv.clone(), TerrainTexture::Ammo),
        terrain_object::TerrainObjectDrawSystem::new(factory, rtv.clone(), dsv.clone(), TerrainTexture::House),
        terrain_object::TerrainObjectDrawSystem::new(factory, rtv.clone(), dsv.clone(), TerrainTexture::Tree)
      ],
      text_system: [
        hud::TextDrawSystem::new(factory, &HUD_TEXTS, VERSION_NUMBER_TEXT, rtv.clone(), dsv.clone()),
        hud::TextDrawSystem::new(factory, &HUD_TEXTS, CURRENT_AMMO_TEXT, rtv.clone(), dsv.clone()),
        hud::TextDrawSystem::new(factory, &HUD_TEXTS, CURRENT_AMMO_TEXT, rtv.clone(), dsv.clone())
      ],
      encoder_queue,
      game_time: Instant::now(),
      frames: 0,
      cool_down: 1.0,
      run_cool_down: 1.0,
      fire_cool_down: 1.0,
    }
  }

  fn update_cooldown(&mut self, delta: f64) {
    if self.cool_down == 0.0 {
      self.cool_down += 0.05;
    }
    if self.fire_cool_down == 0.0 {
      self.fire_cool_down += 0.2;
    }
    if self.run_cool_down == 0.0 {
      self.run_cool_down += 0.02;
    }
    self.cool_down = (self.cool_down - delta).max(0.0);
    self.run_cool_down = (self.run_cool_down - delta).max(0.0);
    self.fire_cool_down = (self.fire_cool_down - delta).max(0.0);
  }
}

impl<'a, D> specs::prelude::System<'a> for DrawSystem<D>
  where D: gfx::Device,
        D::CommandBuffer: Send {
  type SystemData = (WriteStorage<'a, terrain::TerrainDrawable>,
                     WriteStorage<'a, character::CharacterDrawable>,
                     WriteStorage<'a, CharacterSprite>,
                     WriteStorage<'a, hud::hud_objects::HudObjects>,
                     WriteStorage<'a, zombie::zombies::Zombies>,
                     WriteStorage<'a, bullet::bullets::Bullets>,
                     WriteStorage<'a, terrain_object::terrain_objects::TerrainObjects>,
                     Read<'a, DeltaTime>);

  fn run(&mut self, (mut terrain, mut character, mut character_sprite, mut hud_objects, mut zombies, mut bullets, mut terrain_objects, dt): Self::SystemData) {
    use specs::join::Join;
    let mut encoder = self.encoder_queue.receiver
      .recv()
      .expect("Encoder error");

    self.update_cooldown(dt.0);

    let current_time = Instant::now();
    self.frames += 1;
    if cfg!(feature = "framerate") && (current_time.duration_since(self.game_time).as_secs()) >= 1 {
      println!("{:?} ms/frames", 1000.0 / f64::from(self.frames));
      self.frames = 0;
      self.game_time = Instant::now();
    }

    encoder.clear(&self.render_target_view, [16.0 / 256.0, 16.0 / 256.0, 20.0 / 256.0, 1.0]);
    encoder.clear_depth(&self.depth_stencil_view, 1.0);

    for (t, c, cs, hds, zs, bs, obj) in (&mut terrain, &mut character, &mut character_sprite, &mut hud_objects,
                                         &mut zombies, &mut bullets, &mut terrain_objects).join() {
      self.terrain_system.draw(t, &mut encoder);

      for hud in &mut hds.objects {
        self.text_system[0].draw(hud, &mut encoder);
        self.text_system[1].draw(hud, &mut encoder);
      }

      if self.cool_down == 0.0 {
        if c.stance == Stance::Walking {
          cs.update_run();
        }
        for z in &mut zs.zombies {
          match z.stance {
            Stance::NormalDeath => z.update_death_idx(5),
            Stance::CriticalDeath => z.update_death_idx(7),
            Stance::Walking => z.update_alive_idx(7),
            Stance::Still => z.update_alive_idx(3),
            _ => ()
          };
        }
      } else if self.fire_cool_down == 0.0 && c.stance == Stance::Firing {
        cs.update_fire();
      }

      if self.run_cool_down == 0.0 {
        for z in &mut zs.zombies {
          if let Stance::Running = z.stance {
            z.update_alive_idx(7)
          }
        }
      }

      let mut drawables: Vec<Drawables> = vec![];
      drawables.append(&mut bs.bullets.iter().map(|b| Drawables::Bullet(b)).collect());
      drawables.append(&mut zs.zombies.iter_mut().map(|z| Drawables::Zombie(z)).collect());

      for o in &obj.objects {
        match o.object_type {
          TerrainTexture::Ammo => drawables.push(Drawables::TerrainAmmo(o)),
          TerrainTexture::House => drawables.push(Drawables::TerrainHouse(o)),
          TerrainTexture::Tree => drawables.push(Drawables::TerrainTree(o)),
        };
      }

      drawables.push(Drawables::Character(c));

      drawables.sort_by(|a, b| {
        Drawables::get_vertical_pos(b)
          .partial_cmp(&Drawables::get_vertical_pos(a))
          .expect("Z-axis sorting failed")
      });

      for e in &mut drawables {
        match *e {
          Drawables::Bullet(ref e) => { self.bullet_system.draw(e, &mut encoder) }
          Drawables::Zombie(ref mut e) => { self.zombie_system.draw(e, &mut encoder) }
          Drawables::TerrainAmmo(ref mut e) => { self.terrain_object_system[0].draw(e, &mut encoder) }
          Drawables::TerrainHouse(ref mut e) => { self.terrain_object_system[1].draw(e, &mut encoder) }
          Drawables::TerrainTree(ref mut e) => { self.terrain_object_system[2].draw(e, &mut encoder) }
          Drawables::Character(ref mut e) => { self.character_system.draw(e, cs, &mut encoder) }
        }
      }
    }

    self.encoder_queue.sender.send(encoder).expect("Encoder queue update error");
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Tibor Benke <ihrwein@gmail.com>
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

use action::Action;
use context::base::BaseContext;
use dispatcher::Response;
use dispatcher::response::ResponseSender;
use message::{Message, MessageBuilder};

use std::borrow::Borrow;
use std::collections::BTreeMap;
use state::State;
use self::error::Error;
use self::renderer_context::RendererContext;
use super::ExecCondition;
use handlebars::{Handlebars, Context, Template};

pub use self::builder::MessageActionBuilder;

mod error;
mod renderer_context;
mod deser;
mod builder;
#[cfg(test)]
mod test;

pub const CONTEXT_UUID: &'static str = "context_uuid";
pub const CONTEXT_NAME: &'static str = "context_name";
pub const CONTEXT_LEN: &'static str = "context_len";
pub const MESSAGES: &'static str = "messages";
const MESSAGE: &'static str = "MESSAGE";

pub struct MessageAction {
    uuid: String,
    name: Option<String>,
    message: Template,
    values: Handlebars,
    when: ExecCondition,
    inject_mode: InjectMode,
}

impl MessageAction {
    pub fn uuid(&self) -> &String {
        &self.uuid
    }
    pub fn name(&self) -> Option<&String> {
        self.name.as_ref()
    }
    pub fn message(&self) -> &Template {
        &self.message
    }
    pub fn values(&self) -> &Handlebars {
        &self.values
    }
    pub fn inject_mode(&self) -> &InjectMode {
        &self.inject_mode
    }

    fn render_value(&self, key: &str, template_context: &Context) -> Result<String, Error> {
        let mut writer = Vec::new();
        {
            try!(self.values.renderw(key, &template_context, &mut writer));
        }
        let string = try!(String::from_utf8(writer));
        Ok(string)
    }

    fn render_values(&self, template_context: &Context) -> Result<BTreeMap<String, String>, Error> {
        let mut rendered_values = BTreeMap::new();
        for (key, _) in self.values.get_templates() {
            let rendered_value = try!(self.render_value(key, &template_context));
            rendered_values.insert(key.to_owned(), rendered_value);
        }
        Ok(rendered_values)
    }

    fn render_message(&self, state: &State, context: &BaseContext) -> Result<Message, Error> {
        let template_context = {
            use handlebars::Context;
            let context = RendererContext::new(state, context);
            Context::wraps(&context)
        };

        let mut rendered_values = try!(self.render_values(&template_context));
        MessageAction::extend_with_context_information(&mut rendered_values, state, context);
        let message = rendered_values.remove(MESSAGE)
                                     .expect(&format!("There is no '{}' key in the renderer \
                                                       key-value pairs",
                                                      MESSAGE));
        let name = self.name.as_ref().map(|name| name.borrow());
        let message = MessageBuilder::new(&self.uuid, message)
                          .name(name)
                          .values(rendered_values)
                          .build();
        Ok(message)
    }

    fn extend_with_context_information(values: &mut BTreeMap<String, String>,
                                       state: &State,
                                       context: &BaseContext) {
        values.insert(CONTEXT_UUID.to_owned(),
                      context.uuid().to_hyphenated_string());
        values.insert(CONTEXT_LEN.to_owned(), state.messages().len().to_string());
        if let Some(name) = context.name() {
            values.insert(CONTEXT_NAME.to_owned(), name.to_owned());
        }
    }

    fn execute(&self, state: &State, context: &BaseContext, responder: &mut ResponseSender) {
        match self.render_message(state, context) {
            Ok(message) => {
                let response = Alert {
                    message: message,
                    inject_mode: self.inject_mode.clone(),
                };
                responder.send_response(Response::Alert(response));
            }
            Err(error) => {
                error!("{}", error);
            }
        }
    }
}

impl From<MessageAction> for super::ActionType {
    fn from(action: MessageAction) -> super::ActionType {
        super::ActionType::Message(action)
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum InjectMode {
    Log,
    Forward,
    Loopback,
}

impl Default for InjectMode {
    fn default() -> InjectMode {
        InjectMode::Log
    }
}

#[derive(Debug, Clone)]
pub struct Alert {
    message: Message,
    inject_mode: InjectMode,
}

impl Alert {
    pub fn message(&self) -> &Message {
        &self.message
    }
}

impl Action for MessageAction {
    fn on_opened(&self, state: &State, context: &BaseContext, responder: &mut ResponseSender) {
        if self.when.on_opened {
            trace!("MessageAction: on_opened()");
            self.execute(state, context, responder);
        }
    }

    fn on_closed(&self, state: &State, context: &BaseContext, responder: &mut ResponseSender) {
        if self.when.on_closed {
            trace!("MessageAction: on_closed()");
            self.execute(state, context, responder);
        }
    }
}
<commit_msg>MessageAction: fix lint<commit_after>// Copyright (c) 2016 Tibor Benke <ihrwein@gmail.com>
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

use action::Action;
use context::base::BaseContext;
use dispatcher::Response;
use dispatcher::response::ResponseSender;
use message::{Message, MessageBuilder};

use std::borrow::Borrow;
use std::collections::BTreeMap;
use state::State;
use self::error::Error;
use self::renderer_context::RendererContext;
use super::ExecCondition;
use handlebars::{Handlebars, Context, Template};

pub use self::builder::MessageActionBuilder;

mod error;
mod renderer_context;
mod deser;
mod builder;
#[cfg(test)]
mod test;

pub const CONTEXT_UUID: &'static str = "context_uuid";
pub const CONTEXT_NAME: &'static str = "context_name";
pub const CONTEXT_LEN: &'static str = "context_len";
pub const MESSAGES: &'static str = "messages";
const MESSAGE: &'static str = "MESSAGE";

pub struct MessageAction {
    uuid: String,
    name: Option<String>,
    message: Template,
    values: Handlebars,
    when: ExecCondition,
    inject_mode: InjectMode,
}

impl MessageAction {
    pub fn uuid(&self) -> &String {
        &self.uuid
    }
    pub fn name(&self) -> Option<&String> {
        self.name.as_ref()
    }
    pub fn message(&self) -> &Template {
        &self.message
    }
    pub fn values(&self) -> &Handlebars {
        &self.values
    }
    pub fn inject_mode(&self) -> &InjectMode {
        &self.inject_mode
    }

    fn render_value(&self, key: &str, template_context: &Context) -> Result<String, Error> {
        let mut writer = Vec::new();
        {
            try!(self.values.renderw(key, &template_context, &mut writer));
        }
        let string = try!(String::from_utf8(writer));
        Ok(string)
    }

    fn render_values(&self, template_context: &Context) -> Result<BTreeMap<String, String>, Error> {
        let mut rendered_values = BTreeMap::new();
        for key in self.values.get_templates().keys() {
            let rendered_value = try!(self.render_value(key, &template_context));
            rendered_values.insert(key.to_owned(), rendered_value);
        }
        Ok(rendered_values)
    }

    fn render_message(&self, state: &State, context: &BaseContext) -> Result<Message, Error> {
        let template_context = {
            use handlebars::Context;
            let context = RendererContext::new(state, context);
            Context::wraps(&context)
        };

        let mut rendered_values = try!(self.render_values(&template_context));
        MessageAction::extend_with_context_information(&mut rendered_values, state, context);
        let message = rendered_values.remove(MESSAGE)
                                     .expect(&format!("There is no '{}' key in the renderer \
                                                       key-value pairs",
                                                      MESSAGE));
        let name = self.name.as_ref().map(|name| name.borrow());
        let message = MessageBuilder::new(&self.uuid, message)
                          .name(name)
                          .values(rendered_values)
                          .build();
        Ok(message)
    }

    fn extend_with_context_information(values: &mut BTreeMap<String, String>,
                                       state: &State,
                                       context: &BaseContext) {
        values.insert(CONTEXT_UUID.to_owned(),
                      context.uuid().to_hyphenated_string());
        values.insert(CONTEXT_LEN.to_owned(), state.messages().len().to_string());
        if let Some(name) = context.name() {
            values.insert(CONTEXT_NAME.to_owned(), name.to_owned());
        }
    }

    fn execute(&self, state: &State, context: &BaseContext, responder: &mut ResponseSender) {
        match self.render_message(state, context) {
            Ok(message) => {
                let response = Alert {
                    message: message,
                    inject_mode: self.inject_mode.clone(),
                };
                responder.send_response(Response::Alert(response));
            }
            Err(error) => {
                error!("{}", error);
            }
        }
    }
}

impl From<MessageAction> for super::ActionType {
    fn from(action: MessageAction) -> super::ActionType {
        super::ActionType::Message(action)
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum InjectMode {
    Log,
    Forward,
    Loopback,
}

impl Default for InjectMode {
    fn default() -> InjectMode {
        InjectMode::Log
    }
}

#[derive(Debug, Clone)]
pub struct Alert {
    message: Message,
    inject_mode: InjectMode,
}

impl Alert {
    pub fn message(&self) -> &Message {
        &self.message
    }
}

impl Action for MessageAction {
    fn on_opened(&self, state: &State, context: &BaseContext, responder: &mut ResponseSender) {
        if self.when.on_opened {
            trace!("MessageAction: on_opened()");
            self.execute(state, context, responder);
        }
    }

    fn on_closed(&self, state: &State, context: &BaseContext, responder: &mut ResponseSender) {
        if self.when.on_closed {
            trace!("MessageAction: on_closed()");
            self.execute(state, context, responder);
        }
    }
}
<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::fs::File;
use std::io::{Read, Write, Seek, SeekFrom};

trait Mbc {
    fn read(&self, address: u16) -> u8;
    fn write(&mut self, address: u16, v: u8);
}

struct Mbc0 {
    data: Vec<u8>,
    ram: [u8; 8192],
}

impl Mbc0 {
    pub fn new(data: Vec<u8>) -> Mbc0 {
        Mbc0 {
            data: data,
            ram: [0; 8192],
        }
    }
}

impl Mbc for Mbc0 {
    fn read(&self, address: u16) -> u8 {
        match address {
            0x0000 ... 0x7FFF => self.data[address as usize],
            0xA000 ... 0xBFFF => self.ram[(address as usize) - 0xA000],
            _ => unimplemented!(),
        }
    }

    fn write(&mut self, _: u16, _: u8) {
        // println!("Writing {:02X} to {:04X}", v, address);
        // match address {
        //    0xA000 ... 0xBFFF => self.ram[(address as usize) - 0xA000] = v,
        //    _ => unimplemented!(),
        //}
    }
}

#[allow(dead_code)]
#[derive(PartialEq, Eq)]
enum MemoryMode {
    C4_32,
    C16_8,
}

#[allow(dead_code)]
struct Mbc3 {
    selected_bank: usize,
    data: Vec<u8>,
    offset: usize,
    ram: RefCell<File>,
    memory_mode: MemoryMode,

    ram_offset: usize,
    ram_enabled: bool,
}

impl Mbc3 {
    pub fn new(data: Vec<u8>, mut disk: File) -> Mbc3 {
        let mut ram = vec![];
        disk.read_to_end(&mut ram).unwrap();

        if ram.len() < 32768 {
            println!("Warning: invalid file size, blanking ram.");
            disk.seek(SeekFrom::Start(0)).unwrap();
            disk.write_all(&[0; 32768]).unwrap();
        }

        Mbc3 {
            selected_bank: 1,
            data: data,
            offset: 0,
            ram: RefCell::new(disk),
            memory_mode: MemoryMode::C4_32,

            ram_offset: 0,
            ram_enabled: false,
        }
    }

    fn write_ram(&mut self, address: u16, v: u8) {
        if !self.ram_enabled {
            panic!("MBC3 RAM has not been enabled.");
        }

        let address = (address - 0xA000) as usize + self.ram_offset;
        self.ram.borrow_mut().seek(SeekFrom::Start(address as u64)).unwrap();
        self.ram.borrow_mut().write_all(&[v]).unwrap();
    }

    fn read_ram(&self, address: u16) -> u8 {
        if !self.ram_enabled {
            panic!("MBC3 RAM has not been enabled.");
        }

        let address = (address - 0xA000) as usize + self.ram_offset;
        self.ram.borrow_mut().seek(SeekFrom::Start(address as u64)).unwrap();
        let mut buffer = [0; 1];
        self.ram.borrow_mut().read_exact(&mut buffer).unwrap();

        buffer[0]
    }
}

impl Mbc for Mbc3 {
    fn read(&self, address: u16) -> u8 {
        match address {
            0x0000 ... 0x3FFF => self.data[address as usize],
            0x4000 ... 0x7FFF => self.data[address as usize + self.offset],
            0xA000 ... 0xBFFF => self.read_ram(address),
            _ => unimplemented!(),
        }
    }

    fn write(&mut self, address: u16, v: u8) {
        match address {
            0x0000 ... 0x1FFF => {
                match v {
                    0x00 => self.ram_enabled = false,
                    0x0A => self.ram_enabled = true,
                    _    => panic!("Unrecognized value for RAM enablement."),
                }
            },
            0x2000 ... 0x3FFF => {
                // Any write to this area will enable the bank of memory contained in v
                // if 0 is selected we will select 1 because 0 is already available
                // statically in 0 0000 - 3FFF
                if v > 0 {
                    self.offset = ((v - 1) as usize) * 0x4000;
                } else {
                    self.offset = 0x0000;
                }
                // println!("Setting offset to {:06X}", self.offset);
            },
            0x4000 ... 0x5FFF => {
                // Writing to this area will cause the controller to switch
                // banks of in-cartridge RAM.
                // Only the lowest two bits are relevant for this register.
                match v & 0b11 {
                    0x00 => self.ram_offset = 0,
                    0x01 => self.ram_offset = 8192,
                    0x02 => self.ram_offset = 16384,
                    0x03 => self.ram_offset = 24576,
                    _ => unimplemented!(),
                }
            },
            0x6000 ... 0x7FFF => {
                // println!("Attempt to write {:02X} to {:04X}", v, address);
                /* match v & 0x1 {
                    0x0 => self.memory_mode = MemoryMode::C16_8, // Memory mode 16_8,
                    0x1 => self.memory_mode = MemoryMode::C4_32,
                    _   => panic!(),
                }*/
            },
            0xA000 ... 0xBFFF => { self.write_ram(address, v); },
            _ => unimplemented!(),
        }
    }
}

pub struct MemoryController {
    controller: Box<Mbc>,
}

impl MemoryController {
    pub fn from_bytes(bytes: Vec<u8>, save_file: File) -> MemoryController {
        let controller = match bytes[0x147] {
            0x00 => Box::new(Mbc0::new(bytes)) as Box<Mbc>,
            0x0F | 0x10 | 0x11 | 0x12 | 0x13 | 0x01 => Box::new(Mbc3::new(bytes, save_file)) as Box<Mbc>,
            _ => {
                println!("Unrecognized type {:02X}", bytes[0x147]);
                panic!();
            }
        };

        MemoryController {
            controller: controller,
        }
    }

    pub fn read(&self, address: u16) -> u8 {
        self.controller.read(address)
    }

    pub fn write(&mut self, address: u16, v: u8) {
        self.controller.write(address, v);
    }
}
<commit_msg>Intial support for MBC1.<commit_after>use std::cell::RefCell;
use std::fs::File;
use std::io::{Read, Write, Seek, SeekFrom};

trait Mbc {
    fn read(&self, address: u16) -> u8;
    fn write(&mut self, address: u16, v: u8);
}

struct Mbc0 {
    data: Vec<u8>,
    ram: [u8; 8192],
}

impl Mbc0 {
    pub fn new(data: Vec<u8>) -> Mbc0 {
        Mbc0 {
            data: data,
            ram: [0; 8192],
        }
    }
}

impl Mbc for Mbc0 {
    fn read(&self, address: u16) -> u8 {
        match address {
            0x0000 ... 0x7FFF => self.data[address as usize],
            0xA000 ... 0xBFFF => self.ram[(address as usize) - 0xA000],
            _ => unimplemented!(),
        }
    }

    fn write(&mut self, _: u16, _: u8) {
        // Theoretically not supposed to write to the Mbc0 ROM, but some games do
        // it anyway.
    }
}

#[allow(dead_code)]
#[derive(PartialEq, Eq)]
enum MemoryMode {
    C4_32,
    C16_8,
}

enum MbcMode {
    Mbc3,
    Mbc1,
}

#[allow(dead_code)]
struct Mbc13 {
    selected_bank: usize,
    data: Vec<u8>,
    offset: usize,
    ram: RefCell<File>,

    ram_offset: usize,
    ram_enabled: bool,

    mode: MbcMode,
}

impl Mbc13 {
    pub fn new(data: Vec<u8>, mut disk: File, mode: MbcMode) -> Mbc13 {
        let mut ram = vec![];
        disk.read_to_end(&mut ram).unwrap();

        if ram.len() < 32768 {
            println!("Warning: invalid file size, blanking ram.");
            disk.seek(SeekFrom::Start(0)).unwrap();
            disk.write_all(&[0; 32768]).unwrap();
        }

        Mbc13 {
            selected_bank: 1,
            data: data,
            offset: 0,
            ram: RefCell::new(disk),

            ram_offset: 0,
            ram_enabled: false,

            mode: mode,
        }
    }

    fn write_ram(&mut self, address: u16, v: u8) {
        if !self.ram_enabled {
            panic!("MBC3 RAM has not been enabled.");
        }

        let address = (address - 0xA000) as usize + self.ram_offset;
        self.ram.borrow_mut().seek(SeekFrom::Start(address as u64)).unwrap();
        self.ram.borrow_mut().write_all(&[v]).unwrap();
    }

    fn read_ram(&self, address: u16) -> u8 {
        if !self.ram_enabled {
            panic!("MBC3 RAM has not been enabled.");
        }

        let address = (address - 0xA000) as usize + self.ram_offset;
        self.ram.borrow_mut().seek(SeekFrom::Start(address as u64)).unwrap();
        let mut buffer = [0; 1];
        self.ram.borrow_mut().read_exact(&mut buffer).unwrap();

        buffer[0]
    }

    fn switch_bank_mbc3(&mut self, v: u8) {
        // Any write to this area will enable the bank of memory contained in v
        // if 0 is selected we will select 1 because 0 is already available
        // statically in 0 0000 - 3FFF
        if v > 0 {
            self.offset = ((v - 1) as usize) * 0x4000;
        } else {
            self.offset = 0x0000;
        }
    }

    fn switch_bank_mbc1(&mut self, v: u8) {
        // There's a bug in MBC1 that makes it so that for v = 0x00, 0x20, 0x40, 0x60
        // the bank selected is actually the following one (v+1)
        let v_bug = match v & 0b11111 {
            0x00 | 0x20 | 0x40 | 0x60 => v + 1,
            _ => v,
        };

        self.offset = ((v_bug - 1) as usize) * 0x4000;
    }
}

impl Mbc for Mbc13 {
    fn read(&self, address: u16) -> u8 {
        match address {
            0x0000 ... 0x3FFF => self.data[address as usize],
            0x4000 ... 0x7FFF => self.data[address as usize + self.offset],
            0xA000 ... 0xBFFF => self.read_ram(address),
            _ => unimplemented!(),
        }
    }

    fn write(&mut self, address: u16, v: u8) {
        match address {
            0x0000 ... 0x1FFF => {
                match v {
                    0x00 => self.ram_enabled = false,
                    0x0A => self.ram_enabled = true,
                    _    => panic!("Unrecognized value for RAM enablement."),
                }
            },
            0x2000 ... 0x3FFF => {
                match self.mode {
                    MbcMode::Mbc1 => self.switch_bank_mbc1(v),
                    MbcMode::Mbc3 => self.switch_bank_mbc3(v),
                }
            },
            0x4000 ... 0x5FFF => {
                // Writing to this area will cause the controller to switch
                // banks of in-cartridge RAM.
                // Only the lowest two bits are relevant for this register.
                match v & 0b11 {
                    0x00 => self.ram_offset = 0,
                    0x01 => self.ram_offset = 8192,
                    0x02 => self.ram_offset = 16384,
                    0x03 => self.ram_offset = 24576,
                    _ => unimplemented!(),
                }
            },
            0x6000 ... 0x7FFF => {
                // TODO
            },
            0xA000 ... 0xBFFF => { self.write_ram(address, v); },
            _ => unimplemented!(),
        }
    }
}

pub struct MemoryController {
    controller: Box<Mbc>,
}

impl MemoryController {
    pub fn from_bytes(bytes: Vec<u8>, save_file: File) -> MemoryController {
        let controller = match bytes[0x147] {
            0x00 =>
                Box::new(Mbc0::new(bytes)) as Box<Mbc>,
            0x01 | 0x02 | 0x03 =>
                Box::new(Mbc13::new(bytes, save_file, MbcMode::Mbc1)) as Box<Mbc>,
            0x0F | 0x10 | 0x11 | 0x12 | 0x13 =>
                Box::new(Mbc13::new(bytes, save_file, MbcMode::Mbc3)) as Box<Mbc>,
            _ => {
                println!("Unrecognized type {:02X}", bytes[0x147]);
                panic!();
            }
        };

        MemoryController {
            controller: controller,
        }
    }

    pub fn read(&self, address: u16) -> u8 {
        self.controller.read(address)
    }

    pub fn write(&mut self, address: u16, v: u8) {
        self.controller.write(address, v);
    }
}
<|endoftext|>


<commit_before>// This file is part of rgtk.
//
// rgtk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// rgtk is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with rgtk.  If not, see <http://www.gnu.org/licenses/>.

use gtk::ffi;
use gtk::ffi::FFIWidget;
use gtk::traits;
use gtk::cast::GTK_PLACES_SIDEBAR;
use gtk;

struct_Widget!(PlacesSidebar)

impl PlacesSidebar {
    pub fn new() -> Option<PlacesSidebar> {
        let tmp_pointer = unsafe { ffi::gtk_places_sidebar_new() };
        check_pointer!(tmp_pointer, PlacesSidebar)
    }

    pub fn set_open_flags(&self, flags: gtk::enums::PlacesOpenFlags) {
        unsafe { ffi::gtk_places_sidebar_set_open_flags(GTK_PLACES_SIDEBAR(self.get_widget()), flags) }
    }

    pub fn get_open_flags(&self) -> gtk::enums::PlacesOpenFlags {
        unsafe { ffi::gtk_places_sidebar_get_open_flags(GTK_PLACES_SIDEBAR(self.get_widget())) }
    }

    pub fn set_show_desktop(&self, show_desktop: bool) {
        unsafe { ffi::gtk_places_sidebar_set_show_desktop(GTK_PLACES_SIDEBAR(self.get_widget()), ffi::to_gboolean(show_desktop)) }
    }

    pub fn get_show_desktop(&self) -> bool {
        unsafe { ffi::to_bool(ffi::gtk_places_sidebar_get_show_desktop(GTK_PLACES_SIDEBAR(self.get_widget()))) }
    }

    pub fn set_show_connect_to_server(&self, show_connect_to_server: bool) {
        unsafe { ffi::gtk_places_sidebar_set_show_connect_to_server(GTK_PLACES_SIDEBAR(self.get_widget()),
            ffi::to_gboolean(show_connect_to_server)) }
    }

    pub fn get_show_connect_to_server(&self) -> bool {
        unsafe { ffi::to_bool(ffi::gtk_places_sidebar_get_show_connect_to_server(GTK_PLACES_SIDEBAR(self.get_widget()))) }
    }

    pub fn set_local_only(&self, local_only: bool) {
        unsafe { ffi::gtk_places_sidebar_set_local_only(GTK_PLACES_SIDEBAR(self.get_widget()), ffi::to_gboolean(local_only)) }
    }

    pub fn get_local_only(&self) -> bool {
        unsafe { ffi::to_bool(ffi::gtk_places_sidebar_get_local_only(GTK_PLACES_SIDEBAR(self.get_widget()))) }
    }

    pub fn set_show_enter_location(&self, show_enter_location: bool) {
        unsafe { ffi::gtk_places_sidebar_set_show_enter_location(GTK_PLACES_SIDEBAR(self.get_widget()),
            ffi::to_gboolean(show_enter_location)) }
    }

    pub fn get_show_enter_location(&self) -> bool {
        unsafe { ffi::to_bool(ffi::gtk_places_sidebar_get_show_enter_location(GTK_PLACES_SIDEBAR(self.get_widget()))) }
    }
}

impl_drop!(PlacesSidebar)
impl_TraitWidget!(PlacesSidebar)

impl traits::Container for PlacesSidebar {}
impl traits::Bin for PlacesSidebar {}
impl traits::ScrolledWindow for PlacesSidebar {}

impl_widget_events!(PlacesSidebar)<commit_msg>Add widget's description<commit_after>// This file is part of rgtk.
//
// rgtk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// rgtk is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with rgtk.  If not, see <http://www.gnu.org/licenses/>.

//! GtkPlacesSidebar — Sidebar that displays frequently-used places in the file system

use gtk::ffi;
use gtk::ffi::FFIWidget;
use gtk::traits;
use gtk::cast::GTK_PLACES_SIDEBAR;
use gtk;

struct_Widget!(PlacesSidebar)

impl PlacesSidebar {
    pub fn new() -> Option<PlacesSidebar> {
        let tmp_pointer = unsafe { ffi::gtk_places_sidebar_new() };
        check_pointer!(tmp_pointer, PlacesSidebar)
    }

    pub fn set_open_flags(&self, flags: gtk::enums::PlacesOpenFlags) {
        unsafe { ffi::gtk_places_sidebar_set_open_flags(GTK_PLACES_SIDEBAR(self.get_widget()), flags) }
    }

    pub fn get_open_flags(&self) -> gtk::enums::PlacesOpenFlags {
        unsafe { ffi::gtk_places_sidebar_get_open_flags(GTK_PLACES_SIDEBAR(self.get_widget())) }
    }

    pub fn set_show_desktop(&self, show_desktop: bool) {
        unsafe { ffi::gtk_places_sidebar_set_show_desktop(GTK_PLACES_SIDEBAR(self.get_widget()), ffi::to_gboolean(show_desktop)) }
    }

    pub fn get_show_desktop(&self) -> bool {
        unsafe { ffi::to_bool(ffi::gtk_places_sidebar_get_show_desktop(GTK_PLACES_SIDEBAR(self.get_widget()))) }
    }

    pub fn set_show_connect_to_server(&self, show_connect_to_server: bool) {
        unsafe { ffi::gtk_places_sidebar_set_show_connect_to_server(GTK_PLACES_SIDEBAR(self.get_widget()),
            ffi::to_gboolean(show_connect_to_server)) }
    }

    pub fn get_show_connect_to_server(&self) -> bool {
        unsafe { ffi::to_bool(ffi::gtk_places_sidebar_get_show_connect_to_server(GTK_PLACES_SIDEBAR(self.get_widget()))) }
    }

    pub fn set_local_only(&self, local_only: bool) {
        unsafe { ffi::gtk_places_sidebar_set_local_only(GTK_PLACES_SIDEBAR(self.get_widget()), ffi::to_gboolean(local_only)) }
    }

    pub fn get_local_only(&self) -> bool {
        unsafe { ffi::to_bool(ffi::gtk_places_sidebar_get_local_only(GTK_PLACES_SIDEBAR(self.get_widget()))) }
    }

    pub fn set_show_enter_location(&self, show_enter_location: bool) {
        unsafe { ffi::gtk_places_sidebar_set_show_enter_location(GTK_PLACES_SIDEBAR(self.get_widget()),
            ffi::to_gboolean(show_enter_location)) }
    }

    pub fn get_show_enter_location(&self) -> bool {
        unsafe { ffi::to_bool(ffi::gtk_places_sidebar_get_show_enter_location(GTK_PLACES_SIDEBAR(self.get_widget()))) }
    }
}

impl_drop!(PlacesSidebar)
impl_TraitWidget!(PlacesSidebar)

impl traits::Container for PlacesSidebar {}
impl traits::Bin for PlacesSidebar {}
impl traits::ScrolledWindow for PlacesSidebar {}

impl_widget_events!(PlacesSidebar)<|endoftext|>


<commit_before><commit_msg>Auto merge of #2409 - glennw:fix-mips, r=nical<commit_after><|endoftext|>


<commit_before>use specs::*;

use amq_protocol_types::*;
use serde_json::Value;

use std::collections::BTreeMap;

/* Modified version of AMQProtocolDefinition to handle deserialization */
#[derive(Debug, Deserialize)]
pub struct _AMQProtocolDefinition {
    name:          ShortString,
    #[serde(rename="major-version")]
    major_version: ShortShortUInt,
    #[serde(rename="minor-version")]
    minor_version: ShortShortUInt,
    revision:      ShortShortUInt,
    port:          LongUInt,
    copyright:     Vec<LongString>,
    domains:       Vec<_AMQPDomain>,
    constants:     Vec<_AMQPConstant>,
    classes:       Vec<_AMQPClass>,
}

impl _AMQProtocolDefinition {
    pub fn to_specs(self) -> AMQProtocolDefinition {
        let domains = self.domains.iter().fold(BTreeMap::new(), |mut domains, domain| {
            domains.insert(domain.0.clone(), domain.1.to_specs());
            domains
        });
        let classes = self.classes.iter().map(|klass| klass.to_specs(&domains)).collect();
        AMQProtocolDefinition {
            name:          self.name,
            major_version: self.major_version,
            minor_version: self.minor_version,
            revision:      self.revision,
            port:          self.port,
            copyright:     self.copyright.iter().fold(LongString::new(), |acc, cur| acc + cur),
            domains:       domains,
            constants:     self.constants.iter().filter_map(|constant| if constant.klass.is_none() { Some(constant.to_specs()) } else { None }).collect(),
            soft_errors:   self.constants.iter().filter_map(|constant| if let Some(_AMQPErrorKind::Soft) = constant.klass { Some(constant.to_specs()) } else { None }).collect(),
            hard_errors:   self.constants.iter().filter_map(|constant| if let Some(_AMQPErrorKind::Hard) = constant.klass { Some(constant.to_specs()) } else { None }).collect(),
            classes:       classes,
        }
    }
}

/* Defined as a two-elems array in the spec */
#[derive(Debug, Deserialize)]
struct _AMQPDomain(ShortString, _AMQPType);

/* Subset of AMQPType used in specs for deserialization */
#[derive(Debug, Deserialize)]
enum _AMQPType {
    #[serde(rename="bit")]
    Bit,
    #[serde(rename="octet")]
    Octet,
    #[serde(rename="short")]
    Short,
    #[serde(rename="long")]
    Long,
    #[serde(rename="longlong")]
    LongLong,
    #[serde(rename="shortstr")]
    ShortStr,
    #[serde(rename="longstr")]
    LongStr,
    #[serde(rename="table")]
    Table,
    #[serde(rename="timestamp")]
    Timestamp,
}

impl _AMQPType {
    fn to_specs(&self) -> AMQPType {
        match *self {
            _AMQPType::Bit       => AMQPType::Boolean,
            _AMQPType::Octet     => AMQPType::ShortShortUInt,
            _AMQPType::Short     => AMQPType::ShortUInt,
            _AMQPType::Long      => AMQPType::LongUInt,
            _AMQPType::LongLong  => AMQPType::LongLongUInt,
            _AMQPType::ShortStr  => AMQPType::ShortString,
            _AMQPType::LongStr   => AMQPType::LongString,
            _AMQPType::Table     => AMQPType::FieldTable,
            _AMQPType::Timestamp => AMQPType::Timestamp,
        }
    }
}

#[derive(Debug, Deserialize)]
enum  _AMQPErrorKind {
    #[serde(rename="soft-error")]
    Soft,
    #[serde(rename="hard-error")]
    Hard,
}

#[derive(Debug, Deserialize)]
struct _AMQPConstant {
    pub name:   ShortString,
    pub value:  ShortUInt,
    #[serde(rename="class")]
    pub klass: Option<_AMQPErrorKind>,
}

impl _AMQPConstant {
    fn to_specs(&self) -> AMQPConstant {
        AMQPConstant {
            name:      self.name.clone(),
            value:     self.value,
            amqp_type: if self.value > 255 { AMQPType::ShortUInt } else { AMQPType::ShortShortUInt },
        }
    }
}

#[derive(Debug, Deserialize)]
struct _AMQPClass {
    id:         ShortUInt,
    methods:    Vec<_AMQPMethod>,
    name:       ShortString,
    properties: Option<Vec<_AMQPProperty>>,
}

impl _AMQPClass {
    fn to_specs(&self, domains: &BTreeMap<String, AMQPType>) -> AMQPClass {
        let properties     = match self.properties {
            Some(ref properties) => properties.iter().map(|prop| prop.to_specs()).collect(),
            None                 => Vec::new(),
        };
        AMQPClass {
            id:             self.id,
            methods:        self.methods.iter().map(|method| method.to_specs(domains)).collect(),
            name:           self.name.clone(),
            properties:     properties,
            has_properties: self.properties.as_ref().map(|p| !p.is_empty()).unwrap_or(false),
            is_connection:  self.id == 10,
        }
    }
}

#[derive(Debug, Deserialize)]
struct _AMQPMethod {
    id:          ShortUInt,
    arguments:   Vec<_AMQPArgument>,
    name:        ShortString,
    synchronous: Option<Boolean>,
}

impl _AMQPMethod {
    fn to_specs(&self, domains: &BTreeMap<ShortString, AMQPType>) -> AMQPMethod {
        let arguments = self.arguments_to_specs(domains);
        let has_arguments = !arguments.is_empty();
        let has_flags = arguments.iter().any(|arg| match *arg {
            AMQPArgument::Value(_) => false,
            AMQPArgument::Flags(_) => true,
        });
        AMQPMethod {
            id:            self.id,
            arguments:     arguments,
            has_arguments: has_arguments,
            has_flags:     has_flags,
            name:          self.name.clone(),
            synchronous:   self.synchronous.unwrap_or(false),
        }
    }

    fn arguments_to_specs(&self, domains: &BTreeMap<ShortString, AMQPType>) -> Vec<AMQPArgument> {
        let mut arguments                            = Vec::new();
        let mut flags : Option<Vec<AMQPFlagArgument>> = None;
        for argument in &self.arguments {
            let amqp_type = argument.get_type(domains);
            if amqp_type == AMQPType::Boolean {
                let mut flgs = flags.take().unwrap_or_else(|| Vec::new());
                flgs.push(argument.to_flag_specs());
                flags = Some(flgs);
            } else {
                if let Some(flags) = flags.take() {
                    arguments.push(AMQPArgument::Flags(flags));
                }
                arguments.push(AMQPArgument::Value(argument.to_value_specs(amqp_type)));
            }
        }
        if let Some(flags) = flags.take() {
            arguments.push(AMQPArgument::Flags(flags));
        }
        arguments
    }
}

#[derive(Debug, Deserialize)]
struct _AMQPArgument {
    #[serde(rename="type")]
    amqp_type:     Option<_AMQPType>,
    name:          ShortString,
    #[serde(rename="default-value")]
    default_value: Option<Value>,
    domain:        Option<ShortString>,
}

impl _AMQPArgument {
    fn to_flag_specs(&self) -> AMQPFlagArgument {
        AMQPFlagArgument {
            name:          self.name.clone(),
            default_value: self.default_value.as_ref().and_then(|v| v.as_u64()).map(|u| u != 0).unwrap_or(false),
        }
    }

    fn to_value_specs(&self, amqp_type: AMQPType) -> AMQPValueArgument {
        AMQPValueArgument {
            amqp_type:     amqp_type,
            name:          self.name.clone(),
            default_value: self.default_value.as_ref().map(From::from),
            domain:        self.domain.clone(),
        }
    }

    fn get_type(&self, domains: &BTreeMap<ShortString, AMQPType>) -> AMQPType {
        match self.amqp_type {
            Some(ref amqp_type) => amqp_type.to_specs(),
            None                => {
                let domain = match self.domain {
                    Some(ref domain) => domain,
                    None             => panic!(format!("{} has no type nor domain", self.name)),
                };
                domains.get(domain).expect(&format!("No {} domain exists", domain)).clone()
            },
        }
    }
}

#[derive(Debug, Deserialize)]
struct _AMQPProperty {
    #[serde(rename="type")]
    amqp_type: _AMQPType,
    name:      ShortString,
}

impl _AMQPProperty {
    fn to_specs(&self) -> AMQPProperty {
        AMQPProperty {
            amqp_type: self.amqp_type.to_specs(),
            name:      self.name.clone(),
        }
    }
}
<commit_msg>codegen: add test for internal conversion<commit_after>use specs::*;

use amq_protocol_types::*;
use serde_json::Value;

use std::collections::BTreeMap;

/* Modified version of AMQProtocolDefinition to handle deserialization */
#[derive(Debug, Deserialize)]
pub struct _AMQProtocolDefinition {
    name:          ShortString,
    #[serde(rename="major-version")]
    major_version: ShortShortUInt,
    #[serde(rename="minor-version")]
    minor_version: ShortShortUInt,
    revision:      ShortShortUInt,
    port:          LongUInt,
    copyright:     Vec<LongString>,
    domains:       Vec<_AMQPDomain>,
    constants:     Vec<_AMQPConstant>,
    classes:       Vec<_AMQPClass>,
}

impl _AMQProtocolDefinition {
    pub fn to_specs(self) -> AMQProtocolDefinition {
        let domains = self.domains.iter().fold(BTreeMap::new(), |mut domains, domain| {
            domains.insert(domain.0.clone(), domain.1.to_specs());
            domains
        });
        let classes = self.classes.iter().map(|klass| klass.to_specs(&domains)).collect();
        AMQProtocolDefinition {
            name:          self.name,
            major_version: self.major_version,
            minor_version: self.minor_version,
            revision:      self.revision,
            port:          self.port,
            copyright:     self.copyright.iter().fold(LongString::new(), |acc, cur| acc + cur),
            domains:       domains,
            constants:     self.constants.iter().filter_map(|constant| if constant.klass.is_none() { Some(constant.to_specs()) } else { None }).collect(),
            soft_errors:   self.constants.iter().filter_map(|constant| if let Some(_AMQPErrorKind::Soft) = constant.klass { Some(constant.to_specs()) } else { None }).collect(),
            hard_errors:   self.constants.iter().filter_map(|constant| if let Some(_AMQPErrorKind::Hard) = constant.klass { Some(constant.to_specs()) } else { None }).collect(),
            classes:       classes,
        }
    }
}

/* Defined as a two-elems array in the spec */
#[derive(Debug, Deserialize)]
struct _AMQPDomain(ShortString, _AMQPType);

/* Subset of AMQPType used in specs for deserialization */
#[derive(Debug, Deserialize)]
enum _AMQPType {
    #[serde(rename="bit")]
    Bit,
    #[serde(rename="octet")]
    Octet,
    #[serde(rename="short")]
    Short,
    #[serde(rename="long")]
    Long,
    #[serde(rename="longlong")]
    LongLong,
    #[serde(rename="shortstr")]
    ShortStr,
    #[serde(rename="longstr")]
    LongStr,
    #[serde(rename="table")]
    Table,
    #[serde(rename="timestamp")]
    Timestamp,
}

impl _AMQPType {
    fn to_specs(&self) -> AMQPType {
        match *self {
            _AMQPType::Bit       => AMQPType::Boolean,
            _AMQPType::Octet     => AMQPType::ShortShortUInt,
            _AMQPType::Short     => AMQPType::ShortUInt,
            _AMQPType::Long      => AMQPType::LongUInt,
            _AMQPType::LongLong  => AMQPType::LongLongUInt,
            _AMQPType::ShortStr  => AMQPType::ShortString,
            _AMQPType::LongStr   => AMQPType::LongString,
            _AMQPType::Table     => AMQPType::FieldTable,
            _AMQPType::Timestamp => AMQPType::Timestamp,
        }
    }
}

#[derive(Debug, Deserialize)]
enum  _AMQPErrorKind {
    #[serde(rename="soft-error")]
    Soft,
    #[serde(rename="hard-error")]
    Hard,
}

#[derive(Debug, Deserialize)]
struct _AMQPConstant {
    pub name:   ShortString,
    pub value:  ShortUInt,
    #[serde(rename="class")]
    pub klass: Option<_AMQPErrorKind>,
}

impl _AMQPConstant {
    fn to_specs(&self) -> AMQPConstant {
        AMQPConstant {
            name:      self.name.clone(),
            value:     self.value,
            amqp_type: if self.value > 255 { AMQPType::ShortUInt } else { AMQPType::ShortShortUInt },
        }
    }
}

#[derive(Debug, Deserialize)]
struct _AMQPClass {
    id:         ShortUInt,
    methods:    Vec<_AMQPMethod>,
    name:       ShortString,
    properties: Option<Vec<_AMQPProperty>>,
}

impl _AMQPClass {
    fn to_specs(&self, domains: &BTreeMap<String, AMQPType>) -> AMQPClass {
        let properties     = match self.properties {
            Some(ref properties) => properties.iter().map(|prop| prop.to_specs()).collect(),
            None                 => Vec::new(),
        };
        AMQPClass {
            id:             self.id,
            methods:        self.methods.iter().map(|method| method.to_specs(domains)).collect(),
            name:           self.name.clone(),
            properties:     properties,
            has_properties: self.properties.as_ref().map(|p| !p.is_empty()).unwrap_or(false),
            is_connection:  self.id == 10,
        }
    }
}

#[derive(Debug, Deserialize)]
struct _AMQPMethod {
    id:          ShortUInt,
    arguments:   Vec<_AMQPArgument>,
    name:        ShortString,
    synchronous: Option<Boolean>,
}

impl _AMQPMethod {
    fn to_specs(&self, domains: &BTreeMap<ShortString, AMQPType>) -> AMQPMethod {
        let arguments = self.arguments_to_specs(domains);
        let has_arguments = !arguments.is_empty();
        let has_flags = arguments.iter().any(|arg| match *arg {
            AMQPArgument::Value(_) => false,
            AMQPArgument::Flags(_) => true,
        });
        AMQPMethod {
            id:            self.id,
            arguments:     arguments,
            has_arguments: has_arguments,
            has_flags:     has_flags,
            name:          self.name.clone(),
            synchronous:   self.synchronous.unwrap_or(false),
        }
    }

    fn arguments_to_specs(&self, domains: &BTreeMap<ShortString, AMQPType>) -> Vec<AMQPArgument> {
        let mut arguments                            = Vec::new();
        let mut flags : Option<Vec<AMQPFlagArgument>> = None;
        for argument in &self.arguments {
            let amqp_type = argument.get_type(domains);
            if amqp_type == AMQPType::Boolean {
                let mut flgs = flags.take().unwrap_or_else(|| Vec::new());
                flgs.push(argument.to_flag_specs());
                flags = Some(flgs);
            } else {
                if let Some(flags) = flags.take() {
                    arguments.push(AMQPArgument::Flags(flags));
                }
                arguments.push(AMQPArgument::Value(argument.to_value_specs(amqp_type)));
            }
        }
        if let Some(flags) = flags.take() {
            arguments.push(AMQPArgument::Flags(flags));
        }
        arguments
    }
}

#[derive(Debug, Deserialize)]
struct _AMQPArgument {
    #[serde(rename="type")]
    amqp_type:     Option<_AMQPType>,
    name:          ShortString,
    #[serde(rename="default-value")]
    default_value: Option<Value>,
    domain:        Option<ShortString>,
}

impl _AMQPArgument {
    fn to_flag_specs(&self) -> AMQPFlagArgument {
        AMQPFlagArgument {
            name:          self.name.clone(),
            default_value: self.default_value.as_ref().and_then(|v| v.as_u64()).map(|u| u != 0).unwrap_or(false),
        }
    }

    fn to_value_specs(&self, amqp_type: AMQPType) -> AMQPValueArgument {
        AMQPValueArgument {
            amqp_type:     amqp_type,
            name:          self.name.clone(),
            default_value: self.default_value.as_ref().map(From::from),
            domain:        self.domain.clone(),
        }
    }

    fn get_type(&self, domains: &BTreeMap<ShortString, AMQPType>) -> AMQPType {
        match self.amqp_type {
            Some(ref amqp_type) => amqp_type.to_specs(),
            None                => {
                let domain = match self.domain {
                    Some(ref domain) => domain,
                    None             => panic!(format!("{} has no type nor domain", self.name)),
                };
                domains.get(domain).expect(&format!("No {} domain exists", domain)).clone()
            },
        }
    }
}

#[derive(Debug, Deserialize)]
struct _AMQPProperty {
    #[serde(rename="type")]
    amqp_type: _AMQPType,
    name:      ShortString,
}

impl _AMQPProperty {
    fn to_specs(&self) -> AMQPProperty {
        AMQPProperty {
            amqp_type: self.amqp_type.to_specs(),
            name:      self.name.clone(),
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_convert_to_specs() {
        let def      = _AMQProtocolDefinition {
            name:          "amqp".to_string(),
            major_version: 0,
            minor_version: 9,
            revision:      1,
            port:          5672,
            copyright:     vec!["foo".to_string(), "bar".to_string()],
            domains:       vec![_AMQPDomain("d1".to_string(), _AMQPType::Bit)],
            constants:     vec![
                _AMQPConstant {
                    name:  "c1".to_string(),
                    value: 42,
                    klass: None,
                },
                _AMQPConstant {
                    name:  "c2".to_string(),
                    value: 43,
                    klass: Some(_AMQPErrorKind::Soft),
                },
                _AMQPConstant {
                    name:  "c3".to_string(),
                    value: 256,
                    klass: Some(_AMQPErrorKind::Hard),
                },
            ],
            classes:       vec![_AMQPClass {
                id:         42,
                methods:    vec![_AMQPMethod {
                    id:          42,
                    arguments:   vec![_AMQPArgument {
                        amqp_type:     Some(_AMQPType::Short),
                        name:          "arg1".to_string(),
                        default_value: None,
                        domain:        None,
                    }],
                    name:        "meth1".to_string(),
                    synchronous: None,
                }],
                name:       "class1".to_string(),
                properties: Some(vec![_AMQPProperty {
                    amqp_type: _AMQPType::Octet,
                    name:     "prop1".to_string(),
                }]),
            }],
        };
        let mut dom  = BTreeMap::new();
        dom.insert("d1".to_string(), AMQPType::Boolean);
        let expected = AMQProtocolDefinition {
            name:          "amqp".to_string(),
            major_version: 0,
            minor_version: 9,
            revision:      1,
            port:          5672,
            copyright:     "foobar".to_string(),
            domains:       dom,
            constants:     vec![AMQPConstant {
                name:      "c1".to_string(),
                value:     42,
                amqp_type: AMQPType::ShortShortUInt,
            }],
            soft_errors:   vec![AMQPConstant {
                name:      "c2".to_string(),
                value:     43,
                amqp_type: AMQPType::ShortShortUInt,
            }],
            hard_errors:   vec![AMQPConstant {
                name:      "c3".to_string(),
                value:     256,
                amqp_type: AMQPType::ShortUInt,
            }],
            classes:       vec![AMQPClass {
                id:             42,
                methods:        vec![AMQPMethod {
                    id:            42,
                    arguments:     vec![AMQPArgument::Value(AMQPValueArgument {
                        amqp_type:    AMQPType::ShortUInt,
                        name:         "arg1".to_string(),
                        default_value: None,
                        domain:        None,
                    })],
                    name:          "meth1".to_string(),
                    synchronous:   false,
                    has_arguments: true,
                    has_flags:     false,
                }],
                name:           "class1".to_string(),
                properties:     vec![AMQPProperty {
                    amqp_type: AMQPType::ShortShortUInt,
                    name:      "prop1".to_string(),
                }],
                has_properties: true,
                is_connection:  false,
            }],
        };
        assert_eq!(def.to_specs(), expected);
    }
}
<|endoftext|>


<commit_before>use crate::borrow::Cow;
use core::iter::FromIterator;

use super::Vec;

#[stable(feature = "cow_from_vec", since = "1.8.0")]
impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> {
    fn from(s: &'a [T]) -> Cow<'a, [T]> {
        Cow::Borrowed(s)
    }
}

#[stable(feature = "cow_from_vec", since = "1.8.0")]
impl<'a, T: Clone> From<Vec<T>> for Cow<'a, [T]> {
    fn from(v: Vec<T>) -> Cow<'a, [T]> {
        Cow::Owned(v)
    }
}

#[stable(feature = "cow_from_vec_ref", since = "1.28.0")]
impl<'a, T: Clone> From<&'a Vec<T>> for Cow<'a, [T]> {
    fn from(v: &'a Vec<T>) -> Cow<'a, [T]> {
        Cow::Borrowed(v.as_slice())
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> FromIterator<T> for Cow<'a, [T]>
where
    T: Clone,
{
    fn from_iter<I: IntoIterator<Item = T>>(it: I) -> Cow<'a, [T]> {
        Cow::Owned(FromIterator::from_iter(it))
    }
}
<commit_msg>Document `From` impls for cow.rs<commit_after>use crate::borrow::Cow;
use core::iter::FromIterator;

use super::Vec;

#[stable(feature = "cow_from_vec", since = "1.8.0")]
impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> {
    /// Creates a [`Borrowed`] variant of [`Cow`]
    /// from a slice.
    ///
    /// This conversion does not allocate or clone the data.
    ///
    /// [`Borrowed`]: crate::borrow::Cow::Borrowed
    fn from(s: &'a [T]) -> Cow<'a, [T]> {
        Cow::Borrowed(s)
    }
}

#[stable(feature = "cow_from_vec", since = "1.8.0")]
impl<'a, T: Clone> From<Vec<T>> for Cow<'a, [T]> {
    /// Creates an [`Owned`] variant of [`Cow`]
    /// from an owned instance of [`Vec`].
    ///
    /// This conversion does not allocate or clone the data.
    ///
    /// [`Owned`]: crate::borrow::Cow::Owned
    fn from(v: Vec<T>) -> Cow<'a, [T]> {
        Cow::Owned(v)
    }
}

#[stable(feature = "cow_from_vec_ref", since = "1.28.0")]
impl<'a, T: Clone> From<&'a Vec<T>> for Cow<'a, [T]> {
    /// Creates a [`Borrowed`] variant of [`Cow`]
    /// from a reference to [`Vec`].
    ///
    /// This conversion does not allocate or clone the data.
    ///
    /// [`Borrowed`]: crate::borrow::Cow::Borrowed
    fn from(v: &'a Vec<T>) -> Cow<'a, [T]> {
        Cow::Borrowed(v.as_slice())
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> FromIterator<T> for Cow<'a, [T]>
where
    T: Clone,
{
    fn from_iter<I: IntoIterator<Item = T>>(it: I) -> Cow<'a, [T]> {
        Cow::Owned(FromIterator::from_iter(it))
    }
}
<|endoftext|>


<commit_before>use screen::*;
use piston_window;

pub struct MainMenuScreen;

impl Screen for MainMenuScreen {
    fn on_input(&mut self, input: &piston_window::Input) -> InputResults {
        // TODO: FIXME:
        use piston_window::{Input, Button, MouseButton};

        let mut result = Vec::new();

        match input {
            &Input::Press(Button::Mouse(MouseButton::Left)) => {
                result.push(InputResult::PushScreen(Box::new(BattleScreen::new())));
            }
            _ => {}
        }

        result
    }

    fn on_draw(&mut self, args: &piston_window::RenderArgs, window: &piston_window::PistonWindow) {
        window.draw_2d(|context, graphics| {
            piston_window::clear([0., 0., 1., 1.0], graphics);
        });
    }

    fn on_update(&mut self, args: &piston_window::UpdateArgs) {
    }
}
<commit_msg>Menu screen: pop previous window<commit_after>use screen::*;
use piston_window;

pub struct MainMenuScreen;

impl Screen for MainMenuScreen {
    fn on_input(&mut self, input: &piston_window::Input) -> InputResults {
        // TODO: FIXME:
        use piston_window::{Input, Button, MouseButton};

        let mut result = Vec::new();

        match input {
            &Input::Press(Button::Mouse(MouseButton::Left)) => {
                result.push(InputResult::PopScreen);
                result.push(InputResult::PushScreen(Box::new(BattleScreen::new())));
            }
            _ => {}
        }

        result
    }

    fn on_draw(&mut self, args: &piston_window::RenderArgs, window: &piston_window::PistonWindow) {
        window.draw_2d(|context, graphics| {
            piston_window::clear([0., 0., 1., 1.0], graphics);
        });
    }

    fn on_update(&mut self, args: &piston_window::UpdateArgs) {
    }
}
<|endoftext|>


<commit_before><commit_msg>Minor Encode.rs Cleanup<commit_after><|endoftext|>


<commit_before>use failure::{Error, ResultExt};
use lucet_wasi_sdk::Link;
use lucetc::bindings::Bindings;
use lucetc::load;
use parity_wasm::elements::Module;
use std::collections::HashMap;
use std::path::PathBuf;
use std::str;
use tempfile;

fn module_from_c(cfiles: &[&str], exports: &[&str]) -> Result<Module, Error> {
    let cfiles: Vec<PathBuf> = cfiles
        .iter()
        .map(|ref name| PathBuf::from(format!("tests/wasi-sdk/{}.c", name)))
        .collect();
    let tempdir = tempfile::Builder::new()
        .prefix("wasi-sdk-test")
        .tempdir()
        .context("tempdir creation")?;

    let mut wasm = PathBuf::from(tempdir.path());
    wasm.push("out.wasm");

    let mut linker = Link::new(cfiles.clone())
        .cflag("-nostartfiles")
        .ldflag("--no-entry")
        .ldflag("--allow-undefined");
    for export in exports {
        linker.with_ldflag(&format!("--export={}", export));
    }
    linker.link(wasm.clone())?;

    let m = load::read_module(&wasm).context(format!("loading module built from {:?}", cfiles))?;
    Ok(m)
}

fn b_only_test_bindings() -> Bindings {
    let imports: HashMap<String, String> = [
        ("a".into(), "a".into()), // b_only
    ]
    .iter()
    .cloned()
    .collect();

    Bindings::env(imports)
}

mod programs {
    use super::{b_only_test_bindings, module_from_c};
    use cranelift_module::Linkage;
    use lucetc::bindings::Bindings;
    use lucetc::compile;
    use lucetc::compiler::OptLevel;
    use lucetc::program::{HeapSettings, Program};

    fn num_import_globals(p: &Program) -> usize {
        p.globals()
            .iter()
            .filter_map(|g| g.as_import())
            .collect::<Vec<_>>()
            .len()
    }

    fn num_export_functions(p: &Program) -> usize {
        p.defined_functions()
            .iter()
            .filter(|f| f.linkage() == Linkage::Export)
            .collect::<Vec<_>>()
            .len()
    }

    #[test]
    fn empty() {
        let m = module_from_c(&["empty"], &[]).expect("build module for empty");
        let b = Bindings::empty();
        let h = HeapSettings::default();
        let p = Program::new(m, b, h).expect("create program for empty");
        assert_eq!(p.import_functions().len(), 0, "import functions");
        assert_eq!(num_import_globals(&p), 0, "import globals");
        assert_eq!(num_export_functions(&p), 0, "export functions");
        let _c = compile(&p, "empty".into(), OptLevel::Best).expect("compile empty");
    }

    #[test]
    fn just_a() {
        let m = module_from_c(&["a"], &["a"]).expect("build module for a");
        let b = Bindings::empty();
        let h = HeapSettings::default();
        let p = Program::new(m, b, h).expect("create program for a");
        assert_eq!(p.import_functions().len(), 0, "import functions");
        assert_eq!(num_import_globals(&p), 0, "import globals");
        assert_eq!(num_export_functions(&p), 1, "export functions");
        let _c = compile(&p, "a_only".into(), OptLevel::Best).expect("compile a");
    }

    #[test]
    fn just_b() {
        let m = module_from_c(&["b"], &["b"]).expect("build module for b");
        let b = b_only_test_bindings();
        let h = HeapSettings::default();
        let p = Program::new(m, b, h).expect("create program for b");
        assert_eq!(p.import_functions().len(), 1, "import functions");
        assert_eq!(num_import_globals(&p), 0, "import globals");
        assert_eq!(num_export_functions(&p), 1, "export functions");
        let _c = compile(&p, "b_only".into(), OptLevel::Best).expect("compile b");
    }

    #[test]
    fn a_and_b() {
        let m = module_from_c(&["a", "b"], &["a", "b"]).expect("build module for a & b");
        let b = Bindings::empty();
        let h = HeapSettings::default();
        let p = Program::new(m, b, h).expect("create program for a & b");
        assert_eq!(p.import_functions().len(), 0, "import functions");
        assert_eq!(num_import_globals(&p), 0, "import globals");
        assert_eq!(num_export_functions(&p), 2, "export functions");
        let _c = compile(&p, "a_and_b".into(), OptLevel::Best).expect("compile a & b");
    }

}
<commit_msg>lucetc: fixup test that uses wasi-sdk api<commit_after>use failure::{Error, ResultExt};
use lucet_wasi_sdk::Link;
use lucetc::bindings::Bindings;
use lucetc::load;
use parity_wasm::elements::Module;
use std::collections::HashMap;
use std::path::PathBuf;
use std::str;
use tempfile;

fn module_from_c(cfiles: &[&str], exports: &[&str]) -> Result<Module, Error> {
    let cfiles: Vec<PathBuf> = cfiles
        .iter()
        .map(|ref name| PathBuf::from(format!("tests/wasi-sdk/{}.c", name)))
        .collect();
    let tempdir = tempfile::Builder::new()
        .prefix("wasi-sdk-test")
        .tempdir()
        .context("tempdir creation")?;

    let mut wasm = PathBuf::from(tempdir.path());
    wasm.push("out.wasm");

    let mut linker = Link::new(&cfiles)
        .cflag("-nostartfiles")
        .ldflag("--no-entry")
        .ldflag("--allow-undefined");
    for export in exports {
        linker.with_ldflag(&format!("--export={}", export));
    }
    linker.link(wasm.clone())?;

    let m = load::read_module(&wasm).context(format!("loading module built from {:?}", cfiles))?;
    Ok(m)
}

fn b_only_test_bindings() -> Bindings {
    let imports: HashMap<String, String> = [
        ("a".into(), "a".into()), // b_only
    ]
    .iter()
    .cloned()
    .collect();

    Bindings::env(imports)
}

mod programs {
    use super::{b_only_test_bindings, module_from_c};
    use cranelift_module::Linkage;
    use lucetc::bindings::Bindings;
    use lucetc::compile;
    use lucetc::compiler::OptLevel;
    use lucetc::program::{HeapSettings, Program};

    fn num_import_globals(p: &Program) -> usize {
        p.globals()
            .iter()
            .filter_map(|g| g.as_import())
            .collect::<Vec<_>>()
            .len()
    }

    fn num_export_functions(p: &Program) -> usize {
        p.defined_functions()
            .iter()
            .filter(|f| f.linkage() == Linkage::Export)
            .collect::<Vec<_>>()
            .len()
    }

    #[test]
    fn empty() {
        let m = module_from_c(&["empty"], &[]).expect("build module for empty");
        let b = Bindings::empty();
        let h = HeapSettings::default();
        let p = Program::new(m, b, h).expect("create program for empty");
        assert_eq!(p.import_functions().len(), 0, "import functions");
        assert_eq!(num_import_globals(&p), 0, "import globals");
        assert_eq!(num_export_functions(&p), 0, "export functions");
        let _c = compile(&p, "empty".into(), OptLevel::Best).expect("compile empty");
    }

    #[test]
    fn just_a() {
        let m = module_from_c(&["a"], &["a"]).expect("build module for a");
        let b = Bindings::empty();
        let h = HeapSettings::default();
        let p = Program::new(m, b, h).expect("create program for a");
        assert_eq!(p.import_functions().len(), 0, "import functions");
        assert_eq!(num_import_globals(&p), 0, "import globals");
        assert_eq!(num_export_functions(&p), 1, "export functions");
        let _c = compile(&p, "a_only".into(), OptLevel::Best).expect("compile a");
    }

    #[test]
    fn just_b() {
        let m = module_from_c(&["b"], &["b"]).expect("build module for b");
        let b = b_only_test_bindings();
        let h = HeapSettings::default();
        let p = Program::new(m, b, h).expect("create program for b");
        assert_eq!(p.import_functions().len(), 1, "import functions");
        assert_eq!(num_import_globals(&p), 0, "import globals");
        assert_eq!(num_export_functions(&p), 1, "export functions");
        let _c = compile(&p, "b_only".into(), OptLevel::Best).expect("compile b");
    }

    #[test]
    fn a_and_b() {
        let m = module_from_c(&["a", "b"], &["a", "b"]).expect("build module for a & b");
        let b = Bindings::empty();
        let h = HeapSettings::default();
        let p = Program::new(m, b, h).expect("create program for a & b");
        assert_eq!(p.import_functions().len(), 0, "import functions");
        assert_eq!(num_import_globals(&p), 0, "import globals");
        assert_eq!(num_export_functions(&p), 2, "export functions");
        let _c = compile(&p, "a_and_b".into(), OptLevel::Best).expect("compile a & b");
    }

}
<|endoftext|>


<commit_before>pub fn range(lo: uint, hi: uint, it: |uint|) {
    let mut iter = lo;
    while iter < hi {
        it(iter);
        iter += 1;
    }
}

#[inline]
pub fn to_str_bytes(num: int, radix: int, f: |u8|) {
    let neg = num < 0;
    let mut deccum = if neg { -num } else { num };

    // Radix can be as low as 2, so we need 64 characters for a number
    // near 2^64, plus another one for a possible '-' character.
    let mut buf = [0u8, ..65];
    let mut cur = 0;

    loop {
        let digit = deccum % radix;
        buf[cur] = match digit as u8 {
            i @ 0..9 => '0' as u8 + i,
            i        => 'a' as u8 + (i-10),
        };
        cur += 1;
        deccum /= radix as int;
        if deccum == 0 { break; }
    }

    if neg {
        f('-' as u8);
    }

    while cur > 0 {
        cur -= 1;
        f(buf[cur]);
    }
}
<commit_msg>Fix to_str_bytes<commit_after>use core::fail::assert;

pub fn range(lo: uint, hi: uint, it: |uint|) {
    let mut iter = lo;
    while iter < hi {
        it(iter);
        iter += 1;
    }
}

macro_rules! int_module (($T:ty, $bits:expr) => (

#[inline]
pub fn to_str_bytes(num: $T, radix: uint, f: |u8|) {
    assert(2 <= radix && radix <= 36);
    let neg = num < 0;

    // Radix can be as low as 2, so we need 64 characters for a number
    // near 2^64, plus another one for a possible '-' character.
    let mut buf = [0u8, ..65];
    let mut cur = 0;

    // TODO: test overflow
    let mut deccum = num / radix as $T;
    let mut digit = num % radix as $T;

    // Calculate the absolute value after dividing the whole number once,
    // because a U2 representable negative number doesn't necessarily have
    // a unique inverse of the same type.
    // Example: -128i8 == 128i8. For radix=2, -128i8/2 = -64i8 != 64i8.
    if neg {
        deccum = -deccum;
        digit = -digit;
    }

    loop {
        buf[cur] = match digit as u8 {
            i @ 0..9 => '0' as u8 + i,
            i        => 'a' as u8 + (i-10),
        };
        cur += 1;
        deccum /= radix as $T;
        if deccum == 0 { break; }
        digit = deccum % radix as $T;
    }

    if neg {
        f('-' as u8);
    }

    while cur > 0 {
        cur -= 1;
        f(buf[cur]);
    }
}

))

#[cfg(target_word_size = "32")] int_module!(int, 32)
#[cfg(target_word_size = "64")] int_module!(int, 64)
<|endoftext|>