<commit_before>use error::{RuntimeError, VoidResult};
use frame::GPUFrame;

use super::display::LinuxDisplay;
use super::window::{LinuxWindow, PollEventsIterator};
use super::context::{Context, create_context};

pub struct LinuxApplication {
   display: LinuxDisplay,
   window: LinuxWindow,
   context: Box<Context>,
}

impl LinuxApplication {
   pub fn new(
      display: LinuxDisplay,
      title: &str,
      x: i32, y: i32,
      width: u32, height: u32
   ) -> Result<Self, RuntimeError> {

      let window = try!(LinuxWindow::new(
         &display, title, x, y, width, height,
      ));

      let context = try!(
         create_context(&display.display, &display.screen_id, &window.window)
      );

      Ok(LinuxApplication {
         display: display,
         window: window,
         context: context,
      })
   }

   #[inline]
   pub fn create_gpu_frame(
      &self, width: u32, height: u32
   ) -> Result<Box<GPUFrame>, RuntimeError> {
      self.context.create_gpu_frame(width, height)
   }

   #[inline]
   pub fn screen_size(&self) -> (u32, u32) {
      self.display.screen_size()
   }

   #[inline]
   pub fn poll_events(&self) -> PollEventsIterator {
      self.window.poll_events()
   }

   #[inline]
   pub fn swap_buffers(&self) -> VoidResult {
      self.context.swap_buffers()
   }
}
<commit_msg>Freetype loading for Linux<commit_after>use error::{RuntimeError, VoidResult};
use frame::GPUFrame;

use sys::utils::fn_ptr::FnPtrLibrary;

use sys::dl;
use sys::ft;

use super::display::LinuxDisplay;
use super::window::{LinuxWindow, PollEventsIterator};
use super::context::{Context, create_context};

pub struct LinuxApplication {
   pub display: LinuxDisplay,
   pub window: LinuxWindow,
   pub context: Box<Context>,
   pub freetype: dl::Library,
}

impl LinuxApplication {
   pub fn new(
      display: LinuxDisplay,
      title: &str,
      x: i32, y: i32,
      width: u32, height: u32
   ) -> Result<Self, RuntimeError> {

      let window = try!(LinuxWindow::new(
         &display, title, x, y, width, height,
      ));

      let context = try!(
         create_context(&display.display, &display.screen_id, &window.window)
      );

      let freetype = LinuxApplication::load_freetype();

      Ok(LinuxApplication {
         display: display,
         window: window,
         context: context,
         freetype: freetype,
      })
   }

   #[inline]
   pub fn load_freetype() -> dl::Library {
      let library = dl::Library::open("libfreetype.so.6").unwrap();

      ft::load(&library);

      library
   }

   #[inline]
   pub fn create_gpu_frame(
      &self, width: u32, height: u32
   ) -> Result<Box<GPUFrame>, RuntimeError> {
      self.context.create_gpu_frame(width, height)
   }

   #[inline]
   pub fn screen_size(&self) -> (u32, u32) {
      self.display.screen_size()
   }

   #[inline]
   pub fn poll_events(&self) -> PollEventsIterator {
      self.window.poll_events()
   }

   #[inline]
   pub fn swap_buffers(&self) -> VoidResult {
      self.context.swap_buffers()
   }
}
<|endoftext|>


<commit_before>//! checks for attributes

use reexport::*;
use rustc::lint::*;
use rustc::hir::*;
use semver::Version;
use syntax::ast::{Attribute, Lit, LitKind, MetaItemKind};
use syntax::codemap::Span;
use utils::{in_macro, match_path, span_lint, span_lint_and_then, snippet_opt};
use utils::paths;

/// **What it does:** Checks for items annotated with `#[inline(always)]`,
/// unless the annotated function is empty or simply panics.
///
/// **Why is this bad?** While there are valid uses of this annotation (and once
/// you know when to use it, by all means `allow` this lint), it's a common
/// newbie-mistake to pepper one's code with it.
///
/// As a rule of thumb, before slapping `#[inline(always)]` on a function,
/// measure if that additional function call really affects your runtime profile
/// sufficiently to make up for the increase in compile time.
///
/// **Known problems:** False positives, big time. This lint is meant to be
/// deactivated by everyone doing serious performance work. This means having
/// done the measurement.
///
/// **Example:**
/// ```rust
/// #[inline(always)]
/// fn not_quite_hot_code(..) { ... }
/// ```
declare_lint! {
    pub INLINE_ALWAYS,
    Warn,
    "use of `#[inline(always)]`"
}

/// **What it does:** Checks for `extern crate` and `use` items annotated with lint attributes
///
/// **Why is this bad?** Lint attributes have no effect on crate imports. Most likely a `!` was forgotten
///
/// **Known problems:** Technically one might allow `unused_import` on a `use` item, but it's easier to remove the unused item.
///
/// **Example:**
/// ```rust
/// #[deny(dead_code)]
/// extern crate foo;
/// #[allow(unused_import)]
/// use foo::bar;
/// ```
declare_lint! {
    pub USELESS_ATTRIBUTE,
    Warn,
    "use of lint attributes on `extern crate` items"
}

/// **What it does:** Checks for `#[deprecated]` annotations with a `since`
/// field that is not a valid semantic version.
///
/// **Why is this bad?** For checking the version of the deprecation, it must be
/// a valid semver. Failing that, the contained information is useless.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// #[deprecated(since = "forever")]
/// fn something_else(..) { ... }
/// ```
declare_lint! {
    pub DEPRECATED_SEMVER,
    Warn,
    "use of `#[deprecated(since = \"x\")]` where x is not semver"
}

#[derive(Copy,Clone)]
pub struct AttrPass;

impl LintPass for AttrPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(INLINE_ALWAYS, DEPRECATED_SEMVER, USELESS_ATTRIBUTE)
    }
}

impl LateLintPass for AttrPass {
    fn check_attribute(&mut self, cx: &LateContext, attr: &Attribute) {
        if let MetaItemKind::List(ref name, ref items) = attr.node.value.node {
            if items.is_empty() || name != &"deprecated" {
                return;
            }
            for item in items {
                if let MetaItemKind::NameValue(ref name, ref lit) = item.node {
                    if name == &"since" {
                        check_semver(cx, item.span, lit);
                    }
                }
            }
        }
    }

    fn check_item(&mut self, cx: &LateContext, item: &Item) {
        if is_relevant_item(item) {
            check_attrs(cx, item.span, &item.name, &item.attrs)
        }
        match item.node {
            ItemExternCrate(_) |
            ItemUse(_) => {
                for attr in &item.attrs {
                    if let MetaItemKind::List(ref name, _) = attr.node.value.node {
                        match &**name {
                            "allow" | "warn" | "deny" | "forbid" => {
                                if let Some(mut sugg) = snippet_opt(cx, attr.span) {
                                    if sugg.len() > 1 {
                                        span_lint_and_then(cx, USELESS_ATTRIBUTE, attr.span,
                                                           "useless lint attribute",
                                                           |db| {
                                            sugg.insert(1, '!');
                                            db.span_suggestion(attr.span, "if you just forgot a `!`, use", sugg);
                                        });
                                    }
                                }
                            },
                            _ => {},
                        }
                    }
                }
            },
            _ => {},
        }
    }

    fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) {
        if is_relevant_impl(item) {
            check_attrs(cx, item.span, &item.name, &item.attrs)
        }
    }

    fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) {
        if is_relevant_trait(item) {
            check_attrs(cx, item.span, &item.name, &item.attrs)
        }
    }
}

fn is_relevant_item(item: &Item) -> bool {
    if let ItemFn(_, _, _, _, _, ref block) = item.node {
        is_relevant_block(block)
    } else {
        false
    }
}

fn is_relevant_impl(item: &ImplItem) -> bool {
    match item.node {
        ImplItemKind::Method(_, ref block) => is_relevant_block(block),
        _ => false,
    }
}

fn is_relevant_trait(item: &TraitItem) -> bool {
    match item.node {
        MethodTraitItem(_, None) => true,
        MethodTraitItem(_, Some(ref block)) => is_relevant_block(block),
        _ => false,
    }
}

fn is_relevant_block(block: &Block) -> bool {
    for stmt in &block.stmts {
        match stmt.node {
            StmtDecl(_, _) => return true,
            StmtExpr(ref expr, _) |
            StmtSemi(ref expr, _) => {
                return is_relevant_expr(expr);
            }
        }
    }
    block.expr.as_ref().map_or(false, |e| is_relevant_expr(e))
}

fn is_relevant_expr(expr: &Expr) -> bool {
    match expr.node {
        ExprBlock(ref block) => is_relevant_block(block),
        ExprRet(Some(ref e)) => is_relevant_expr(e),
        ExprRet(None) | ExprBreak(_) => false,
        ExprCall(ref path_expr, _) => {
            if let ExprPath(_, ref path) = path_expr.node {
                !match_path(path, &paths::BEGIN_PANIC)
            } else {
                true
            }
        }
        _ => true,
    }
}

fn check_attrs(cx: &LateContext, span: Span, name: &Name, attrs: &[Attribute]) {
    if in_macro(cx, span) {
        return;
    }

    for attr in attrs {
        if let MetaItemKind::List(ref inline, ref values) = attr.node.value.node {
            if values.len() != 1 || inline != &"inline" {
                continue;
            }
            if let MetaItemKind::Word(ref always) = values[0].node {
                if always != &"always" {
                    continue;
                }
                span_lint(cx,
                          INLINE_ALWAYS,
                          attr.span,
                          &format!("you have declared `#[inline(always)]` on `{}`. This is usually a bad idea",
                                   name));
            }
        }
    }
}

fn check_semver(cx: &LateContext, span: Span, lit: &Lit) {
    if let LitKind::Str(ref is, _) = lit.node {
        if Version::parse(&*is).is_ok() {
            return;
        }
    }
    span_lint(cx,
              DEPRECATED_SEMVER,
              span,
              "the since field must contain a semver-compliant version");
}
<commit_msg>`unused_import` is a valid lint to be changed on `use` statements<commit_after>//! checks for attributes

use reexport::*;
use rustc::lint::*;
use rustc::hir::*;
use semver::Version;
use syntax::ast::{Attribute, Lit, LitKind, MetaItemKind};
use syntax::codemap::Span;
use utils::{in_macro, match_path, span_lint, span_lint_and_then, snippet_opt};
use utils::paths;

/// **What it does:** Checks for items annotated with `#[inline(always)]`,
/// unless the annotated function is empty or simply panics.
///
/// **Why is this bad?** While there are valid uses of this annotation (and once
/// you know when to use it, by all means `allow` this lint), it's a common
/// newbie-mistake to pepper one's code with it.
///
/// As a rule of thumb, before slapping `#[inline(always)]` on a function,
/// measure if that additional function call really affects your runtime profile
/// sufficiently to make up for the increase in compile time.
///
/// **Known problems:** False positives, big time. This lint is meant to be
/// deactivated by everyone doing serious performance work. This means having
/// done the measurement.
///
/// **Example:**
/// ```rust
/// #[inline(always)]
/// fn not_quite_hot_code(..) { ... }
/// ```
declare_lint! {
    pub INLINE_ALWAYS,
    Warn,
    "use of `#[inline(always)]`"
}

/// **What it does:** Checks for `extern crate` and `use` items annotated with lint attributes
///
/// **Why is this bad?** Lint attributes have no effect on crate imports. Most likely a `!` was forgotten
///
/// **Known problems:** Technically one might allow `unused_import` on a `use` item, but it's easier to remove the unused item.
///
/// **Example:**
/// ```rust
/// #[deny(dead_code)]
/// extern crate foo;
/// #[allow(unused_import)]
/// use foo::bar;
/// ```
declare_lint! {
    pub USELESS_ATTRIBUTE,
    Warn,
    "use of lint attributes on `extern crate` items"
}

/// **What it does:** Checks for `#[deprecated]` annotations with a `since`
/// field that is not a valid semantic version.
///
/// **Why is this bad?** For checking the version of the deprecation, it must be
/// a valid semver. Failing that, the contained information is useless.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// #[deprecated(since = "forever")]
/// fn something_else(..) { ... }
/// ```
declare_lint! {
    pub DEPRECATED_SEMVER,
    Warn,
    "use of `#[deprecated(since = \"x\")]` where x is not semver"
}

#[derive(Copy,Clone)]
pub struct AttrPass;

impl LintPass for AttrPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(INLINE_ALWAYS, DEPRECATED_SEMVER, USELESS_ATTRIBUTE)
    }
}

impl LateLintPass for AttrPass {
    fn check_attribute(&mut self, cx: &LateContext, attr: &Attribute) {
        if let MetaItemKind::List(ref name, ref items) = attr.node.value.node {
            if items.is_empty() || name != &"deprecated" {
                return;
            }
            for item in items {
                if let MetaItemKind::NameValue(ref name, ref lit) = item.node {
                    if name == &"since" {
                        check_semver(cx, item.span, lit);
                    }
                }
            }
        }
    }

    fn check_item(&mut self, cx: &LateContext, item: &Item) {
        if is_relevant_item(item) {
            check_attrs(cx, item.span, &item.name, &item.attrs)
        }
        match item.node {
            ItemExternCrate(_) |
            ItemUse(_) => {
                for attr in &item.attrs {
                    if let MetaItemKind::List(ref name, ref lint_list) = attr.node.value.node {
                        match &**name {
                            "allow" | "warn" | "deny" | "forbid" => {
                                // whitelist `unused_imports`
                                for lint in lint_list {
                                    if let MetaItemKind::Word(ref word) = lint.node {
                                        if word == "unused_imports" {
                                            if let ItemUse(_) = item.node {
                                                return;
                                            }
                                        }
                                    }
                                }
                                if let Some(mut sugg) = snippet_opt(cx, attr.span) {
                                    if sugg.len() > 1 {
                                        span_lint_and_then(cx, USELESS_ATTRIBUTE, attr.span,
                                                           "useless lint attribute",
                                                           |db| {
                                            sugg.insert(1, '!');
                                            db.span_suggestion(attr.span, "if you just forgot a `!`, use", sugg);
                                        });
                                    }
                                }
                            },
                            _ => {},
                        }
                    }
                }
            },
            _ => {},
        }
    }

    fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) {
        if is_relevant_impl(item) {
            check_attrs(cx, item.span, &item.name, &item.attrs)
        }
    }

    fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) {
        if is_relevant_trait(item) {
            check_attrs(cx, item.span, &item.name, &item.attrs)
        }
    }
}

fn is_relevant_item(item: &Item) -> bool {
    if let ItemFn(_, _, _, _, _, ref block) = item.node {
        is_relevant_block(block)
    } else {
        false
    }
}

fn is_relevant_impl(item: &ImplItem) -> bool {
    match item.node {
        ImplItemKind::Method(_, ref block) => is_relevant_block(block),
        _ => false,
    }
}

fn is_relevant_trait(item: &TraitItem) -> bool {
    match item.node {
        MethodTraitItem(_, None) => true,
        MethodTraitItem(_, Some(ref block)) => is_relevant_block(block),
        _ => false,
    }
}

fn is_relevant_block(block: &Block) -> bool {
    for stmt in &block.stmts {
        match stmt.node {
            StmtDecl(_, _) => return true,
            StmtExpr(ref expr, _) |
            StmtSemi(ref expr, _) => {
                return is_relevant_expr(expr);
            }
        }
    }
    block.expr.as_ref().map_or(false, |e| is_relevant_expr(e))
}

fn is_relevant_expr(expr: &Expr) -> bool {
    match expr.node {
        ExprBlock(ref block) => is_relevant_block(block),
        ExprRet(Some(ref e)) => is_relevant_expr(e),
        ExprRet(None) | ExprBreak(_) => false,
        ExprCall(ref path_expr, _) => {
            if let ExprPath(_, ref path) = path_expr.node {
                !match_path(path, &paths::BEGIN_PANIC)
            } else {
                true
            }
        }
        _ => true,
    }
}

fn check_attrs(cx: &LateContext, span: Span, name: &Name, attrs: &[Attribute]) {
    if in_macro(cx, span) {
        return;
    }

    for attr in attrs {
        if let MetaItemKind::List(ref inline, ref values) = attr.node.value.node {
            if values.len() != 1 || inline != &"inline" {
                continue;
            }
            if let MetaItemKind::Word(ref always) = values[0].node {
                if always != &"always" {
                    continue;
                }
                span_lint(cx,
                          INLINE_ALWAYS,
                          attr.span,
                          &format!("you have declared `#[inline(always)]` on `{}`. This is usually a bad idea",
                                   name));
            }
        }
    }
}

fn check_semver(cx: &LateContext, span: Span, lit: &Lit) {
    if let LitKind::Str(ref is, _) = lit.node {
        if Version::parse(&*is).is_ok() {
            return;
        }
    }
    span_lint(cx,
              DEPRECATED_SEMVER,
              span,
              "the since field must contain a semver-compliant version");
}
<|endoftext|>


<commit_before>use game::{Game, View, ViewAction};
use game::data::Rectangle;
use game::gfx::{CopySprite, Sprite};
use data::load_character;
use sdl2::pixels::Color;
use sdl2::render::Renderer;
use sdl2::rect::Point;
use conv::prelude::*;

const PLAYER_SPEED: f64 = 150.0;
const CHARACTER_W: f64 = 56.0;
const CHARACTER_H: f64 = 43.0;

const TERRAIN_W: f64 = 100.0;
const TERRAIN_H: f64 = 50.0;

const TILES_W: usize = 32;
const TILES_H: usize = 20;

#[derive(Clone)]
struct Background {
  pos: f64,
  sprite: Sprite,
}

impl Background {
  fn render(&mut self, renderer: &mut Renderer) {
    let size = self.sprite.size();

    let (_, window_h) = renderer.output_size().unwrap();
    renderer.copy_sprite(&self.sprite, Rectangle {
      x: 0.0,
      y: 0.0,
      w: size.0,
      h: window_h as f64,
    })
  }
}

#[derive(Clone, Copy)]
enum CharacterFrame {
  Still = 0,
  Right = 1,
  UpRight = 28,
  Up = 56,
  UpLeft = 84,
  Left = 108,
  DownLeft = 122,
  Down = 150,
  DownRight = 178
}

#[derive(Clone, Copy)]
enum TerrainFrame {
  Sand = 0,
  Grass = 1,
}

struct Character {
  rect: Rectangle,
  sprites: Vec<Sprite>,
  current: CharacterFrame,
  anim_index: u32
}

struct TerrainTile {
  rect: Rectangle,
  terrain_sprites: Vec<Sprite>,
  current: TerrainFrame,
}

pub struct GameView {
  player: Character,
  tiles: Vec<TerrainTile>,
  background: Background,
}

impl GameView {
  pub fn new(game: &mut Game) -> GameView {
    let spritesheet = Sprite::load(&mut game.renderer, "assets/character.png").unwrap();
    let character_datapoints = load_character();
    let terrain_spritesheet = Sprite::load(&mut game.renderer, "assets/terrain.png").unwrap();
    let mut sprites = Vec::with_capacity(256);
    let mut terrain_sprites = Vec::with_capacity(TILES_W);
    let mut tiles = Vec::with_capacity(TILES_W * TILES_H * 2);

    for x in 0..3 {
      terrain_sprites.push(terrain_spritesheet.region(Rectangle {
        w: TERRAIN_W,
        h: TERRAIN_H,
        x: TERRAIN_W * x as f64,
        y: 0.0 as f64,
      }).unwrap());
    }

    for x in 0..194 {
      sprites.push(spritesheet.region(character_datapoints[x]).unwrap());
    }

    for x in 0..TILES_W {
      for y in 0..TILES_H {
        let x2: f64 = 100.0 * 1.5 as f64;
        let y2: f64 = 50.0 * 1.5 as f64;
        tiles.push(TerrainTile {
          rect: Rectangle {
            x: 100.0 * x as f64,
            y: 50.0 * y as f64,
            w: TERRAIN_W,
            h: TERRAIN_H,
          },
          terrain_sprites: terrain_sprites.clone(),
          current: TerrainFrame::Grass,
        });

        tiles.push(TerrainTile {
          rect: Rectangle {
            x: 100.0 * f64::value_from((x+1)).unwrap() - x2 as f64,
            y: 50.0 * f64::value_from((y+1)).unwrap() - y2 as f64,
            w: TERRAIN_W,
            h: TERRAIN_H,
          },
          terrain_sprites: terrain_sprites.clone(),
          current: TerrainFrame::Sand,
        });
      }
    }

    GameView {
      player: Character {
        rect: Rectangle {
          x: 64.0,
          y: 64.0,
          w: CHARACTER_W,
          h: CHARACTER_H,
        },
        sprites: sprites.clone(),
        current: CharacterFrame::Down,
        anim_index: 0
      },

      tiles: tiles,

      background: Background {
        pos: 0.0,
        sprite: Sprite::load(&mut game.renderer, "assets/background.png").unwrap(),
      },
    }
  }
}

impl View for GameView {
  fn render(&mut self, game: &mut Game, elapsed: f64) -> ViewAction {
    if game.events.now.quit || game.events.now.key_escape == Some(true) {
      return ViewAction::Quit;
    }

    let diagonal = (game.events.key_up ^ game.events.key_down) && (game.events.key_left ^ game.events.key_right);
    let moved = if diagonal { 1.0 / 2.0f64.sqrt() } else { 1.0 } * PLAYER_SPEED * elapsed;
    let dx = match (game.events.key_left, game.events.key_right) {
      (true, true) | (false, false) => 0.0,
      (true, false) => -moved,
      (false, true) => moved,
    };

    let dy = match (game.events.key_up, game.events.key_down) {
      (true, true) | (false, false) => 0.0,
      (true, false) => -moved,
      (false, true) => moved,
    };

    self.player.rect.x += dx;
    self.player.rect.y += (dy / 2.0);

    let movable_region = Rectangle {
      x: 0.0,
      y: 0.0,
      w: game.output_size().0,
      h: game.output_size().1,
    };

    self.player.rect = self.player.rect.move_inside(movable_region).unwrap();
    self.player.current =
    if dx == 0.0 && dy < 0.0       { CharacterFrame::Up }
    else if dx > 0.0 && dy < 0.0   { CharacterFrame::UpRight }
    else if dx < 0.0 && dy < 0.0   { CharacterFrame::UpLeft }
    else if dx == 0.0 && dy == 0.0 { CharacterFrame::Still }
    else if dx > 0.0 && dy == 0.0  { CharacterFrame::Right }
    else if dx < 0.0 && dy == 0.0  { CharacterFrame::Left }
    else if dx == 0.0 && dy > 0.0  { CharacterFrame::Down }
    else if dx > 0.0 && dy > 0.0   { CharacterFrame::DownRight }
    else if dx < 0.0 && dy > 0.0   { CharacterFrame::DownLeft }
    else { unreachable!() };

    game.renderer.set_draw_color(Color::RGBA(120, 120, 120, 0));
    self.background.render(&mut game.renderer);
    game.renderer.clear();

    for x in 0..TILES_W {
      for y in 0..TILES_H {
        let index = x * TILES_H + y;
        game.renderer.copy_sprite(&self.tiles[index].terrain_sprites[self.tiles[index].current as usize], self.tiles[index].rect);
      }
    }

    match game.events.mouse_click {
      Some(m) => {
        game.renderer.set_draw_color(Color::RGBA(255, 0, 0, 0));
        let _ = game.renderer.draw_line(Point::new(m.0, m.1 ), Point::new(m.0 - 10, m.1));
      },
      None => {},
    }

    // player
    game.renderer.set_draw_color(Color::RGBA(119,119,119,0));

    game.renderer.copy_sprite(&self.player.sprites[self.player.current as usize + self.player.anim_index as usize], self.player.rect);
    self.player.anim_index =
      if dx == 0.0 && dy == 0.0 { 0u32 }
      else if self.player.anim_index < 13u32 { self.player.anim_index + 1u32 }
      else { 0u32 };

    ViewAction::None
  }
}
<commit_msg>Remove extra parenthesis<commit_after>use game::{Game, View, ViewAction};
use game::data::Rectangle;
use game::gfx::{CopySprite, Sprite};
use data::load_character;
use sdl2::pixels::Color;
use sdl2::render::Renderer;
use sdl2::rect::Point;
use conv::prelude::*;

const PLAYER_SPEED: f64 = 150.0;
const CHARACTER_W: f64 = 56.0;
const CHARACTER_H: f64 = 43.0;

const TERRAIN_W: f64 = 100.0;
const TERRAIN_H: f64 = 50.0;

const TILES_W: usize = 32;
const TILES_H: usize = 20;

#[derive(Clone)]
struct Background {
  pos: f64,
  sprite: Sprite,
}

impl Background {
  fn render(&mut self, renderer: &mut Renderer) {
    let size = self.sprite.size();

    let (_, window_h) = renderer.output_size().unwrap();
    renderer.copy_sprite(&self.sprite, Rectangle {
      x: 0.0,
      y: 0.0,
      w: size.0,
      h: window_h as f64,
    })
  }
}

#[derive(Clone, Copy)]
enum CharacterFrame {
  Still = 0,
  Right = 1,
  UpRight = 28,
  Up = 56,
  UpLeft = 84,
  Left = 108,
  DownLeft = 122,
  Down = 150,
  DownRight = 178
}

#[derive(Clone, Copy)]
enum TerrainFrame {
  Sand = 0,
  Grass = 1,
}

struct Character {
  rect: Rectangle,
  sprites: Vec<Sprite>,
  current: CharacterFrame,
  anim_index: u32
}

struct TerrainTile {
  rect: Rectangle,
  terrain_sprites: Vec<Sprite>,
  current: TerrainFrame,
}

pub struct GameView {
  player: Character,
  tiles: Vec<TerrainTile>,
  background: Background,
}

impl GameView {
  pub fn new(game: &mut Game) -> GameView {
    let spritesheet = Sprite::load(&mut game.renderer, "assets/character.png").unwrap();
    let character_datapoints = load_character();
    let terrain_spritesheet = Sprite::load(&mut game.renderer, "assets/terrain.png").unwrap();
    let mut sprites = Vec::with_capacity(256);
    let mut terrain_sprites = Vec::with_capacity(TILES_W);
    let mut tiles = Vec::with_capacity(TILES_W * TILES_H * 2);

    for x in 0..3 {
      terrain_sprites.push(terrain_spritesheet.region(Rectangle {
        w: TERRAIN_W,
        h: TERRAIN_H,
        x: TERRAIN_W * x as f64,
        y: 0.0 as f64,
      }).unwrap());
    }

    for x in 0..194 {
      sprites.push(spritesheet.region(character_datapoints[x]).unwrap());
    }

    for x in 0..TILES_W {
      for y in 0..TILES_H {
        let x2: f64 = 100.0 * 1.5 as f64;
        let y2: f64 = 50.0 * 1.5 as f64;
        tiles.push(TerrainTile {
          rect: Rectangle {
            x: 100.0 * x as f64,
            y: 50.0 * y as f64,
            w: TERRAIN_W,
            h: TERRAIN_H,
          },
          terrain_sprites: terrain_sprites.clone(),
          current: TerrainFrame::Grass,
        });

        tiles.push(TerrainTile {
          rect: Rectangle {
            x: 100.0 * f64::value_from((x+1)).unwrap() - x2 as f64,
            y: 50.0 * f64::value_from((y+1)).unwrap() - y2 as f64,
            w: TERRAIN_W,
            h: TERRAIN_H,
          },
          terrain_sprites: terrain_sprites.clone(),
          current: TerrainFrame::Sand,
        });
      }
    }

    GameView {
      player: Character {
        rect: Rectangle {
          x: 64.0,
          y: 64.0,
          w: CHARACTER_W,
          h: CHARACTER_H,
        },
        sprites: sprites.clone(),
        current: CharacterFrame::Down,
        anim_index: 0
      },

      tiles: tiles,

      background: Background {
        pos: 0.0,
        sprite: Sprite::load(&mut game.renderer, "assets/background.png").unwrap(),
      },
    }
  }
}

impl View for GameView {
  fn render(&mut self, game: &mut Game, elapsed: f64) -> ViewAction {
    if game.events.now.quit || game.events.now.key_escape == Some(true) {
      return ViewAction::Quit;
    }

    let diagonal = (game.events.key_up ^ game.events.key_down) && (game.events.key_left ^ game.events.key_right);
    let moved = if diagonal { 1.0 / 2.0f64.sqrt() } else { 1.0 } * PLAYER_SPEED * elapsed;
    let dx = match (game.events.key_left, game.events.key_right) {
      (true, true) | (false, false) => 0.0,
      (true, false) => -moved,
      (false, true) => moved,
    };

    let dy = match (game.events.key_up, game.events.key_down) {
      (true, true) | (false, false) => 0.0,
      (true, false) => -moved,
      (false, true) => moved,
    };

    self.player.rect.x += dx;
    self.player.rect.y += dy / 2.0;

    let movable_region = Rectangle {
      x: 0.0,
      y: 0.0,
      w: game.output_size().0,
      h: game.output_size().1,
    };

    self.player.rect = self.player.rect.move_inside(movable_region).unwrap();
    self.player.current =
    if dx == 0.0 && dy < 0.0       { CharacterFrame::Up }
    else if dx > 0.0 && dy < 0.0   { CharacterFrame::UpRight }
    else if dx < 0.0 && dy < 0.0   { CharacterFrame::UpLeft }
    else if dx == 0.0 && dy == 0.0 { CharacterFrame::Still }
    else if dx > 0.0 && dy == 0.0  { CharacterFrame::Right }
    else if dx < 0.0 && dy == 0.0  { CharacterFrame::Left }
    else if dx == 0.0 && dy > 0.0  { CharacterFrame::Down }
    else if dx > 0.0 && dy > 0.0   { CharacterFrame::DownRight }
    else if dx < 0.0 && dy > 0.0   { CharacterFrame::DownLeft }
    else { unreachable!() };

    game.renderer.set_draw_color(Color::RGBA(120, 120, 120, 0));
    self.background.render(&mut game.renderer);
    game.renderer.clear();

    for x in 0..TILES_W {
      for y in 0..TILES_H {
        let index = x * TILES_H + y;
        game.renderer.copy_sprite(&self.tiles[index].terrain_sprites[self.tiles[index].current as usize], self.tiles[index].rect);
      }
    }

    match game.events.mouse_click {
      Some(m) => {
        game.renderer.set_draw_color(Color::RGBA(255, 0, 0, 0));
        let _ = game.renderer.draw_line(Point::new(m.0, m.1 ), Point::new(m.0 - 10, m.1));
      },
      None => {},
    }

    // player
    game.renderer.set_draw_color(Color::RGBA(119,119,119,0));

    game.renderer.copy_sprite(&self.player.sprites[self.player.current as usize + self.player.anim_index as usize], self.player.rect);
    self.player.anim_index =
      if dx == 0.0 && dy == 0.0 { 0u32 }
      else if self.player.anim_index < 13u32 { self.player.anim_index + 1u32 }
      else { 0u32 };

    ViewAction::None
  }
}
<|endoftext|>


<commit_before>use game::{Game, View, ViewAction};
use game::data::Rectangle;
use game::gfx::{CopySprite, Sprite};
use views::background::Background;
use data::load_character;
use sdl2::pixels::Color;
use sdl2::render::Renderer;
use sdl2::rect::Point;
use conv::prelude::*;

mod background;

const PLAYER_SPEED: f64 = 150.0;
const CHARACTER_W: f64 = 56.0;
const CHARACTER_H: f64 = 43.0;

const TERRAIN_W: f64 = 100.0;
const TERRAIN_H: f64 = 50.0;

const TILES_W: usize = 32;
const TILES_H: usize = 20;

#[derive(Clone, Copy)]
enum CharacterFrame {
  Still = 0,
  Right = 1,
  UpRight = 28,
  Up = 56,
  UpLeft = 84,
  Left = 108,
  DownLeft = 122,
  Down = 150,
  DownRight = 178
}

#[derive(Clone, Copy)]
enum TerrainFrame {
  Sand = 0,
  Grass = 1,
}

struct Character {
  rect: Rectangle,
  sprites: Vec<Sprite>,
  current: CharacterFrame,
  heading: CharacterFrame,
  anim_index: u32
}

struct TerrainTile {
  rect: Rectangle,
  terrain_sprites: Vec<Sprite>,
  current: TerrainFrame,
}

pub struct GameView {
  player: Character,
  tiles: Vec<TerrainTile>,
  background: Background,
}

impl GameView {
  pub fn new(game: &mut Game) -> GameView {
    let spritesheet = Sprite::load(&mut game.renderer, "assets/character.png").unwrap();
    let character_datapoints = load_character();
    let terrain_spritesheet = Sprite::load(&mut game.renderer, "assets/terrain.png").unwrap();
    let mut sprites = Vec::with_capacity(256);
    let mut terrain_sprites = Vec::with_capacity(TILES_W);
    let mut tiles = Vec::with_capacity(TILES_W * TILES_H * 2);

    for x in 0..3 {
      terrain_sprites.push(terrain_spritesheet.region(Rectangle {
        w: TERRAIN_W,
        h: TERRAIN_H,
        x: TERRAIN_W * x as f64,
        y: 0.0 as f64,
      }).unwrap());
    }

    for x in 0..194 {
      sprites.push(spritesheet.region(character_datapoints[x]).unwrap());
    }

    for x in 0..TILES_W {
      for y in 0..TILES_H {
        let x2: f64 = 100.0 * 1.5 as f64;
        let y2: f64 = 50.0 * 1.5 as f64;
        tiles.push(TerrainTile {
          rect: Rectangle {
            x: 100.0 * x as f64,
            y: 50.0 * y as f64,
            w: TERRAIN_W,
            h: TERRAIN_H,
          },
          terrain_sprites: terrain_sprites.clone(),
          current: TerrainFrame::Grass,
        });

        tiles.push(TerrainTile {
          rect: Rectangle {
            x: 100.0 * f64::value_from((x+1)).unwrap() - x2 as f64,
            y: 50.0 * f64::value_from((y+1)).unwrap() - y2 as f64,
            w: TERRAIN_W,
            h: TERRAIN_H,
          },
          terrain_sprites: terrain_sprites.clone(),
          current: TerrainFrame::Sand,
        });
      }
    }

    GameView {
      player: Character {
        rect: Rectangle {
          x: 64.0,
          y: 64.0,
          w: CHARACTER_W,
          h: CHARACTER_H,
        },
        sprites: sprites.clone(),
        current: CharacterFrame::Down,
        heading: CharacterFrame::Down,
        anim_index: 0
      },

      tiles: tiles,

      background: Background {
        pos: 0.0,
        sprite: Sprite::load(&mut game.renderer, "assets/background.png").unwrap(),
      },
    }
  }
}

impl View for GameView {
  fn render(&mut self, game: &mut Game, elapsed: f64) -> ViewAction {
    if game.events.now.quit || game.events.now.key_escape == Some(true) {
      return ViewAction::Quit;
    }

    let diagonal = (game.events.key_up ^ game.events.key_down) && (game.events.key_left ^ game.events.key_right);
    let moved = if diagonal { 1.0 / 2.0f64.sqrt() } else { 1.0 } * PLAYER_SPEED * elapsed;
    let dx = match (game.events.key_left, game.events.key_right) {
      (true, true) | (false, false) => 0.0,
      (true, false) => -moved,
      (false, true) => moved,
    };

    let dy = match (game.events.key_up, game.events.key_down) {
      (true, true) | (false, false) => 0.0,
      (true, false) => -moved,
      (false, true) => moved,
    };

    self.player.rect.x += dx;
    self.player.rect.y += dy / 2.0;

    let movable_region = Rectangle {
      x: 0.0,
      y: 0.0,
      w: game.output_size().0,
      h: game.output_size().1,
    };

    self.player.rect = self.player.rect.move_inside(movable_region).unwrap();
    self.player.current =
    if dx == 0.0 && dy < 0.0       { CharacterFrame::Up }
    else if dx > 0.0 && dy < 0.0   { CharacterFrame::UpRight }
    else if dx < 0.0 && dy < 0.0   { CharacterFrame::UpLeft }
    else if dx == 0.0 && dy == 0.0 { self.player.heading }
    else if dx > 0.0 && dy == 0.0  { CharacterFrame::Right }
    else if dx < 0.0 && dy == 0.0  { CharacterFrame::Left }
    else if dx == 0.0 && dy > 0.0  { CharacterFrame::Down }
    else if dx > 0.0 && dy > 0.0   { CharacterFrame::DownRight }
    else if dx < 0.0 && dy > 0.0   { CharacterFrame::DownLeft }
    else { unreachable!() };

    self.player.heading = self.player.current;

    game.renderer.set_draw_color(Color::RGBA(120, 120, 120, 0));
    self.background.render(&mut game.renderer);
    game.renderer.clear();

    for x in 0..TILES_W {
      for y in 0..TILES_H {
        let index = x * TILES_H + y;
        game.renderer.copy_sprite(&self.tiles[index].terrain_sprites[self.tiles[index].current as usize], self.tiles[index].rect);
      }
    }

    match game.events.mouse_click {
      Some(m) => {
        game.renderer.set_draw_color(Color::RGBA(255, 0, 0, 0));
        let _ = game.renderer.draw_line(Point::new(m.0, m.1 ), Point::new(m.0 - 10, m.1));
      },
      None => {},
    }

    // player
    game.renderer.set_draw_color(Color::RGBA(119,119,119,0));

    game.renderer.copy_sprite(&self.player.sprites[self.player.current as usize + self.player.anim_index as usize], self.player.rect);
    self.player.anim_index =
      if dx == 0.0 && dy == 0.0 { 0u32 }
      else if self.player.anim_index < 13u32 { self.player.anim_index + 1u32 }
      else { 0u32 };

    ViewAction::None
  }
}
<commit_msg>Flash shooting sprite while mouse 1 pressed<commit_after>use game::{Game, View, ViewAction};
use game::data::Rectangle;
use game::gfx::{CopySprite, Sprite};
use views::background::Background;
use data::load_character;
use sdl2::pixels::Color;
use sdl2::render::Renderer;
use sdl2::rect::Point;
use conv::prelude::*;

mod background;

const PLAYER_SPEED: f64 = 150.0;
const CHARACTER_W: f64 = 56.0;
const CHARACTER_H: f64 = 43.0;

const TERRAIN_W: f64 = 100.0;
const TERRAIN_H: f64 = 50.0;

const TILES_W: usize = 32;
const TILES_H: usize = 20;

#[derive(Clone, Copy)]
enum CharacterFrame {
  Still = 0,
  Right = 1,
  UpRight = 28,
  Up = 56,
  UpLeft = 84,
  Left = 108,
  DownLeft = 122,
  Down = 150,
  DownRight = 178
}

#[derive(Clone, Copy)]
enum TerrainFrame {
  Sand = 0,
  Grass = 1,
}

struct Character {
  rect: Rectangle,
  sprites: Vec<Sprite>,
  current: CharacterFrame,
  heading: CharacterFrame,
  anim_index: u32
}

struct TerrainTile {
  rect: Rectangle,
  terrain_sprites: Vec<Sprite>,
  current: TerrainFrame,
}

pub struct GameView {
  player: Character,
  tiles: Vec<TerrainTile>,
  background: Background,
}

impl GameView {
  pub fn new(game: &mut Game) -> GameView {
    let spritesheet = Sprite::load(&mut game.renderer, "assets/character.png").unwrap();
    let character_datapoints = load_character();
    let terrain_spritesheet = Sprite::load(&mut game.renderer, "assets/terrain.png").unwrap();
    let mut sprites = Vec::with_capacity(256);
    let mut terrain_sprites = Vec::with_capacity(TILES_W);
    let mut tiles = Vec::with_capacity(TILES_W * TILES_H * 2);

    for x in 0..3 {
      terrain_sprites.push(terrain_spritesheet.region(Rectangle {
        w: TERRAIN_W,
        h: TERRAIN_H,
        x: TERRAIN_W * x as f64,
        y: 0.0 as f64,
      }).unwrap());
    }

    for x in 0..194 {
      sprites.push(spritesheet.region(character_datapoints[x]).unwrap());
    }

    for x in 195..239 {
      sprites.push(spritesheet.region(character_datapoints[x]).unwrap());
    }

    for x in 0..TILES_W {
      for y in 0..TILES_H {
        let x2: f64 = 100.0 * 1.5 as f64;
        let y2: f64 = 50.0 * 1.5 as f64;
        tiles.push(TerrainTile {
          rect: Rectangle {
            x: 100.0 * x as f64,
            y: 50.0 * y as f64,
            w: TERRAIN_W,
            h: TERRAIN_H,
          },
          terrain_sprites: terrain_sprites.clone(),
          current: TerrainFrame::Grass,
        });

        tiles.push(TerrainTile {
          rect: Rectangle {
            x: 100.0 * f64::value_from((x + 1)).unwrap() - x2 as f64,
            y: 50.0 * f64::value_from((y + 1)).unwrap() - y2 as f64,
            w: TERRAIN_W,
            h: TERRAIN_H,
          },
          terrain_sprites: terrain_sprites.clone(),
          current: TerrainFrame::Sand,
        });
      }
    }

    GameView {
      player: Character {
        rect: Rectangle {
          x: 64.0,
          y: 64.0,
          w: CHARACTER_W,
          h: CHARACTER_H,
        },
        sprites: sprites.clone(),
        current: CharacterFrame::Down,
        heading: CharacterFrame::Down,
        anim_index: 0
      },

      tiles: tiles,

      background: Background {
        pos: 0.0,
        sprite: Sprite::load(&mut game.renderer, "assets/background.png").unwrap(),
      },
    }
  }
}

impl View for GameView {
  fn render(&mut self, game: &mut Game, elapsed: f64) -> ViewAction {
    if game.events.now.quit || game.events.now.key_escape == Some(true) {
      return ViewAction::Quit;
    }

    let diagonal = (game.events.key_up ^ game.events.key_down) && (game.events.key_left ^ game.events.key_right);
    let moved = if diagonal { 1.0 / 2.0f64.sqrt() } else { 1.0 } * PLAYER_SPEED * elapsed;
    let dx = match (game.events.key_left, game.events.key_right) {
      (true, true) | (false, false) => 0.0,
      (true, false) => -moved,
      (false, true) => moved,
    };

    let dy = match (game.events.key_up, game.events.key_down) {
      (true, true) | (false, false) => 0.0,
      (true, false) => -moved,
      (false, true) => moved,
    };

    self.player.rect.x += dx;
    self.player.rect.y += dy / 2.0;

    let movable_region = Rectangle {
      x: 0.0,
      y: 0.0,
      w: game.output_size().0,
      h: game.output_size().1,
    };

    self.player.rect = self.player.rect.move_inside(movable_region).unwrap();
    self.player.current =
    if dx == 0.0 && dy < 0.0       { CharacterFrame::Up }
    else if dx > 0.0 && dy < 0.0   { CharacterFrame::UpRight }
    else if dx < 0.0 && dy < 0.0   { CharacterFrame::UpLeft }
    else if dx == 0.0 && dy == 0.0 { self.player.heading }
    else if dx > 0.0 && dy == 0.0  { CharacterFrame::Right }
    else if dx < 0.0 && dy == 0.0  { CharacterFrame::Left }
    else if dx == 0.0 && dy > 0.0  { CharacterFrame::Down }
    else if dx > 0.0 && dy > 0.0   { CharacterFrame::DownRight }
    else if dx < 0.0 && dy > 0.0   { CharacterFrame::DownLeft }
    else { unreachable!() };

    self.player.heading = self.player.current;

    game.renderer.set_draw_color(Color::RGBA(120, 120, 120, 0));
    self.background.render(&mut game.renderer);
    game.renderer.clear();

    for x in 0..TILES_W {
      for y in 0..TILES_H {
        let index = x * TILES_H + y;
        game.renderer.copy_sprite(&self.tiles[index].terrain_sprites[self.tiles[index].current as usize], self.tiles[index].rect);
      }
    }

    game.renderer.set_draw_color(Color::RGBA(119, 119, 119, 0));
    match game.events.mouse_click {
      Some(m) => {
        game.renderer.copy_sprite(&self.player.sprites[200], self.player.rect);
      },
      None => {

        game.renderer.copy_sprite(&self.player.sprites[self.player.current as usize + self.player.anim_index as usize], self.player.rect);
        self.player.anim_index =
          if dx == 0.0 && dy == 0.0 { 0u32 } else if self.player.anim_index < 13u32 { self.player.anim_index + 1u32 } else { 0u32 };
      },
    }

    ViewAction::None
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2020 Gilad Naaman, Ralf Jung
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

/// `addr_of!`, or just ref-then-cast when that is not available.
#[cfg(raw_ref_macros)]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__addr_of {
    ($path:expr) => {{
        $crate::__priv::ptr::addr_of!($path)
    }};
}
#[cfg(not(raw_ref_macros))]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__addr_of {
    ($path:expr) => {{
        // This is UB because we create an intermediate reference to uninitialized memory.
        // Nothing we can do about that without `addr_of!` though.
        &$path as *const _
    }};
}

/// Deref-coercion protection macro.
#[cfg(allow_clippy)]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__field_check {
    ($type:path, $field:tt) => {
        // Make sure the field actually exists. This line ensures that a
        // compile-time error is generated if $field is accessed through a
        // Deref impl.
        #[allow(clippy::unneeded_field_pattern)]
        let $type { $field: _, .. };
    };
}
#[cfg(not(allow_clippy))]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__field_check {
    ($type:path, $field:tt) => {
        // Make sure the field actually exists. This line ensures that a
        // compile-time error is generated if $field is accessed through a
        // Deref impl.
        let $type { $field: _, .. };
    };
}

/// Deref-coercion protection macro.
#[cfg(allow_clippy)]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__field_check_tuple {
    ($type:ty, $field:tt) => {
        // Make sure the type argument is a tuple
        #[allow(clippy::unneeded_wildcard_pattern)]
        let (_, ..): $type;
    };
}
#[cfg(not(allow_clippy))]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__field_check_tuple {
    ($type:ty, $field:tt) => {
        // Make sure the type argument is a tuple
        let (_, ..): $type;
    };
}

/// Deref-coercion protection macro for unions.
/// Unfortunately accepts single-field structs as well, which is not ideal,
/// but ultimately pretty harmless.
#[cfg(allow_clippy)]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__field_check_union {
    ($type:path, $field:tt) => {
        // Make sure the field actually exists. This line ensures that a
        // compile-time error is generated if $field is accessed through a
        // Deref impl.
        #[allow(clippy::unneeded_wildcard_pattern)]
        // rustc1.19 requires unsafe here for the pattern; not needed in newer versions
        #[allow(unused_unsafe)]
        unsafe {
            let $type { $field: _ };
        }
    };
}
#[cfg(not(allow_clippy))]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__field_check_union {
    ($type:path, $field:tt) => {
        // Make sure the field actually exists. This line ensures that a
        // compile-time error is generated if $field is accessed through a
        // Deref impl.
        // rustc1.19 requires unsafe here for the pattern; not needed in newer versions
        #[allow(unused_unsafe)]
        unsafe {
            let $type { $field: _ };
        }
    };
}

/// Computes a const raw pointer to the given field of the given base pointer
/// to the given parent type.
///
/// The `base` pointer *must not* be dangling, but it *may* point to
/// uninitialized memory.
#[macro_export(local_inner_macros)]
macro_rules! raw_field {
    ($base:expr, $parent:path, $field:tt) => {{
        _memoffset__field_check!($parent, $field);
        let base = $base; // evaluate $base outside the `unsafe` block

        // Get the field address.
        // Crucially, we know that this will not trigger a deref coercion because
        // of the field check we did above.
        #[allow(unused_unsafe)] // for when the macro is used in an unsafe block
        unsafe {
            _memoffset__addr_of!((*(base as *const $parent)).$field)
        }
    }};
}

/// Computes a const raw pointer to the given field of the given base pointer
/// to the given parent tuple typle.
///
/// The `base` pointer *must not* be dangling, but it *may* point to
/// uninitialized memory.
#[cfg(tuple_ty)]
#[macro_export(local_inner_macros)]
macro_rules! raw_field_tuple {
    ($base:expr, $parent:ty, $field:tt) => {{
        _memoffset__field_check_tuple!($parent, $field);
        let base = $base; // evaluate $base outside the `unsafe` block

        // Get the field address.
        // Crucially, we know that this will not trigger a deref coercion because
        // of the field check we did above.
        #[allow(unused_unsafe)] // for when the macro is used in an unsafe block
        unsafe {
            _memoffset__addr_of!((*(base as *const $parent)).$field)
        }
    }};
}

/// Computes a const raw pointer to the given field of the given base pointer
/// to the given parent tuple typle.
///
/// The `base` pointer *must not* be dangling, but it *may* point to
/// uninitialized memory.
///
/// ## Note
/// This macro is the same as `raw_field`, except for a different Deref-coercion check that
/// supports unions.
/// Due to macro_rules limitations, this check will accept structs with a single field as well as unions.
/// Using this macro for a single-field struct will still work, but might lead to a future
/// compatibility problem if the struct gains more fields.
#[macro_export(local_inner_macros)]
macro_rules! raw_field_union {
    ($base:expr, $parent:path, $field:tt) => {{
        _memoffset__field_check_union!($parent, $field);
        let base = $base; // evaluate $base outside the `unsafe` block

        // Get the field address.
        // Crucially, we know that this will not trigger a deref coercion because
        // of the field check we did above.
        #[allow(unused_unsafe)] // for when the macro is used in an unsafe block
        unsafe {
            _memoffset__addr_of!((*(base as *const $parent)).$field)
        }
    }};
}
<commit_msg>Update src/raw_field.rs<commit_after>// Copyright (c) 2020 Gilad Naaman, Ralf Jung
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

/// `addr_of!`, or just ref-then-cast when that is not available.
#[cfg(raw_ref_macros)]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__addr_of {
    ($path:expr) => {{
        $crate::__priv::ptr::addr_of!($path)
    }};
}
#[cfg(not(raw_ref_macros))]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__addr_of {
    ($path:expr) => {{
        // This is UB because we create an intermediate reference to uninitialized memory.
        // Nothing we can do about that without `addr_of!` though.
        &$path as *const _
    }};
}

/// Deref-coercion protection macro.
#[cfg(allow_clippy)]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__field_check {
    ($type:path, $field:tt) => {
        // Make sure the field actually exists. This line ensures that a
        // compile-time error is generated if $field is accessed through a
        // Deref impl.
        #[allow(clippy::unneeded_field_pattern)]
        let $type { $field: _, .. };
    };
}
#[cfg(not(allow_clippy))]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__field_check {
    ($type:path, $field:tt) => {
        // Make sure the field actually exists. This line ensures that a
        // compile-time error is generated if $field is accessed through a
        // Deref impl.
        let $type { $field: _, .. };
    };
}

/// Deref-coercion protection macro.
#[cfg(allow_clippy)]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__field_check_tuple {
    ($type:ty, $field:tt) => {
        // Make sure the type argument is a tuple
        #[allow(clippy::unneeded_wildcard_pattern)]
        let (_, ..): $type;
    };
}
#[cfg(not(allow_clippy))]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__field_check_tuple {
    ($type:ty, $field:tt) => {
        // Make sure the type argument is a tuple
        let (_, ..): $type;
    };
}

/// Deref-coercion protection macro for unions.
/// Unfortunately accepts single-field structs as well, which is not ideal,
/// but ultimately pretty harmless.
#[cfg(allow_clippy)]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__field_check_union {
    ($type:path, $field:tt) => {
        // Make sure the field actually exists. This line ensures that a
        // compile-time error is generated if $field is accessed through a
        // Deref impl.
        #[allow(clippy::unneeded_wildcard_pattern)]
        // rustc1.19 requires unsafe here for the pattern; not needed in newer versions
        #[allow(unused_unsafe)]
        unsafe {
            let $type { $field: _ };
        }
    };
}
#[cfg(not(allow_clippy))]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__field_check_union {
    ($type:path, $field:tt) => {
        // Make sure the field actually exists. This line ensures that a
        // compile-time error is generated if $field is accessed through a
        // Deref impl.
        // rustc1.19 requires unsafe here for the pattern; not needed in newer versions
        #[allow(unused_unsafe)]
        unsafe {
            let $type { $field: _ };
        }
    };
}

/// Computes a const raw pointer to the given field of the given base pointer
/// to the given parent type.
///
/// The `base` pointer *must not* be dangling, but it *may* point to
/// uninitialized memory.
#[macro_export(local_inner_macros)]
macro_rules! raw_field {
    ($base:expr, $parent:path, $field:tt) => {{
        _memoffset__field_check!($parent, $field);
        let base = $base; // evaluate $base outside the `unsafe` block

        // Get the field address.
        // Crucially, we know that this will not trigger a deref coercion because
        // of the field check we did above.
        #[allow(unused_unsafe)] // for when the macro is used in an unsafe block
        unsafe {
            _memoffset__addr_of!((*(base as *const $parent)).$field)
        }
    }};
}

/// Computes a const raw pointer to the given field of the given base pointer
/// to the given parent tuple typle.
///
/// The `base` pointer *must not* be dangling, but it *may* point to
/// uninitialized memory.
#[cfg(tuple_ty)]
#[macro_export(local_inner_macros)]
macro_rules! raw_field_tuple {
    ($base:expr, $parent:ty, $field:tt) => {{
        _memoffset__field_check_tuple!($parent, $field);
        let base = $base; // evaluate $base outside the `unsafe` block

        // Get the field address.
        // Crucially, we know that this will not trigger a deref coercion because
        // of the field check we did above.
        #[allow(unused_unsafe)] // for when the macro is used in an unsafe block
        unsafe {
            _memoffset__addr_of!((*(base as *const $parent)).$field)
        }
    }};
}

/// Computes a const raw pointer to the given field of the given base pointer
/// to the given parent tuple typle.
///
/// The `base` pointer *must not* be dangling, but it *may* point to
/// uninitialized memory.
///
/// ## Note
/// This macro is the same as `raw_field`, except for a different Deref-coercion check that
/// supports unions.
/// Due to macro_rules limitations, this check will accept structs with a single field as well as unions.
/// This is not a stable guarantee, and future versions of this crate might fail
/// on any use of this macro with a struct, without a semver bump.
#[macro_export(local_inner_macros)]
macro_rules! raw_field_union {
    ($base:expr, $parent:path, $field:tt) => {{
        _memoffset__field_check_union!($parent, $field);
        let base = $base; // evaluate $base outside the `unsafe` block

        // Get the field address.
        // Crucially, we know that this will not trigger a deref coercion because
        // of the field check we did above.
        #[allow(unused_unsafe)] // for when the macro is used in an unsafe block
        unsafe {
            _memoffset__addr_of!((*(base as *const $parent)).$field)
        }
    }};
}
<|endoftext|>


<commit_before>// Copyright 2015 Keegan McAllister.
// Copyright 2016 Corey Farwell
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// See `LICENSE` in this repository.

extern crate gcc;
extern crate quale;

use std::env;
use std::ffi::{OsStr, OsString};
use std::fs::File;
use std::process::Command;

/// Get the filesystem path to the llvm-config executable
fn llvm_config_path() -> OsString {
    let llvm_config_path = if let Some(path) = env::var_os("LLVM_CONFIG") {
        path
    } else if let Some(path) = quale::which("llvm-config-3.8") {
        path.into()
    } else if let Some(path) = quale::which("llvm-config") {
        path.into()
    } else {
        panic!("Could not find LLVM. Either set $LLVM_CONFIG or ensure \
                `llvm-config` is in your $PATH. Consult the README for more \
                information.");
    };
    // Ensure we're working with version 3.8.x
    let output = Command::new(&llvm_config_path)
                         .arg("--version")
                         .output()
                         .expect("Could not execute llvm-config");
    if !output.stdout.starts_with(b"3.8") {
        panic!("Found llvm-config, but is not a compatible version. afl.rs \
                requires version LLVM 3.8. Either set $LLVM_CONFIG or ensure \
                `llvm-config` version 3.8 is in your $PATH.")
    }
    File::open(&llvm_config_path).unwrap_or_else(|error| {
        panic!("Cannot access {:?} to determine your LLVM configuration: {}",
               llvm_config_path,
               error);
    });
    llvm_config_path
}

/// Using llvm-config, determine the flags we'll pass to the C++ compiler
fn cxx_flags<T: AsRef<OsStr>>(llvm_config_path: T) -> Vec<String> {
    let output = Command::new(llvm_config_path)
                     .arg("--cxxflags")
                     .output()
                     .unwrap_or_else(|e| panic!("failed to execute process: {}", e));
    if !output.status.success() {
        panic!("{:?}", output);
    }
    let output_string = unsafe { String::from_utf8_unchecked(output.stdout) };
    output_string.trim()
                 .split(' ')
                 .filter(|s| !s.is_empty())
                 .map(|s| s.to_owned())
                 .collect::<Vec<_>>()
}

fn main() {
    let llvm_config_path = llvm_config_path();
    let cxx_flags = cxx_flags(llvm_config_path);
    let mut config = gcc::Config::new();
    config.cpp(true);
    config.opt_level(2);
    config.file("afl-llvm-pass.so.cc");
    config.flag("-fPIC");
    config.flag("-Wall");
    config.flag("-Werror");
    config.flag("-fno-rtti");
    config.flag("-c");
    for flag in cxx_flags {
        config.flag(&flag);
    }
    config.compile("libafl-llvm-pass.a")
}
<commit_msg>Remove LLVM version enforcement.<commit_after>// Copyright 2015 Keegan McAllister.
// Copyright 2016 Corey Farwell
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// See `LICENSE` in this repository.

extern crate gcc;
extern crate quale;

use std::env;
use std::ffi::{OsStr, OsString};
use std::fs::File;
use std::process::Command;

/// Get the filesystem path to the llvm-config executable
fn llvm_config_path() -> OsString {
    let llvm_config_path = if let Some(path) = env::var_os("LLVM_CONFIG") {
        path
    } else if let Some(path) = quale::which("llvm-config-3.8") {
        path.into()
    } else if let Some(path) = quale::which("llvm-config") {
        path.into()
    } else {
        panic!("Could not find LLVM. Either set $LLVM_CONFIG or ensure \
                `llvm-config` is in your $PATH. Consult the README for more \
                information.");
    };
    File::open(&llvm_config_path).unwrap_or_else(|error| {
        panic!("Cannot access {:?} to determine your LLVM configuration: {}",
               llvm_config_path,
               error);
    });
    llvm_config_path
}

/// Using llvm-config, determine the flags we'll pass to the C++ compiler
fn cxx_flags<T: AsRef<OsStr>>(llvm_config_path: T) -> Vec<String> {
    let output = Command::new(llvm_config_path)
                     .arg("--cxxflags")
                     .output()
                     .unwrap_or_else(|e| panic!("failed to execute process: {}", e));
    if !output.status.success() {
        panic!("{:?}", output);
    }
    let output_string = unsafe { String::from_utf8_unchecked(output.stdout) };
    output_string.trim()
                 .split(' ')
                 .filter(|s| !s.is_empty())
                 .map(|s| s.to_owned())
                 .collect::<Vec<_>>()
}

fn main() {
    let llvm_config_path = llvm_config_path();
    let cxx_flags = cxx_flags(llvm_config_path);
    let mut config = gcc::Config::new();
    config.cpp(true);
    config.opt_level(2);
    config.file("afl-llvm-pass.so.cc");
    config.flag("-fPIC");
    config.flag("-Wall");
    config.flag("-Werror");
    config.flag("-fno-rtti");
    config.flag("-c");
    for flag in cxx_flags {
        config.flag(&flag);
    }
    config.compile("libafl-llvm-pass.a")
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use crate::types::{Intern, RawInternKey};
use core::cmp::Ordering;
use fnv::FnvHashMap;
use lazy_static::lazy_static;
use parking_lot::RwLock;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::fmt;
use std::num::NonZeroU32;
use std::str::FromStr;
use std::sync::Arc;

/// Slices of bytes intern as BytesKey
impl Intern for &[u8] {
    type Key = BytesKey;

    fn intern(self) -> Self::Key {
        BytesKey(BYTES_TABLE.intern(self))
    }
}

/// Owned strings intern as StringKey, with the interning
/// based on the raw bytes of the string
impl Intern for String {
    type Key = StringKey;

    fn intern(self) -> Self::Key {
        StringKey(BYTES_TABLE.intern(self.as_bytes()))
    }
}

/// Str (slices) intern as StringKey, with the interning
/// based on the raw bytes of the str.
impl Intern for &str {
    type Key = StringKey;

    fn intern(self) -> Self::Key {
        StringKey(BYTES_TABLE.intern(self.as_bytes()))
    }
}

/// Interned bytes
#[derive(Copy, Clone, Eq, Ord, Hash, PartialEq, PartialOrd)]
pub struct BytesKey(RawInternKey);

impl BytesKey {
    pub fn lookup(self) -> &'static [u8] {
        BYTES_TABLE.lookup(self.0)
    }
}

impl fmt::Debug for BytesKey {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let bytes_value = self.lookup();
        write!(f, "{:?}", bytes_value)
    }
}

/// An interned string
#[derive(Copy, Clone, Eq, Hash, PartialEq)]
pub struct StringKey(RawInternKey);

impl Ord for StringKey {
    fn cmp(&self, other: &Self) -> Ordering {
        self.lookup().cmp(other.lookup())
    }
}

impl PartialOrd for StringKey {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.lookup().partial_cmp(other.lookup())
    }
}

impl FromStr for StringKey {
    type Err = std::convert::Infallible;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(s.intern())
    }
}

impl StringKey {
    /// Get a reference to the original str.
    pub fn lookup(self) -> &'static str {
        let bytes = BYTES_TABLE.lookup(self.0);
        // This is safe because the bytes we are converting originally came
        // from a str when we interned it: the only way to get a StringKey is
        // to intern an (already valid) string, so if we have a StringKey then
        // its bytes must be valid UTF-8.
        unsafe { std::str::from_utf8_unchecked(bytes) }
    }

    /// Convert the interned string key into an interned bytes key. Because
    /// strings intern as their raw bytes, this is an O(1) operation.
    /// Note the reverse (BytesKey.as_str) is a fallible operation since
    /// the bytes may not be valid UTF-8.
    pub fn as_bytes(self) -> BytesKey {
        BytesKey(self.0)
    }
}

impl fmt::Debug for StringKey {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let str_value = self.lookup();
        write!(f, "{:?}", str_value)
    }
}

impl fmt::Display for StringKey {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let str_value = self.lookup();
        write!(f, "{}", str_value)
    }
}

impl Serialize for StringKey {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(self.lookup())
    }
}

impl<'de> Deserialize<'de> for StringKey {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        Deserialize::deserialize(deserializer).map(|s: String| s.intern())
    }
}

// Static table used in the bytes/str Intern implementations
lazy_static! {
    static ref BYTES_TABLE: BytesTable = BytesTable::new();
}

/// Similar to the generic `InternTable` but customized for sequences of raw bytes (and strings).
pub struct BytesTable {
    data: Arc<RwLock<BytesTableData>>,
}

impl BytesTable {
    pub fn new() -> Self {
        Self {
            data: Arc::new(RwLock::new(BytesTableData::new())),
        }
    }

    pub fn intern(&self, value: &[u8]) -> RawInternKey {
        if let Some(prev) = self.data.read().get(value) {
            return prev;
        }
        let mut writer = self.data.write();
        writer.intern(value)
    }

    pub fn lookup(&self, key: RawInternKey) -> &'static [u8] {
        self.data.read().lookup(key)
    }
}

/// BytesTableData is similar to InternTableData but customized for sequences
/// of raw bytes (and notably, strings).
struct BytesTableData {
    // Raw data storage, allocated in large chunks
    buffer: Option<&'static mut [u8]>,
    // Reverse mapping of index=>value, used to convert an
    // interned key back to (a reference to) its value
    items: Vec<&'static [u8]>,
    // Mapping of values to their interned indices
    table: FnvHashMap<&'static [u8], RawInternKey>,
}

impl BytesTableData {
    const BUFFER_SIZE: usize = 4096;

    pub fn new() -> Self {
        Self {
            buffer: Some(Self::new_buffer()),
            items: vec![
                // Add buffer value so the used index starts at 1
                // and we can use a NonZero type.
                b"<sentinel>",
            ],
            table: Default::default(),
        }
    }

    fn new_buffer() -> &'static mut [u8] {
        Box::leak(Box::new([0; Self::BUFFER_SIZE]))
    }

    pub fn get(&self, value: &[u8]) -> Option<RawInternKey> {
        self.table.get(value).cloned()
    }

    // Copy the byte slice into 'static memory by appending it to a buffer, if there is room.
    // If the buffer fills up and the value is small, start over with a new buffer.
    // If the value is large, just give it its own memory.
    fn alloc(&mut self, value: &[u8]) -> &'static [u8] {
        let len = value.len();

        let mut buffer = self.buffer.take().unwrap();
        if len > buffer.len() {
            if len >= Self::BUFFER_SIZE / 16 {
                // This byte slice is so big it can just have its own memory.
                self.buffer = Some(buffer);
                return Box::leak(value.into());
            } else {
                buffer = Self::new_buffer()
            }
        }

        let (mem, remaining) = buffer.split_at_mut(len);
        mem.copy_from_slice(value);
        self.buffer = Some(remaining);

        mem
    }

    pub fn intern(&mut self, value: &[u8]) -> RawInternKey {
        // If there's an existing value return it
        if let Some(prev) = self.get(value) {
            return prev;
        }

        // Otherwise intern
        let key = RawInternKey::new(unsafe {
            // Safe because we initialize `self.items` with a sentinel value
            NonZeroU32::new_unchecked(self.items.len() as u32)
        });
        let static_bytes = self.alloc(value);
        self.items.push(static_bytes);
        self.table.insert(static_bytes, key);

        key
    }

    pub fn lookup(&self, key: RawInternKey) -> &'static [u8] {
        let index = key.as_usize();
        self.items[index]
    }
}
<commit_msg>Serialize reader ast<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use crate::types::{Intern, RawInternKey};
use core::cmp::Ordering;
use fnv::FnvHashMap;
use lazy_static::lazy_static;
use parking_lot::RwLock;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::fmt;
use std::num::NonZeroU32;
use std::str::FromStr;
use std::sync::Arc;

/// Slices of bytes intern as BytesKey
impl Intern for &[u8] {
    type Key = BytesKey;

    fn intern(self) -> Self::Key {
        BytesKey(BYTES_TABLE.intern(self))
    }
}

/// Owned strings intern as StringKey, with the interning
/// based on the raw bytes of the string
impl Intern for String {
    type Key = StringKey;

    fn intern(self) -> Self::Key {
        StringKey(BYTES_TABLE.intern(self.as_bytes()))
    }
}

/// Str (slices) intern as StringKey, with the interning
/// based on the raw bytes of the str.
impl Intern for &str {
    type Key = StringKey;

    fn intern(self) -> Self::Key {
        StringKey(BYTES_TABLE.intern(self.as_bytes()))
    }
}

impl Intern for &String {
    type Key = StringKey;

    fn intern(self) -> Self::Key {
        StringKey(BYTES_TABLE.intern(self.as_bytes()))
    }
}

/// Interned bytes
#[derive(Copy, Clone, Eq, Ord, Hash, PartialEq, PartialOrd)]
pub struct BytesKey(RawInternKey);

impl BytesKey {
    pub fn lookup(self) -> &'static [u8] {
        BYTES_TABLE.lookup(self.0)
    }
}

impl fmt::Debug for BytesKey {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let bytes_value = self.lookup();
        write!(f, "{:?}", bytes_value)
    }
}

/// An interned string
#[derive(Copy, Clone, Eq, Hash, PartialEq)]
pub struct StringKey(RawInternKey);

impl Ord for StringKey {
    fn cmp(&self, other: &Self) -> Ordering {
        self.lookup().cmp(other.lookup())
    }
}

impl PartialOrd for StringKey {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.lookup().partial_cmp(other.lookup())
    }
}

impl FromStr for StringKey {
    type Err = std::convert::Infallible;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(s.intern())
    }
}

impl StringKey {
    /// Get a reference to the original str.
    pub fn lookup(self) -> &'static str {
        let bytes = BYTES_TABLE.lookup(self.0);
        // This is safe because the bytes we are converting originally came
        // from a str when we interned it: the only way to get a StringKey is
        // to intern an (already valid) string, so if we have a StringKey then
        // its bytes must be valid UTF-8.
        unsafe { std::str::from_utf8_unchecked(bytes) }
    }

    /// Convert the interned string key into an interned bytes key. Because
    /// strings intern as their raw bytes, this is an O(1) operation.
    /// Note the reverse (BytesKey.as_str) is a fallible operation since
    /// the bytes may not be valid UTF-8.
    pub fn as_bytes(self) -> BytesKey {
        BytesKey(self.0)
    }
}

impl fmt::Debug for StringKey {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let str_value = self.lookup();
        write!(f, "{:?}", str_value)
    }
}

impl fmt::Display for StringKey {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let str_value = self.lookup();
        write!(f, "{}", str_value)
    }
}

impl Serialize for StringKey {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(self.lookup())
    }
}

impl<'de> Deserialize<'de> for StringKey {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        Deserialize::deserialize(deserializer).map(|s: String| s.intern())
    }
}

// Static table used in the bytes/str Intern implementations
lazy_static! {
    static ref BYTES_TABLE: BytesTable = BytesTable::new();
}

/// Similar to the generic `InternTable` but customized for sequences of raw bytes (and strings).
pub struct BytesTable {
    data: Arc<RwLock<BytesTableData>>,
}

impl BytesTable {
    pub fn new() -> Self {
        Self {
            data: Arc::new(RwLock::new(BytesTableData::new())),
        }
    }

    pub fn intern(&self, value: &[u8]) -> RawInternKey {
        if let Some(prev) = self.data.read().get(value) {
            return prev;
        }
        let mut writer = self.data.write();
        writer.intern(value)
    }

    pub fn lookup(&self, key: RawInternKey) -> &'static [u8] {
        self.data.read().lookup(key)
    }
}

/// BytesTableData is similar to InternTableData but customized for sequences
/// of raw bytes (and notably, strings).
struct BytesTableData {
    // Raw data storage, allocated in large chunks
    buffer: Option<&'static mut [u8]>,
    // Reverse mapping of index=>value, used to convert an
    // interned key back to (a reference to) its value
    items: Vec<&'static [u8]>,
    // Mapping of values to their interned indices
    table: FnvHashMap<&'static [u8], RawInternKey>,
}

impl BytesTableData {
    const BUFFER_SIZE: usize = 4096;

    pub fn new() -> Self {
        Self {
            buffer: Some(Self::new_buffer()),
            items: vec![
                // Add buffer value so the used index starts at 1
                // and we can use a NonZero type.
                b"<sentinel>",
            ],
            table: Default::default(),
        }
    }

    fn new_buffer() -> &'static mut [u8] {
        Box::leak(Box::new([0; Self::BUFFER_SIZE]))
    }

    pub fn get(&self, value: &[u8]) -> Option<RawInternKey> {
        self.table.get(value).cloned()
    }

    // Copy the byte slice into 'static memory by appending it to a buffer, if there is room.
    // If the buffer fills up and the value is small, start over with a new buffer.
    // If the value is large, just give it its own memory.
    fn alloc(&mut self, value: &[u8]) -> &'static [u8] {
        let len = value.len();

        let mut buffer = self.buffer.take().unwrap();
        if len > buffer.len() {
            if len >= Self::BUFFER_SIZE / 16 {
                // This byte slice is so big it can just have its own memory.
                self.buffer = Some(buffer);
                return Box::leak(value.into());
            } else {
                buffer = Self::new_buffer()
            }
        }

        let (mem, remaining) = buffer.split_at_mut(len);
        mem.copy_from_slice(value);
        self.buffer = Some(remaining);

        mem
    }

    pub fn intern(&mut self, value: &[u8]) -> RawInternKey {
        // If there's an existing value return it
        if let Some(prev) = self.get(value) {
            return prev;
        }

        // Otherwise intern
        let key = RawInternKey::new(unsafe {
            // Safe because we initialize `self.items` with a sentinel value
            NonZeroU32::new_unchecked(self.items.len() as u32)
        });
        let static_bytes = self.alloc(value);
        self.items.push(static_bytes);
        self.table.insert(static_bytes, key);

        key
    }

    pub fn lookup(&self, key: RawInternKey) -> &'static [u8] {
        let index = key.as_usize();
        self.items[index]
    }
}
<|endoftext|>


<commit_before>use std::cmp::max;
use std::collections::HashMap;
use std::path::PathBuf;

use serde::Deserialize;

use alacritty_config_derive::ConfigDeserialize;

mod bell;
mod colors;
mod scrolling;

use crate::ansi::{CursorShape, CursorStyle};

pub use crate::config::bell::{BellAnimation, BellConfig};
pub use crate::config::colors::Colors;
pub use crate::config::scrolling::Scrolling;

pub const LOG_TARGET_CONFIG: &str = "alacritty_config_derive";
const MIN_BLINK_INTERVAL: u64 = 10;

pub type MockConfig = Config<HashMap<String, serde_yaml::Value>>;

/// Top-level config type.
#[derive(ConfigDeserialize, Debug, PartialEq, Default)]
pub struct Config<T> {
    /// TERM env variable.
    pub env: HashMap<String, String>,

    /// Should draw bold text with brighter colors instead of bold font.
    pub draw_bold_text_with_bright_colors: bool,

    pub colors: Colors,

    pub selection: Selection,

    /// Path to a shell program to run on startup.
    pub shell: Option<Program>,

    /// How much scrolling history to keep.
    pub scrolling: Scrolling,

    /// Cursor configuration.
    pub cursor: Cursor,

    /// Shell startup directory.
    pub working_directory: Option<PathBuf>,

    /// Additional configuration options not directly required by the terminal.
    #[config(flatten)]
    pub ui_config: T,

    /// Remain open after child process exits.
    #[config(skip)]
    pub hold: bool,

    /// Bell configuration.
    bell: BellConfig,

    #[config(deprecated = "use `bell` instead")]
    pub visual_bell: Option<BellConfig>,
}

impl<T> Config<T> {
    #[inline]
    pub fn bell(&self) -> &BellConfig {
        self.visual_bell.as_ref().unwrap_or(&self.bell)
    }
}

#[derive(ConfigDeserialize, Clone, Debug, PartialEq, Eq)]
pub struct Selection {
    pub semantic_escape_chars: String,
    pub save_to_clipboard: bool,
}

impl Default for Selection {
    fn default() -> Self {
        Self {
            semantic_escape_chars: String::from(",│`|:\"' ()[]{}<>\t"),
            save_to_clipboard: Default::default(),
        }
    }
}

#[derive(ConfigDeserialize, Copy, Clone, Debug, PartialEq)]
pub struct Cursor {
    pub style: ConfigCursorStyle,
    pub vi_mode_style: Option<ConfigCursorStyle>,
    pub unfocused_hollow: bool,

    thickness: Percentage,
    blink_interval: u64,
}

impl Default for Cursor {
    fn default() -> Self {
        Self {
            thickness: Percentage(0.15),
            unfocused_hollow: true,
            blink_interval: 750,
            style: Default::default(),
            vi_mode_style: Default::default(),
        }
    }
}

impl Cursor {
    #[inline]
    pub fn thickness(self) -> f32 {
        self.thickness.as_f32()
    }

    #[inline]
    pub fn style(self) -> CursorStyle {
        self.style.into()
    }

    #[inline]
    pub fn vi_mode_style(self) -> Option<CursorStyle> {
        self.vi_mode_style.map(From::from)
    }

    #[inline]
    pub fn blink_interval(self) -> u64 {
        max(self.blink_interval, MIN_BLINK_INTERVAL)
    }
}

#[serde(untagged)]
#[derive(Deserialize, Debug, Copy, Clone, PartialEq, Eq)]
pub enum ConfigCursorStyle {
    Shape(CursorShape),
    WithBlinking { shape: CursorShape, blinking: CursorBlinking },
}

impl Default for ConfigCursorStyle {
    fn default() -> Self {
        Self::Shape(CursorShape::default())
    }
}

impl ConfigCursorStyle {
    /// Check if blinking is force enabled/disabled.
    pub fn blinking_override(&self) -> Option<bool> {
        match self {
            Self::Shape(_) => None,
            Self::WithBlinking { blinking, .. } => blinking.blinking_override(),
        }
    }
}

impl From<ConfigCursorStyle> for CursorStyle {
    fn from(config_style: ConfigCursorStyle) -> Self {
        match config_style {
            ConfigCursorStyle::Shape(shape) => Self { shape, blinking: false },
            ConfigCursorStyle::WithBlinking { shape, blinking } => {
                Self { shape, blinking: blinking.into() }
            },
        }
    }
}

#[derive(ConfigDeserialize, Debug, Copy, Clone, PartialEq, Eq)]
pub enum CursorBlinking {
    Never,
    Off,
    On,
    Always,
}

impl Default for CursorBlinking {
    fn default() -> Self {
        CursorBlinking::Off
    }
}

impl CursorBlinking {
    fn blinking_override(&self) -> Option<bool> {
        match self {
            Self::Never => Some(false),
            Self::Off | Self::On => None,
            Self::Always => Some(true),
        }
    }
}

impl Into<bool> for CursorBlinking {
    fn into(self) -> bool {
        self == Self::On || self == Self::Always
    }
}

#[serde(untagged)]
#[derive(Deserialize, Debug, Clone, PartialEq, Eq)]
pub enum Program {
    Just(String),
    WithArgs { program: String, args: Vec<String> },
}

impl Program {
    pub fn program(&self) -> &str {
        match self {
            Program::Just(program) => program,
            Program::WithArgs { program, .. } => program,
        }
    }

    pub fn args(&self) -> &[String] {
        match self {
            Program::Just(_) => &[],
            Program::WithArgs { args, .. } => args,
        }
    }
}

/// Wrapper around f32 that represents a percentage value between 0.0 and 1.0.
#[derive(Deserialize, Clone, Copy, Debug, PartialEq)]
pub struct Percentage(f32);

impl Default for Percentage {
    fn default() -> Self {
        Percentage(1.0)
    }
}

impl Percentage {
    pub fn new(value: f32) -> Self {
        Percentage(if value < 0.0 {
            0.0
        } else if value > 1.0 {
            1.0
        } else {
            value
        })
    }

    pub fn as_f32(self) -> f32 {
        self.0
    }
}
<commit_msg>Fix deserialization of untagged enums<commit_after>use std::cmp::max;
use std::collections::HashMap;
use std::path::PathBuf;

use serde::Deserialize;

use alacritty_config_derive::ConfigDeserialize;

mod bell;
mod colors;
mod scrolling;

use crate::ansi::{CursorShape, CursorStyle};

pub use crate::config::bell::{BellAnimation, BellConfig};
pub use crate::config::colors::Colors;
pub use crate::config::scrolling::Scrolling;

pub const LOG_TARGET_CONFIG: &str = "alacritty_config_derive";
const MIN_BLINK_INTERVAL: u64 = 10;

pub type MockConfig = Config<HashMap<String, serde_yaml::Value>>;

/// Top-level config type.
#[derive(ConfigDeserialize, Debug, PartialEq, Default)]
pub struct Config<T> {
    /// TERM env variable.
    pub env: HashMap<String, String>,

    /// Should draw bold text with brighter colors instead of bold font.
    pub draw_bold_text_with_bright_colors: bool,

    pub colors: Colors,

    pub selection: Selection,

    /// Path to a shell program to run on startup.
    pub shell: Option<Program>,

    /// How much scrolling history to keep.
    pub scrolling: Scrolling,

    /// Cursor configuration.
    pub cursor: Cursor,

    /// Shell startup directory.
    pub working_directory: Option<PathBuf>,

    /// Additional configuration options not directly required by the terminal.
    #[config(flatten)]
    pub ui_config: T,

    /// Remain open after child process exits.
    #[config(skip)]
    pub hold: bool,

    /// Bell configuration.
    bell: BellConfig,

    #[config(deprecated = "use `bell` instead")]
    pub visual_bell: Option<BellConfig>,
}

impl<T> Config<T> {
    #[inline]
    pub fn bell(&self) -> &BellConfig {
        self.visual_bell.as_ref().unwrap_or(&self.bell)
    }
}

#[derive(ConfigDeserialize, Clone, Debug, PartialEq, Eq)]
pub struct Selection {
    pub semantic_escape_chars: String,
    pub save_to_clipboard: bool,
}

impl Default for Selection {
    fn default() -> Self {
        Self {
            semantic_escape_chars: String::from(",│`|:\"' ()[]{}<>\t"),
            save_to_clipboard: Default::default(),
        }
    }
}

#[derive(ConfigDeserialize, Copy, Clone, Debug, PartialEq)]
pub struct Cursor {
    pub style: ConfigCursorStyle,
    pub vi_mode_style: Option<ConfigCursorStyle>,
    pub unfocused_hollow: bool,

    thickness: Percentage,
    blink_interval: u64,
}

impl Default for Cursor {
    fn default() -> Self {
        Self {
            thickness: Percentage(0.15),
            unfocused_hollow: true,
            blink_interval: 750,
            style: Default::default(),
            vi_mode_style: Default::default(),
        }
    }
}

impl Cursor {
    #[inline]
    pub fn thickness(self) -> f32 {
        self.thickness.as_f32()
    }

    #[inline]
    pub fn style(self) -> CursorStyle {
        self.style.into()
    }

    #[inline]
    pub fn vi_mode_style(self) -> Option<CursorStyle> {
        self.vi_mode_style.map(From::from)
    }

    #[inline]
    pub fn blink_interval(self) -> u64 {
        max(self.blink_interval, MIN_BLINK_INTERVAL)
    }
}

#[serde(untagged)]
#[derive(Deserialize, Debug, Copy, Clone, PartialEq, Eq)]
pub enum ConfigCursorStyle {
    Shape(CursorShape),
    WithBlinking {
        #[serde(default)]
        shape: CursorShape,
        #[serde(default)]
        blinking: CursorBlinking,
    },
}

impl Default for ConfigCursorStyle {
    fn default() -> Self {
        Self::Shape(CursorShape::default())
    }
}

impl ConfigCursorStyle {
    /// Check if blinking is force enabled/disabled.
    pub fn blinking_override(&self) -> Option<bool> {
        match self {
            Self::Shape(_) => None,
            Self::WithBlinking { blinking, .. } => blinking.blinking_override(),
        }
    }
}

impl From<ConfigCursorStyle> for CursorStyle {
    fn from(config_style: ConfigCursorStyle) -> Self {
        match config_style {
            ConfigCursorStyle::Shape(shape) => Self { shape, blinking: false },
            ConfigCursorStyle::WithBlinking { shape, blinking } => {
                Self { shape, blinking: blinking.into() }
            },
        }
    }
}

#[derive(ConfigDeserialize, Debug, Copy, Clone, PartialEq, Eq)]
pub enum CursorBlinking {
    Never,
    Off,
    On,
    Always,
}

impl Default for CursorBlinking {
    fn default() -> Self {
        CursorBlinking::Off
    }
}

impl CursorBlinking {
    fn blinking_override(&self) -> Option<bool> {
        match self {
            Self::Never => Some(false),
            Self::Off | Self::On => None,
            Self::Always => Some(true),
        }
    }
}

impl Into<bool> for CursorBlinking {
    fn into(self) -> bool {
        self == Self::On || self == Self::Always
    }
}

#[serde(untagged)]
#[derive(Deserialize, Debug, Clone, PartialEq, Eq)]
pub enum Program {
    Just(String),
    WithArgs {
        program: String,
        #[serde(default)]
        args: Vec<String>,
    },
}

impl Program {
    pub fn program(&self) -> &str {
        match self {
            Program::Just(program) => program,
            Program::WithArgs { program, .. } => program,
        }
    }

    pub fn args(&self) -> &[String] {
        match self {
            Program::Just(_) => &[],
            Program::WithArgs { args, .. } => args,
        }
    }
}

/// Wrapper around f32 that represents a percentage value between 0.0 and 1.0.
#[derive(Deserialize, Clone, Copy, Debug, PartialEq)]
pub struct Percentage(f32);

impl Default for Percentage {
    fn default() -> Self {
        Percentage(1.0)
    }
}

impl Percentage {
    pub fn new(value: f32) -> Self {
        Percentage(if value < 0.0 {
            0.0
        } else if value > 1.0 {
            1.0
        } else {
            value
        })
    }

    pub fn as_f32(self) -> f32 {
        self.0
    }
}
<|endoftext|>


<commit_before>use cipher;
use cipher::Cipher;
use cipher::CipherChar;
use cipher::is_pairs;

// A Reflector is a substitution cipher comprising 13 pairs.
//
// For example, an `AB` pair where `A -> B` and `B -> A`.
pub struct Reflector {
    cipher: Cipher,
}

impl Reflector {
    pub fn new(cipher: Cipher) -> Reflector {
        assert!(is_pairs(cipher), "Reflector cipher must be in pairs");
        Reflector {
            cipher: cipher,
        }
    }

    pub fn sub(&self, c: CipherChar) -> CipherChar {
        self.cipher[c]
    }
}

pub struct Reflectors {
    pub b: Reflector,
}

impl Reflectors {
    pub fn new() -> Reflectors {
        Reflectors {
            b: Reflector {
                cipher: cipher::from_string("YRUHQSLDPXNGOKMIEBFZCWVJAT")
            }
        }
    }
}

// TODO?
// fn from_pairs(pairs: &str) -> String {
//
// }

#[cfg(test)]
mod tests {
    use super::*;
    use cipher as Cipher;

    #[test]
    fn simple_reflector() {
        let cipher = Cipher::from_string("YRUHQSLDPXNGOKMIEBFZCWVJAT");
        let reflector = Reflector::new(cipher);

        assert_eq!('Y', Cipher::to_char(reflector.sub(Cipher::from_char('A'))));
        assert_eq!('A', Cipher::to_char(reflector.sub(Cipher::from_char('Y'))));
    }

    #[test]
    #[should_panic(expected = "must be in pairs")]
    fn new_reflector_invalid_cipher() {
        let cipher = Cipher::from_string("RYUHQSLDPXNGOKMIEBFZCWVJAT");
        Reflector::new(cipher);
    }
}
<commit_msg>Add Reflector C<commit_after>use cipher;
use cipher::Cipher;
use cipher::CipherChar;
use cipher::is_pairs;

// A Reflector is a substitution cipher comprising 13 pairs.
//
// For example, an `AB` pair where `A -> B` and `B -> A`.
pub struct Reflector {
    cipher: Cipher,
}

impl Reflector {
    pub fn new(cipher: Cipher) -> Reflector {
        assert!(is_pairs(cipher), "Reflector cipher must be in pairs");
        Reflector {
            cipher: cipher,
        }
    }

    pub fn sub(&self, c: CipherChar) -> CipherChar {
        self.cipher[c]
    }
}

pub struct Reflectors {
    pub b: Reflector,
    pub c: Reflector,
}

impl Reflectors {
    pub fn new() -> Reflectors {
        Reflectors {
            b: Reflector {
                cipher: cipher::from_string("YRUHQSLDPXNGOKMIEBFZCWVJAT")
            },
            c: Reflector {
                cipher: cipher::from_string("FVPJIAOYEDRZXWGCTKUQSBNMHL")
            },
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use cipher as Cipher;

    #[test]
    fn simple_reflector() {
        let cipher = Cipher::from_string("YRUHQSLDPXNGOKMIEBFZCWVJAT");
        let reflector = Reflector::new(cipher);

        assert_eq!('Y', Cipher::to_char(reflector.sub(Cipher::from_char('A'))));
        assert_eq!('A', Cipher::to_char(reflector.sub(Cipher::from_char('Y'))));
    }

    #[test]
    #[should_panic(expected = "must be in pairs")]
    fn new_reflector_invalid_cipher() {
        let cipher = Cipher::from_string("RYUHQSLDPXNGOKMIEBFZCWVJAT");
        Reflector::new(cipher);
    }
}
<|endoftext|>