<commit_before>//! SGX-specific access to architectural features.
//!
//! The functionality in this module is further documented in the Intel
//! Software Developer's Manual, Volume 3, Chapter 40.
#![unstable(feature = "sgx_platform", issue = "56975")]

use crate::mem::MaybeUninit;

/// Wrapper struct to force 16-byte alignment.
#[repr(align(16))]
#[unstable(feature = "sgx_platform", issue = "56975")]
pub struct Align16<T>(pub T);

/// Wrapper struct to force 128-byte alignment.
#[repr(align(128))]
#[unstable(feature = "sgx_platform", issue = "56975")]
pub struct Align128<T>(pub T);

/// Wrapper struct to force 512-byte alignment.
#[repr(align(512))]
#[unstable(feature = "sgx_platform", issue = "56975")]
pub struct Align512<T>(pub T);

const ENCLU_EREPORT: u32 = 0;
const ENCLU_EGETKEY: u32 = 1;

/// Call the `EGETKEY` instruction to obtain a 128-bit secret key.
#[unstable(feature = "sgx_platform", issue = "56975")]
pub fn egetkey(request: &Align512<[u8; 512]>) -> Result<Align16<[u8; 16]>, u32> {
    unsafe {
        let mut out = MaybeUninit::uninit();
        let error;

        asm!(
            "enclu",
            inlateout("eax") ENCLU_EGETKEY => error,
            in("rbx") request,
            in("rcx") out.as_mut_ptr(),
            options(nostack),
        );

        match error {
            0 => Ok(out.assume_init()),
            err => Err(err),
        }
    }
}

/// Call the `EREPORT` instruction.
///
/// This creates a cryptographic report describing the contents of the current
/// enclave. The report may be verified by the enclave described in
/// `targetinfo`.
#[unstable(feature = "sgx_platform", issue = "56975")]
pub fn ereport(
    targetinfo: &Align512<[u8; 512]>,
    reportdata: &Align128<[u8; 64]>,
) -> Align512<[u8; 432]> {
    unsafe {
        let mut report = MaybeUninit::uninit();

        asm!(
            "enclu",
            in("eax") ENCLU_EREPORT,
            in("rbx") targetinfo,
            in("rcx") reportdata,
            in("rdx") report.as_mut_ptr(),
            options(preserves_flags, nostack),
        );

        report.assume_init()
    }
}
<commit_msg>Avoid using rbx in SGX inline assembly since it is reserved<commit_after>//! SGX-specific access to architectural features.
//!
//! The functionality in this module is further documented in the Intel
//! Software Developer's Manual, Volume 3, Chapter 40.
#![unstable(feature = "sgx_platform", issue = "56975")]

use crate::mem::MaybeUninit;

/// Wrapper struct to force 16-byte alignment.
#[repr(align(16))]
#[unstable(feature = "sgx_platform", issue = "56975")]
pub struct Align16<T>(pub T);

/// Wrapper struct to force 128-byte alignment.
#[repr(align(128))]
#[unstable(feature = "sgx_platform", issue = "56975")]
pub struct Align128<T>(pub T);

/// Wrapper struct to force 512-byte alignment.
#[repr(align(512))]
#[unstable(feature = "sgx_platform", issue = "56975")]
pub struct Align512<T>(pub T);

const ENCLU_EREPORT: u32 = 0;
const ENCLU_EGETKEY: u32 = 1;

/// Call the `EGETKEY` instruction to obtain a 128-bit secret key.
#[unstable(feature = "sgx_platform", issue = "56975")]
pub fn egetkey(request: &Align512<[u8; 512]>) -> Result<Align16<[u8; 16]>, u32> {
    unsafe {
        let mut out = MaybeUninit::uninit();
        let error;

        asm!(
            // rbx is reserved by LLVM
            "xchg {}, rbx",
            "enclu",
            "mov rbx, {}",
            inout(reg) request => _,
            inlateout("eax") ENCLU_EGETKEY => error,
            in("rcx") out.as_mut_ptr(),
            options(nostack),
        );

        match error {
            0 => Ok(out.assume_init()),
            err => Err(err),
        }
    }
}

/// Call the `EREPORT` instruction.
///
/// This creates a cryptographic report describing the contents of the current
/// enclave. The report may be verified by the enclave described in
/// `targetinfo`.
#[unstable(feature = "sgx_platform", issue = "56975")]
pub fn ereport(
    targetinfo: &Align512<[u8; 512]>,
    reportdata: &Align128<[u8; 64]>,
) -> Align512<[u8; 432]> {
    unsafe {
        let mut report = MaybeUninit::uninit();

        asm!(
            // rbx is reserved by LLVM
            "xchg {}, rbx",
            "enclu",
            "mov rbx, {}",
            inout(reg) targetinfo => _,
            in("eax") ENCLU_EREPORT,
            in("rcx") reportdata,
            in("rdx") report.as_mut_ptr(),
            options(preserves_flags, nostack),
        );

        report.assume_init()
    }
}
<|endoftext|>


<commit_before>use base64;

use crate::chars::Chars;
use bytes::Bytes;

use httpbis::Header;
use httpbis::Headers;

#[derive(Debug, Clone)]
pub struct MetadataKey {
    pub name: Chars,
}

impl MetadataKey {
    pub fn from<S: Into<Chars>>(s: S) -> MetadataKey {
        let chars = s.into();

        // TODO: assert ASCII
        assert!(!chars.is_empty());

        MetadataKey { name: chars }
    }

    pub fn is_bin(&self) -> bool {
        self.name.ends_with("-bin")
    }

    pub fn into_chars(self) -> Chars {
        self.name
    }

    pub fn as_str(&self) -> &str {
        &self.name
    }
}

#[derive(Debug, Clone)]
pub struct MetadataEntry {
    pub key: MetadataKey,
    pub value: Bytes,
}

#[derive(Debug)]
pub enum MetadataDecodeError {
    Base64(base64::DecodeError),
}

impl From<base64::DecodeError> for MetadataDecodeError {
    fn from(decode_error: base64::DecodeError) -> Self {
        MetadataDecodeError::Base64(decode_error)
    }
}

impl MetadataEntry {
    fn into_header(self) -> Header {
        let is_bin = self.key.is_bin();

        let value = match is_bin {
            true => Bytes::from(base64::encode(&self.value)),
            false => self.value,
        };

        Header::new(self.key.name.into_inner(), value)
    }

    fn from_header(header: Header) -> Result<Option<MetadataEntry>, MetadataDecodeError> {
        if header.name().starts_with(":") {
            return Ok(None);
        }
        if header.name().starts_with("grpc-") {
            return Ok(None);
        }
        let key = MetadataKey {
            // TODO: return subbytes
            name: Chars::copy_from_str(header.name()),
        };
        let value = match key.is_bin() {
            true => Bytes::from(base64::decode(&header.value)?),
            false => header.value,
        };
        Ok(Some(MetadataEntry { key, value }))
    }
}

#[derive(Default, Debug, Clone)]
pub struct Metadata {
    pub entries: Vec<MetadataEntry>,
}

impl Metadata {
    pub fn new() -> Metadata {
        Default::default()
    }

    pub fn from_headers(headers: Headers) -> Result<Metadata, MetadataDecodeError> {
        let mut r = Metadata::new();
        for h in headers.iter() {
            // TODO: clone
            if let Some(e) = MetadataEntry::from_header(h.clone())? {
                r.entries.push(e);
            }
        }
        Ok(r)
    }

    pub fn into_headers(self) -> Headers {
        Headers::from_vec(
            self.entries
                .into_iter()
                .map(MetadataEntry::into_header)
                .collect(),
        )
    }

    // Get metadata by key
    pub fn get<'a>(&'a self, name: &str) -> Option<&'a [u8]> {
        for e in &self.entries {
            if e.key.as_str() == name {
                return Some(&e.value[..]);
            }
        }
        None
    }

    pub fn extend(&mut self, extend: Metadata) {
        self.entries.extend(extend.entries);
    }

    pub fn add(&mut self, key: MetadataKey, value: Bytes) {
        self.entries.push(MetadataEntry { key, value });
    }
}
<commit_msg>Fix compilation<commit_after>use base64;

use crate::chars::Chars;
use bytes::Bytes;

use httpbis::Header;
use httpbis::Headers;

#[derive(Debug, Clone)]
pub struct MetadataKey {
    pub name: Chars,
}

impl MetadataKey {
    pub fn from<S: Into<Chars>>(s: S) -> MetadataKey {
        let chars = s.into();

        // TODO: assert ASCII
        assert!(!chars.is_empty());

        MetadataKey { name: chars }
    }

    pub fn is_bin(&self) -> bool {
        self.name.ends_with("-bin")
    }

    pub fn into_chars(self) -> Chars {
        self.name
    }

    pub fn as_str(&self) -> &str {
        &self.name
    }
}

#[derive(Debug, Clone)]
pub struct MetadataEntry {
    pub key: MetadataKey,
    pub value: Bytes,
}

#[derive(Debug)]
pub enum MetadataDecodeError {
    Base64(base64::DecodeError),
}

impl From<base64::DecodeError> for MetadataDecodeError {
    fn from(decode_error: base64::DecodeError) -> Self {
        MetadataDecodeError::Base64(decode_error)
    }
}

impl MetadataEntry {
    fn into_header(self) -> Header {
        let is_bin = self.key.is_bin();

        let value = match is_bin {
            true => Bytes::from(base64::encode(&self.value)),
            false => self.value,
        };

        Header::new(self.key.name.into_inner(), value)
    }

    fn from_header(header: Header) -> Result<Option<MetadataEntry>, MetadataDecodeError> {
        if header.name().starts_with(":") {
            return Ok(None);
        }
        if header.name().starts_with("grpc-") {
            return Ok(None);
        }
        let key = MetadataKey {
            // TODO: return subbytes
            name: Chars::copy_from_str(header.name()),
        };
        let value = match key.is_bin() {
            true => Bytes::from(base64::decode(&header.value)?),
            false => header.value.into(),
        };
        Ok(Some(MetadataEntry { key, value }))
    }
}

#[derive(Default, Debug, Clone)]
pub struct Metadata {
    pub entries: Vec<MetadataEntry>,
}

impl Metadata {
    pub fn new() -> Metadata {
        Default::default()
    }

    pub fn from_headers(headers: Headers) -> Result<Metadata, MetadataDecodeError> {
        let mut r = Metadata::new();
        for h in headers.iter() {
            // TODO: clone
            if let Some(e) = MetadataEntry::from_header(h.clone())? {
                r.entries.push(e);
            }
        }
        Ok(r)
    }

    pub fn into_headers(self) -> Headers {
        Headers::from_vec(
            self.entries
                .into_iter()
                .map(MetadataEntry::into_header)
                .collect(),
        )
    }

    // Get metadata by key
    pub fn get<'a>(&'a self, name: &str) -> Option<&'a [u8]> {
        for e in &self.entries {
            if e.key.as_str() == name {
                return Some(&e.value[..]);
            }
        }
        None
    }

    pub fn extend(&mut self, extend: Metadata) {
        self.entries.extend(extend.entries);
    }

    pub fn add(&mut self, key: MetadataKey, value: Bytes) {
        self.entries.push(MetadataEntry { key, value });
    }
}
<|endoftext|>


<commit_before>use clap::arg_enum;
use oppai_field::field::{self, to_pos, Field, Pos};
use oppai_field::player::Player;
use oppai_field::zobrist::Zobrist;
use rand::Rng;
use std::sync::Arc;

arg_enum! {
  #[derive(Clone, Copy, PartialEq, Debug)]
  pub enum InitialPosition {
    Empty,
    Cross,
    TwoCrosses,
    TripleCross,
  }
}

#[derive(Debug)]
pub struct ExtendedField {
  pub player: Player,
  pub field: Field,
  pub captures: Vec<(Vec<Pos>, Player, usize)>,
  pub captured: Vec<usize>,
}

fn cross(width: u32, height: u32, player: Player) -> [(Pos, Player); 4] {
  let w2 = width / 2;
  let h2 = height / 2;
  [
    (to_pos(width, w2 - 1, h2 - 1), player),
    (to_pos(width, w2 - 1, h2), player.next()),
    (to_pos(width, w2, h2), player),
    (to_pos(width, w2, h2 - 1), player.next()),
  ]
}

fn two_crosses(width: u32, height: u32, player: Player) -> [(Pos, Player); 8] {
  let w2 = width / 2;
  let h2 = height / 2;
  [
    (to_pos(width, w2 - 2, h2 - 1), player),
    (to_pos(width, w2 - 2, h2), player.next()),
    (to_pos(width, w2 - 1, h2), player),
    (to_pos(width, w2 - 1, h2 - 1), player.next()),
    (to_pos(width, w2, h2), player),
    (to_pos(width, w2, h2 - 1), player.next()),
    (to_pos(width, w2 + 1, h2 - 1), player),
    (to_pos(width, w2 + 1, h2), player.next()),
  ]
}

fn triple_cross(width: u32, height: u32, player: Player) -> [(Pos, Player); 8] {
  let w2 = width / 2;
  let h2 = height / 2;
  [
    (to_pos(width, w2 - 1, h2 - 1), player),
    (to_pos(width, w2 - 1, h2), player.next()),
    (to_pos(width, w2, h2), player),
    (to_pos(width, w2, h2 - 1), player.next()),
    (to_pos(width, w2 + 1, h2 - 1), player),
    (to_pos(width, w2, h2 - 2), player.next()),
    (to_pos(width, w2, h2 + 1), player),
    (to_pos(width, w2 + 1, h2), player.next()),
  ]
}

impl ExtendedField {
  pub fn new<R: Rng>(width: u32, height: u32, rng: &mut R) -> Self {
    let zobrist = Arc::new(Zobrist::new(field::length(width, height) * 2, rng));
    let field = Field::new(width, height, zobrist);
    let length = field.length();
    Self {
      player: Player::Red,
      field,
      captures: Vec::new(),
      captured: vec![0; length],
    }
  }

  fn put_points<I>(&mut self, points: I) -> bool
  where
    I: IntoIterator<Item = (Pos, Player)>,
  {
    for (pos, player) in points {
      if !self.put_players_point(pos, player) {
        return false;
      }
    }
    true
  }

  pub fn from_moves<R, I>(width: u32, height: u32, rng: &mut R, moves: I) -> Option<Self>
  where
    R: Rng,
    I: IntoIterator<Item = (Pos, Player)>,
  {
    let mut result = Self::new(width, height, rng);
    if result.put_points(moves) {
      Some(result)
    } else {
      None
    }
  }

  pub fn place_initial_position(&mut self, initial_position: InitialPosition) {
    match initial_position {
      InitialPosition::Empty => {}
      InitialPosition::Cross => {
        self.put_points(
          cross(self.field.width(), self.field.height(), self.player)
            .iter()
            .cloned(),
        );
      }
      InitialPosition::TwoCrosses => {
        self.put_points(
          two_crosses(self.field.width(), self.field.height(), self.player)
            .iter()
            .cloned(),
        );
      }
      InitialPosition::TripleCross => {
        self.put_points(
          triple_cross(self.field.width(), self.field.height(), self.player)
            .iter()
            .cloned(),
        );
      }
    }
  }

  pub fn put_players_point(&mut self, pos: Pos, player: Player) -> bool {
    if self.field.put_point(pos, player) {
      let last_chain = self.field.get_last_chain();
      if let Some(&pos) = last_chain.first() {
        let player = self.field.cell(pos).get_player();
        self.captures.push((last_chain, player, self.field.moves_count()));
        for (pos, _) in self.field.last_changed_cells() {
          if self.captured[pos] == 0 && self.field.cell(pos).is_captured() {
            self.captured[pos] = self.field.moves_count();
          }
        }
      }

      let n = self.field.n(pos);
      let s = self.field.s(pos);
      let w = self.field.w(pos);
      let e = self.field.e(pos);
      let nw = self.field.nw(pos);
      let ne = self.field.ne(pos);
      let sw = self.field.sw(pos);
      let se = self.field.se(pos);

      let mut check = |pos1: Pos, pos2: Pos| {
        if self.field.cell(pos1).get_players_point() == Some(player)
          && self.field.cell(pos2).get_players_point() == Some(player)
        {
          self
            .captures
            .push((vec![pos, pos1, pos2], player, self.field.moves_count()));
          true
        } else {
          false
        }
      };

      let _ = !check(s, e) && (check(s, se) || check(e, se));
      let _ = !check(e, n) && (check(e, ne) || check(n, ne));
      let _ = !check(n, w) && (check(n, nw) || check(w, nw));
      let _ = !check(w, s) && (check(w, sw) || check(s, sw));

      true
    } else {
      false
    }
  }

  pub fn put_point(&mut self, pos: Pos) -> bool {
    if self.put_players_point(pos, self.player) {
      self.player = self.player.next();
      true
    } else {
      false
    }
  }

  pub fn undo(&mut self) -> bool {
    if let Some(player) = self.field.last_player() {
      let moves_count = self.field.moves_count();
      for (pos, _) in self.field.last_changed_cells() {
        if self.captured[pos] == moves_count {
          self.captured[pos] = 0;
        }
      }

      self.field.undo();
      self.player = player;

      while self
        .captures
        .last()
        .map_or(false, |&(_, _, c)| c > self.field.moves_count())
      {
        self.captures.pop();
      }

      true
    } else {
      false
    }
  }
}
<commit_msg>Set next player when loading a file.<commit_after>use clap::arg_enum;
use oppai_field::field::{self, to_pos, Field, Pos};
use oppai_field::player::Player;
use oppai_field::zobrist::Zobrist;
use rand::Rng;
use std::sync::Arc;

arg_enum! {
  #[derive(Clone, Copy, PartialEq, Debug)]
  pub enum InitialPosition {
    Empty,
    Cross,
    TwoCrosses,
    TripleCross,
  }
}

#[derive(Debug)]
pub struct ExtendedField {
  pub player: Player,
  pub field: Field,
  pub captures: Vec<(Vec<Pos>, Player, usize)>,
  pub captured: Vec<usize>,
}

fn cross(width: u32, height: u32, player: Player) -> [(Pos, Player); 4] {
  let w2 = width / 2;
  let h2 = height / 2;
  [
    (to_pos(width, w2 - 1, h2 - 1), player),
    (to_pos(width, w2 - 1, h2), player.next()),
    (to_pos(width, w2, h2), player),
    (to_pos(width, w2, h2 - 1), player.next()),
  ]
}

fn two_crosses(width: u32, height: u32, player: Player) -> [(Pos, Player); 8] {
  let w2 = width / 2;
  let h2 = height / 2;
  [
    (to_pos(width, w2 - 2, h2 - 1), player),
    (to_pos(width, w2 - 2, h2), player.next()),
    (to_pos(width, w2 - 1, h2), player),
    (to_pos(width, w2 - 1, h2 - 1), player.next()),
    (to_pos(width, w2, h2), player),
    (to_pos(width, w2, h2 - 1), player.next()),
    (to_pos(width, w2 + 1, h2 - 1), player),
    (to_pos(width, w2 + 1, h2), player.next()),
  ]
}

fn triple_cross(width: u32, height: u32, player: Player) -> [(Pos, Player); 8] {
  let w2 = width / 2;
  let h2 = height / 2;
  [
    (to_pos(width, w2 - 1, h2 - 1), player),
    (to_pos(width, w2 - 1, h2), player.next()),
    (to_pos(width, w2, h2), player),
    (to_pos(width, w2, h2 - 1), player.next()),
    (to_pos(width, w2 + 1, h2 - 1), player),
    (to_pos(width, w2, h2 - 2), player.next()),
    (to_pos(width, w2, h2 + 1), player),
    (to_pos(width, w2 + 1, h2), player.next()),
  ]
}

impl ExtendedField {
  pub fn new<R: Rng>(width: u32, height: u32, rng: &mut R) -> Self {
    let zobrist = Arc::new(Zobrist::new(field::length(width, height) * 2, rng));
    let field = Field::new(width, height, zobrist);
    let length = field.length();
    Self {
      player: Player::Red,
      field,
      captures: Vec::new(),
      captured: vec![0; length],
    }
  }

  fn put_points<I>(&mut self, points: I) -> bool
  where
    I: IntoIterator<Item = (Pos, Player)>,
  {
    for (pos, player) in points {
      if !self.put_players_point(pos, player) {
        return false;
      }
    }
    true
  }

  pub fn from_moves<R, I>(width: u32, height: u32, rng: &mut R, moves: I) -> Option<Self>
  where
    R: Rng,
    I: IntoIterator<Item = (Pos, Player)>,
  {
    let mut result = Self::new(width, height, rng);
    if result.put_points(moves) {
      if let Some(&pos) = result.field.points_seq().last() {
        result.player = result.field.cell(pos).get_player().next();
      }
      Some(result)
    } else {
      None
    }
  }

  pub fn place_initial_position(&mut self, initial_position: InitialPosition) {
    match initial_position {
      InitialPosition::Empty => {}
      InitialPosition::Cross => {
        self.put_points(
          cross(self.field.width(), self.field.height(), self.player)
            .iter()
            .cloned(),
        );
      }
      InitialPosition::TwoCrosses => {
        self.put_points(
          two_crosses(self.field.width(), self.field.height(), self.player)
            .iter()
            .cloned(),
        );
      }
      InitialPosition::TripleCross => {
        self.put_points(
          triple_cross(self.field.width(), self.field.height(), self.player)
            .iter()
            .cloned(),
        );
      }
    }
  }

  pub fn put_players_point(&mut self, pos: Pos, player: Player) -> bool {
    if self.field.put_point(pos, player) {
      let last_chain = self.field.get_last_chain();
      if let Some(&pos) = last_chain.first() {
        let player = self.field.cell(pos).get_player();
        self.captures.push((last_chain, player, self.field.moves_count()));
        for (pos, _) in self.field.last_changed_cells() {
          if self.captured[pos] == 0 && self.field.cell(pos).is_captured() {
            self.captured[pos] = self.field.moves_count();
          }
        }
      }

      let n = self.field.n(pos);
      let s = self.field.s(pos);
      let w = self.field.w(pos);
      let e = self.field.e(pos);
      let nw = self.field.nw(pos);
      let ne = self.field.ne(pos);
      let sw = self.field.sw(pos);
      let se = self.field.se(pos);

      let mut check = |pos1: Pos, pos2: Pos| {
        if self.field.cell(pos1).get_players_point() == Some(player)
          && self.field.cell(pos2).get_players_point() == Some(player)
        {
          self
            .captures
            .push((vec![pos, pos1, pos2], player, self.field.moves_count()));
          true
        } else {
          false
        }
      };

      let _ = !check(s, e) && (check(s, se) || check(e, se));
      let _ = !check(e, n) && (check(e, ne) || check(n, ne));
      let _ = !check(n, w) && (check(n, nw) || check(w, nw));
      let _ = !check(w, s) && (check(w, sw) || check(s, sw));

      true
    } else {
      false
    }
  }

  pub fn put_point(&mut self, pos: Pos) -> bool {
    if self.put_players_point(pos, self.player) {
      self.player = self.player.next();
      true
    } else {
      false
    }
  }

  pub fn undo(&mut self) -> bool {
    if let Some(player) = self.field.last_player() {
      let moves_count = self.field.moves_count();
      for (pos, _) in self.field.last_changed_cells() {
        if self.captured[pos] == moves_count {
          self.captured[pos] = 0;
        }
      }

      self.field.undo();
      self.player = player;

      while self
        .captures
        .last()
        .map_or(false, |&(_, _, c)| c > self.field.moves_count())
      {
        self.captures.pop();
      }

      true
    } else {
      false
    }
  }
}
<|endoftext|>


<commit_before>
use error::{StoreError, StoreErrorKind};
use std::io::{Seek, SeekFrom};
use std::path::{Path, PathBuf};
use std::fs::{File, OpenOptions};

/**
 * LazyFile type
 *
 * A lazy file is either absent, but a path to it is available, or it is present.
 */
#[derive(Debug)]
pub enum LazyFile {
    Absent(PathBuf),
    File(File)
}

fn open_file<A: AsRef<Path>>(p: A) -> ::std::io::Result<File> {
    OpenOptions::new().write(true).read(true).open(p)
}

fn create_file<A: AsRef<Path>>(p: A) -> ::std::io::Result<File> {
    OpenOptions::new().write(true).read(true).create(true).open(p)
}

impl LazyFile {

    /**
     * Create a new LazyFile instance from a Path
     */
    pub fn new(p: PathBuf) -> LazyFile {
        LazyFile::Absent(p)
    }

    /**
     * Create a new LazyFile instance from an already existing file
     */
    pub fn new_with_file(f: File) -> LazyFile {
        LazyFile::File(f)
    }

    /**
     * Get the file behind a LazyFile object
     */
    pub fn get_file(&mut self) -> Result<&File, StoreError> {
        match self.get_file_mut() {
            Ok(file) => Ok(&*file),
            Err(e) => Err(e)
        }
    }

    /**
     * Get the mutable file behind a LazyFile object
     */
    pub fn get_file_mut(&mut self) -> Result<&mut File, StoreError> {
        let file = match *self {
            LazyFile::File(ref mut f) => return {
                // We seek to the beginning of the file since we expect each
                // access to the file to be in a different context
                f.seek(SeekFrom::Start(0)).map_err(|e|
                    StoreError::new(
                        StoreErrorKind::FileNotCreated, Some(Box::new(e))));
                Ok(f)
            },
            LazyFile::Absent(ref p) => {
                try!(open_file(p).map_err(|e| {
                    StoreError::new(StoreErrorKind::FileNotFound,
                                    Some(Box::new(e)))
                }))
            }
        };
        *self = LazyFile::File(file);
        if let LazyFile::File(ref mut f) = *self {
            return Ok(f);
        }
        unreachable!()
    }

    /**
     * Create a file out of this LazyFile object
     */
    pub fn create_file(&mut self) -> Result<&mut File, StoreError> {
        let file = match *self {
            LazyFile::File(ref mut f) => return Ok(f),
            LazyFile::Absent(ref p) => {
                try!(create_file(p).map_err(|e| {
                    StoreError::new(StoreErrorKind::FileNotFound,
                                    Some(Box::new(e)))
                }))
            }
        };
        *self = LazyFile::File(file);
        if let LazyFile::File(ref mut f) = *self {
            return Ok(f);
        }
        unreachable!()
    }
}

#[cfg(test)]
mod test {
    use super::LazyFile;
    use std::io::{Read, Write, Seek, SeekFrom};
    use std::path::PathBuf;
    use std::fs::File;
    use tempdir::TempDir;

    fn get_dir() -> TempDir {
        TempDir::new("test-image").unwrap()
    }

    #[test]
    fn lazy_file() {
        let dir = get_dir();
        let mut path = PathBuf::from(dir.path());
        path.set_file_name("test1");
        let mut lf = LazyFile::new(path);

        write!(lf.create_file().unwrap(), "Hello World").unwrap();
        dir.close().unwrap();
    }

    #[test]
    fn lazy_file_with_file() {
        let dir = get_dir();
        let mut path = PathBuf::from(dir.path());
        path.set_file_name("test2");
        let mut lf = LazyFile::new(path.clone());

        {
            let mut file = lf.create_file().unwrap();

            file.write(b"Hello World").unwrap();
            file.sync_all().unwrap();
        }

        {
            let mut file = lf.get_file().unwrap();
            let mut s = Vec::new();
            file.read_to_end(&mut s).unwrap();
            assert_eq!(s, "Hello World".to_string().into_bytes());
        }

        dir.close().unwrap();
    }
}
<commit_msg>Add debug output for LazyFile::{get_file_mut,create_file}()<commit_after>
use error::{StoreError, StoreErrorKind};
use std::io::{Seek, SeekFrom};
use std::path::{Path, PathBuf};
use std::fs::{File, OpenOptions};

/**
 * LazyFile type
 *
 * A lazy file is either absent, but a path to it is available, or it is present.
 */
#[derive(Debug)]
pub enum LazyFile {
    Absent(PathBuf),
    File(File)
}

fn open_file<A: AsRef<Path>>(p: A) -> ::std::io::Result<File> {
    OpenOptions::new().write(true).read(true).open(p)
}

fn create_file<A: AsRef<Path>>(p: A) -> ::std::io::Result<File> {
    OpenOptions::new().write(true).read(true).create(true).open(p)
}

impl LazyFile {

    /**
     * Create a new LazyFile instance from a Path
     */
    pub fn new(p: PathBuf) -> LazyFile {
        LazyFile::Absent(p)
    }

    /**
     * Create a new LazyFile instance from an already existing file
     */
    pub fn new_with_file(f: File) -> LazyFile {
        LazyFile::File(f)
    }

    /**
     * Get the file behind a LazyFile object
     */
    pub fn get_file(&mut self) -> Result<&File, StoreError> {
        match self.get_file_mut() {
            Ok(file) => Ok(&*file),
            Err(e) => Err(e)
        }
    }

    /**
     * Get the mutable file behind a LazyFile object
     */
    pub fn get_file_mut(&mut self) -> Result<&mut File, StoreError> {
        debug!("Getting lazy file: {:?}", self);
        let file = match *self {
            LazyFile::File(ref mut f) => return {
                // We seek to the beginning of the file since we expect each
                // access to the file to be in a different context
                f.seek(SeekFrom::Start(0)).map_err(|e|
                    StoreError::new(
                        StoreErrorKind::FileNotCreated, Some(Box::new(e))));
                Ok(f)
            },
            LazyFile::Absent(ref p) => {
                try!(open_file(p).map_err(|e| {
                    StoreError::new(StoreErrorKind::FileNotFound,
                                    Some(Box::new(e)))
                }))
            }
        };
        *self = LazyFile::File(file);
        if let LazyFile::File(ref mut f) = *self {
            return Ok(f);
        }
        unreachable!()
    }

    /**
     * Create a file out of this LazyFile object
     */
    pub fn create_file(&mut self) -> Result<&mut File, StoreError> {
        debug!("Creating lazy file: {:?}", self);
        let file = match *self {
            LazyFile::File(ref mut f) => return Ok(f),
            LazyFile::Absent(ref p) => {
                try!(create_file(p).map_err(|e| {
                    StoreError::new(StoreErrorKind::FileNotFound,
                                    Some(Box::new(e)))
                }))
            }
        };
        *self = LazyFile::File(file);
        if let LazyFile::File(ref mut f) = *self {
            return Ok(f);
        }
        unreachable!()
    }
}

#[cfg(test)]
mod test {
    use super::LazyFile;
    use std::io::{Read, Write, Seek, SeekFrom};
    use std::path::PathBuf;
    use std::fs::File;
    use tempdir::TempDir;

    fn get_dir() -> TempDir {
        TempDir::new("test-image").unwrap()
    }

    #[test]
    fn lazy_file() {
        let dir = get_dir();
        let mut path = PathBuf::from(dir.path());
        path.set_file_name("test1");
        let mut lf = LazyFile::new(path);

        write!(lf.create_file().unwrap(), "Hello World").unwrap();
        dir.close().unwrap();
    }

    #[test]
    fn lazy_file_with_file() {
        let dir = get_dir();
        let mut path = PathBuf::from(dir.path());
        path.set_file_name("test2");
        let mut lf = LazyFile::new(path.clone());

        {
            let mut file = lf.create_file().unwrap();

            file.write(b"Hello World").unwrap();
            file.sync_all().unwrap();
        }

        {
            let mut file = lf.get_file().unwrap();
            let mut s = Vec::new();
            file.read_to_end(&mut s).unwrap();
            assert_eq!(s, "Hello World".to_string().into_bytes());
        }

        dir.close().unwrap();
    }
}
<|endoftext|>


<commit_before>use glutin::Window;

use event::{Event, PollEvents, Reactor};
use render::{Context, GlutinContext, MetaContext};

pub struct Harness<A, C>
    where A: Application<C>,
          C: MetaContext
{
    application: A,
    context: Context<C>,
}

impl<A> Harness<A, GlutinContext>
    where A: Application<GlutinContext>
{
    pub fn from_glutin_window(application: A, window: Window) -> Self {
        Harness {
            application: application,
            context: Context::from_glutin_window(window),
        }
    }
}

impl<A, C> Harness<A, C>
    where A: Application<C>,
          C: MetaContext
{
    pub fn start(&mut self) {
        'main: loop {
            self.context.clear();
            for event in self.context.window.poll_events() {
                match event {
                    Event::Closed => {
                        break 'main;
                    }
                    Event::Resized(..) => {
                        self.context.update_frame_buffer_view();
                    }
                    _ => {}
                }
                self.application.react(&event);
            }
            self.application.update();
            self.application.draw(&mut self.context);
            self.context.flush().unwrap();
        }
        self.application.stop();
    }
}

pub trait Application<C>: Reactor
    where C: MetaContext
{
    fn update(&mut self);
    // TODO: Do not accept the entire `Context`. Maybe `Context` can emit a
    //       more limited type that can be used for rendering.
    fn draw(&mut self, context: &mut Context<C>);
    fn stop(&mut self) {}
}
<commit_msg>Move `Application` out of `Harness`.<commit_after>use glutin::Window;

use event::{Event, PollEvents, Reactor};
use render::{Context, GlutinContext, MetaContext};

pub struct Harness<C>
    where C: MetaContext
{
    context: Context<C>,
}

impl Harness<GlutinContext> {
    pub fn from_glutin_window(window: Window) -> Self {
        Harness {
            context: Context::from_glutin_window(window),
        }
    }
}

impl<C> Harness<C>
    where C: MetaContext
{
    pub fn start<A>(&mut self, application: &mut A)
        where A: Application<C>
    {
        'main: loop {
            self.context.clear();
            for event in self.context.window.poll_events() {
                match event {
                    Event::Closed => {
                        break 'main;
                    }
                    Event::Resized(..) => {
                        self.context.update_frame_buffer_view();
                    }
                    _ => {}
                }
                application.react(&event);
            }
            application.update();
            application.draw(&mut self.context);
            self.context.flush().unwrap();
        }
        application.stop();
    }
}

pub trait Application<C>: Reactor
    where C: MetaContext
{
    fn update(&mut self);
    // TODO: Do not accept the entire `Context`. Maybe `Context` can emit a
    //       more limited type that can be used for rendering.
    fn draw(&mut self, context: &mut Context<C>);
    fn stop(&mut self) {}
}
<|endoftext|>


<commit_before>use std::cell::Cell;
use std::rc::Rc;

use gfx_device_gl::Factory;
use piston_window::*;
use piston_window::character::CharacterCache;

use game::asset_factory::AssetFactory;
use game::config::{Config, ConfigBuilder};
use game::factory::TetrominoFactory;
use game::grid::Grid;
use game::tetromino::{Direction, MoveResult, Rotation, RotationResult, Tetromino};
use game::timer::{Timer, TimerTickResult};
use game::window::GameWindow;

use game::scoring::{Score, ScoringSystem, ScoreMetaData, DefaultScoringSystem};

pub struct Game {
    time: Rc<Cell<f64>>,
    config: Config,
    asset_factory: AssetFactory,
    grid: Grid,
    lockstep_timer: Timer,
    drop_timer: Timer,
    scoring_system: Box<ScoringSystem>,
    score: Score,
    tetromino: Tetromino,
    tetromino_factory: TetrominoFactory,
}

impl Game {
    pub fn new(gfx_factory: Factory) -> Game {
        let time = RcCell!(0.0);
        let factory = TetrominoFactory::new();
        let config = ConfigBuilder::new()
            .grid_size((10, 22))
            .grid_offset(10.0)
            .tile_size(29.0)
            .build();

        let tetromino = factory.create(&config);

        Game {
            time: time.clone(),
            config: config,
            asset_factory: AssetFactory::new(gfx_factory),
            grid: Grid::new(),
            lockstep_timer: Timer::new(0.5, time.clone()),
            drop_timer: Timer::new(0.5, time.clone()),
            score: Score::new(),
            scoring_system: Box::new(DefaultScoringSystem),
            tetromino: tetromino,
            tetromino_factory: factory,
        }
    }

    pub fn process(&mut self, e: &Event) -> bool {
        match *e {
            Event::Update(update) => {
                // Update the globa game time
                self.update_time(update.dt);

                // Drop the current block if it needs dropping
                self.drop_current_block(None);

                // Apply the currently active tetromino into the grid
                self.grid.apply_tetromino(&self.tetromino);
            }
            Event::Input(ref input_event) => {
                self.handle_input(input_event);
            }
            _ => (),
        }

        true
    }

    /// Increments the global time
    fn update_time(&mut self, delta: f64) {
        self.time.set(self.time.get() + delta);
    }

    fn drop_current_block<O>(&mut self, force_drop: O)
        where O: Into<Option<bool>>
    {
        // If we can drop, check if we are ready and drop the active tetromino
        match self.tetromino.can_move(Direction::South, &self.grid.boxes) {
            MoveResult::Allow => {
                if self.drop_timer.elapsed() || force_drop.into().is_some() {
                    self.tetromino.drop_down();
                    self.drop_timer.reset();
                    self.lockstep_timer.reset();
                }
            }
            MoveResult::Blocked => {
                // If its blocked.. first check if our LockStep has elapsed
                if self.lockstep_timer.elapsed() {
                    // Store the tetromino in the grid and create a new tetromino
                    self.new_tetromino();
                    self.lockstep_timer.stop();
                    let lines_cleared = self.grid.remove_complete_lines(&self.config);

                    self.scoring_system.update_score(&mut self.score,
                                                     ScoreMetaData {
                                                         lines_cleared: lines_cleared,
                                                     });
                }
            }
            _ => (),
        }
    }

    fn new_tetromino(&mut self) {
        self.grid.store_tetromino(&self.tetromino);
        self.tetromino = self.tetromino_factory.create(&self.config);
    }

    fn handle_input(&mut self, input: &Input) {
        if let Input::Press(ref button) = *input {
            match *button {
                Button::Keyboard(Key::Z) => {
                    match self.tetromino.can_rotate(Rotation::CounterClockwise, &self.grid.boxes) {
                        RotationResult::Allow => self.tetromino.rotate(Rotation::CounterClockwise),
                        _ => (),
                    }
                }
                Button::Keyboard(Key::X) => {
                    match self.tetromino.can_rotate(Rotation::Clockwise, &self.grid.boxes) {
                        RotationResult::Allow => self.tetromino.rotate(Rotation::Clockwise),
                        _ => (),
                    }
                }
                Button::Keyboard(Key::Left) => {
                    match self.tetromino.can_move(Direction::West, &self.grid.boxes) {
                        MoveResult::Allow => self.tetromino.move_left(),
                        MoveResult::Blocked => self.new_tetromino(),
                        _ => (),
                    }
                }
                Button::Keyboard(Key::Right) => {
                    match self.tetromino.can_move(Direction::East, &self.grid.boxes) {
                        MoveResult::Allow => self.tetromino.move_right(),
                        MoveResult::Blocked => self.new_tetromino(),
                        _ => (),
                    }
                }
                Button::Keyboard(Key::Down) => {
                    self.drop_current_block(true);
                }
                _ => (),
            }
        }
    }

    pub fn render(&mut self, window: &mut GameWindow, e: &Event) {
        window.draw_2d(e, |c, g| {
            clear([1.0, 1.0, 1.0, 1.0], g);

            self.grid.render(&self.config, c, g, &e);
            self.score.render(self.asset_factory.font.as_mut().unwrap(), c, g);
        });
    }
}
<commit_msg>Added Space bar to immediately drop current tetromino<commit_after>use std::cell::Cell;
use std::rc::Rc;

use gfx_device_gl::Factory;
use piston_window::*;
use piston_window::character::CharacterCache;

use game::asset_factory::AssetFactory;
use game::config::{Config, ConfigBuilder};
use game::factory::TetrominoFactory;
use game::grid::Grid;
use game::tetromino::{Direction, MoveResult, Rotation, RotationResult, Tetromino};
use game::timer::{Timer, TimerTickResult};
use game::window::GameWindow;

use game::scoring::{Score, ScoringSystem, ScoreMetaData, DefaultScoringSystem};

pub struct Game {
    time: Rc<Cell<f64>>,
    config: Config,
    asset_factory: AssetFactory,
    grid: Grid,
    lockstep_timer: Timer,
    drop_timer: Timer,
    scoring_system: Box<ScoringSystem>,
    score: Score,
    tetromino: Tetromino,
    tetromino_factory: TetrominoFactory,
}

impl Game {
    pub fn new(gfx_factory: Factory) -> Game {
        let time = RcCell!(0.0);
        let factory = TetrominoFactory::new();
        let config = ConfigBuilder::new()
            .grid_size((10, 22))
            .grid_offset(10.0)
            .tile_size(29.0)
            .build();

        let tetromino = factory.create(&config);

        Game {
            time: time.clone(),
            config: config,
            asset_factory: AssetFactory::new(gfx_factory),
            grid: Grid::new(),
            lockstep_timer: Timer::new(0.5, time.clone()),
            drop_timer: Timer::new(0.5, time.clone()),
            score: Score::new(),
            scoring_system: Box::new(DefaultScoringSystem),
            tetromino: tetromino,
            tetromino_factory: factory,
        }
    }

    pub fn process(&mut self, e: &Event) -> bool {
        match *e {
            Event::Update(update) => {
                // Update the globa game time
                self.update_time(update.dt);

                // Drop the current block if it needs dropping
                self.move_down(None);

                // Apply the currently active tetromino into the grid
                self.grid.apply_tetromino(&self.tetromino);
            }
            Event::Input(ref input_event) => {
                self.handle_input(input_event);
            }
            _ => (),
        }

        true
    }

    /// Increments the global time
    fn update_time(&mut self, delta: f64) {
        self.time.set(self.time.get() + delta);
    }

    fn move_down<O>(&mut self, force_drop: O)
        where O: Into<Option<bool>>
    {
        // If we can drop, check if we are ready and drop the active tetromino
        match self.tetromino.can_move(Direction::South, &self.grid.boxes) {
            MoveResult::Allow => {
                if self.drop_timer.elapsed() || force_drop.into().is_some() {
                    self.tetromino.drop_down();
                    self.drop_timer.reset();
                    self.lockstep_timer.reset();
                }
            }
            MoveResult::Blocked => {
                self.handle_blocked(None);
            }
            _ => (),
        }
    }

    fn handle_blocked<O>(&mut self, force: O)
        where O: Into<Option<bool>>
    {
        // If its blocked.. first check if our LockStep has elapsed
        if self.lockstep_timer.elapsed() || force.into().is_some() {
            // Store the tetromino in the grid and create a new tetromino
            self.new_tetromino();
            self.lockstep_timer.stop();
            let lines_cleared = self.grid.remove_complete_lines(&self.config);

            self.scoring_system.update_score(&mut self.score,
                                             ScoreMetaData { lines_cleared: lines_cleared });
        }
    }

    /// Drops a Tetromino straight down until it hits the lowest
    /// possible point.
    fn drop_tetromino(&mut self) {
        loop {
            if let MoveResult::Allow = self.tetromino.can_move(Direction::South, &self.grid.boxes) {
                self.tetromino.drop_down();
            } else {
                break;
            }
        }
    }

    fn new_tetromino(&mut self) {
        self.grid.store_tetromino(&self.tetromino);
        self.tetromino = self.tetromino_factory.create(&self.config);
    }

    fn handle_input(&mut self, input: &Input) {
        if let Input::Press(ref button) = *input {
            match *button {
                Button::Keyboard(Key::Z) => {
                    match self.tetromino.can_rotate(Rotation::CounterClockwise, &self.grid.boxes) {
                        RotationResult::Allow => self.tetromino.rotate(Rotation::CounterClockwise),
                        _ => (),
                    }
                }
                Button::Keyboard(Key::X) => {
                    match self.tetromino.can_rotate(Rotation::Clockwise, &self.grid.boxes) {
                        RotationResult::Allow => self.tetromino.rotate(Rotation::Clockwise),
                        _ => (),
                    }
                }
                Button::Keyboard(Key::Left) => {
                    match self.tetromino.can_move(Direction::West, &self.grid.boxes) {
                        MoveResult::Allow => self.tetromino.move_left(),
                        MoveResult::Blocked => self.new_tetromino(),
                        _ => (),
                    }
                }
                Button::Keyboard(Key::Right) => {
                    match self.tetromino.can_move(Direction::East, &self.grid.boxes) {
                        MoveResult::Allow => self.tetromino.move_right(),
                        MoveResult::Blocked => self.new_tetromino(),
                        _ => (),
                    }
                }
                Button::Keyboard(Key::Down) => {
                    self.move_down(true);
                }
                Button::Keyboard(Key::Space) => {
                    self.drop_tetromino();
                    // Stop the lockstep timer straight away
                    self.handle_blocked(true);
                }
                _ => (),
            }
        }
    }

    pub fn render(&mut self, window: &mut GameWindow, e: &Event) {
        window.draw_2d(e, |c, g| {
            clear([1.0, 1.0, 1.0, 1.0], g);

            self.grid.render(&self.config, c, g, &e);
            self.score.render(self.asset_factory.font.as_mut().unwrap(), c, g);
        });
    }
}
<|endoftext|>


<commit_before>
use calx_ecs::Entity;
use calx_grid::Dir6;
use display;
use euclid::{Point2D, Rect, Size2D, vec2};
use rand;
use scancode::Scancode;
use std::fs::File;
use std::io::prelude::*;
use vitral::{Context, FracPoint2D, FracSize2D, FracRect, Align};
use world::{Command, Location, Slot, TerrainQuery, World, on_screen};

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum State {
    Main,
    Inventory(InventoryAction),
    Console,
    Aim(AimAction),
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum InventoryAction {
    View,
    Drop,
    Equip,
    Use,
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum AimAction {
    Zap(Entity),
    // Maybe add intrinsic abilities not tied to a specific entity later
}

pub struct GameLoop {
    pub world: World,
    pub console: display::Console,
    state: State,
}

impl GameLoop {
    pub fn new(world: World) -> GameLoop {
        GameLoop {
            world,
            console: display::Console::default(),
            state: State::Main,
        }
    }

    fn game_input(&mut self, scancode: Scancode) -> Result<(), ()> {
        use scancode::Scancode::*;
        match scancode {
            Tab => {
                self.state = State::Console;
                Ok(())
            }
            Q => self.world.step(Dir6::Northwest),
            W => self.world.step(Dir6::North),
            E => self.world.step(Dir6::Northeast),
            A => self.world.step(Dir6::Southwest),
            S => self.world.step(Dir6::South),
            D => self.world.step(Dir6::Southeast),
            I => {
                self.state = State::Inventory(InventoryAction::View);
                Ok(())
            }
            F5 => {
                self.world
                    .save(&mut File::create("save.gam").unwrap())
                    .unwrap();
                Ok(())
            }
            F9 => {
                let mut savefile = File::open("save.gam").unwrap();
                self.world = World::load(&mut savefile).unwrap();
                Ok(())
            }
            _ => Ok(()),
        }
    }

    fn inventory_input(&mut self, scancode: Scancode) -> Result<(), ()> {
        use scancode::Scancode::*;
        match scancode {
            Escape => {
                self.state = State::Main;
                Ok(())
            }
            _ => Ok(()),
        }
    }

    fn console_input(&mut self, scancode: Scancode) -> Result<(), ()> {
        use scancode::Scancode::*;
        match scancode {
            Tab => {
                self.state = State::Main;
                Ok(())
            }
            Enter | PadEnter => {
                let input = self.console.get_input();
                let _ = writeln!(&mut self.console, "{}", input);
                if let Err(e) = self.parse(&input) {
                    let _ = writeln!(&mut self.console, "{}", e);
                }
                Ok(())
            }
            _ => Ok(()),
        }
    }

    fn dump(&mut self) { dump_map(&self.world); }

    /// Generate a new random cave map.
    fn cave(&mut self) {
        use world::mapgen;
        self.world = World::new(1);
        mapgen::caves(
            &mut self.world,
            &mut rand::thread_rng(),
            Location::new(0, 0, 0),
            300,
        );
    }

    /// Generate a new random maze map.
    fn maze(&mut self, sparseness: usize) {
        use world::mapgen;
        self.world = World::new(1);
        mapgen::maze(&mut self.world, &mut rand::thread_rng(), sparseness);
    }

    /// Generate a new random rooms and corridors
    fn rooms(&mut self) {
        use world::mapgen;
        self.world = World::new(1);
        mapgen::rooms(&mut self.world, &mut rand::thread_rng());
    }

    command_parser!{
        fn cave(&mut self);
        fn maze(&mut self, sparseness: usize);
        fn rooms(&mut self);

        fn dump(&mut self);
    }

    fn draw_inventory(&mut self, c: &mut display::Backend, area: &Rect<f32>) {
        // Start with hardcoded invetory data to test the UI logic.
        c.fill_rect(
            FracRect::new(FracPoint2D::new(0.0, 0.0), FracSize2D::new(1.0, 1.0)),
            [0.0, 0.0, 0.0, 0.99],
        );

        let mut letter_pos = Point2D::new(0.0, 0.0);
        let mut slot_name_pos = Point2D::new(20.0, 0.0);
        let mut item_name_pos = Point2D::new(80.0, 0.0);
        let text_color = [1.0, 1.0, 1.0, 1.0];

        for slot in SLOT_DATA.iter() {
            // TODO: Bounding box for these is a button...
            letter_pos = c.draw_text(
                letter_pos,
                Align::Left,
                text_color,
                &format!("{})", slot.key),
            );
            slot_name_pos = c.draw_text(slot_name_pos, Align::Left, text_color, slot.name);
            item_name_pos = c.draw_text(item_name_pos, Align::Left, text_color, "[Inventory Item]");
        }
    }

    fn draw_console(&mut self, context: &mut display::Backend, screen_area: &Rect<f32>) {}

    pub fn draw(&mut self, context: &mut display::Backend, screen_area: &Rect<f32>) {
        let camera_loc = Location::new(0, 0, 0);
        let mut view = display::WorldView::new(camera_loc, *screen_area);
        view.show_cursor = true;

        view.draw(&self.world, context);

        match self.state {
            State::Inventory(_) => {
                self.draw_inventory(
                    context,
                    &Rect::new(Point2D::new(0.0, 0.0), Size2D::new(320.0, 360.0)),
                );
            }
            State::Console => {
                let mut console_area = *screen_area;
                console_area.size.height /= 2.0;
                self.console.draw_large(context, &console_area);
            }
            _ => {
                self.console.draw_small(context, screen_area);
            }
        }

        if let Some(scancode) = context.poll_key().and_then(|k| Scancode::new(k.scancode)) {
            let _ = match self.state {
                State::Inventory(_) => self.inventory_input(scancode),
                State::Console => self.console_input(scancode),
                _ => self.game_input(scancode),
            };
        }
    }
}

/// Print the world map as ASCII.
fn dump_map(world: &World) {
    for y in -21..21 {
        for x in -39..41 {
            if (x + y) % 2 != 0 {
                print!(" ");
                continue;
            }
            let pos = vec2((x + y) / 2, y);
            if on_screen(pos) {
                let t = world.terrain(Location::new(0, 0, 0) + pos);
                if t.is_open() {
                    print!(".");
                } else if t.is_door() {
                    print!("+");
                } else if t.is_wall() {
                    print!("#");
                } else {
                    print!("*");
                }
            } else {
                print!(" ");
            }
        }
        println!("");
    }
}

struct SlotData {
    key: char,
    slot: Slot,
    name: &'static str,
}

#[cfg_attr(rustfmt, rustfmt_skip)]
static SLOT_DATA: [SlotData; 34] = [
    SlotData { key: '1', slot: Slot::Spell1,     name: "Ability" },
    SlotData { key: '2', slot: Slot::Spell2,     name: "Ability" },
    SlotData { key: '3', slot: Slot::Spell3,     name: "Ability" },
    SlotData { key: '4', slot: Slot::Spell4,     name: "Ability" },
    SlotData { key: '5', slot: Slot::Spell5,     name: "Ability" },
    SlotData { key: '6', slot: Slot::Spell6,     name: "Ability" },
    SlotData { key: '7', slot: Slot::Spell7,     name: "Ability" },
    SlotData { key: '8', slot: Slot::Spell8,     name: "Ability" },
    SlotData { key: 'a', slot: Slot::Melee,      name: "Weapon" },
    SlotData { key: 'b', slot: Slot::Ranged,     name: "Ranged" },
    SlotData { key: 'c', slot: Slot::Head,       name: "Head" },
    SlotData { key: 'd', slot: Slot::Body,       name: "Body" },
    SlotData { key: 'e', slot: Slot::Feet,       name: "Feet" },
    SlotData { key: 'f', slot: Slot::TrinketF,   name: "Trinket" },
    SlotData { key: 'g', slot: Slot::TrinketG,   name: "Trinket" },
    SlotData { key: 'h', slot: Slot::TrinketH,   name: "Trinket" },
    SlotData { key: 'i', slot: Slot::TrinketI,   name: "Trinket" },
    SlotData { key: 'j', slot: Slot::InventoryJ, name: "" },
    SlotData { key: 'k', slot: Slot::InventoryK, name: "" },
    SlotData { key: 'l', slot: Slot::InventoryL, name: "" },
    SlotData { key: 'm', slot: Slot::InventoryM, name: "" },
    SlotData { key: 'n', slot: Slot::InventoryN, name: "" },
    SlotData { key: 'o', slot: Slot::InventoryO, name: "" },
    SlotData { key: 'p', slot: Slot::InventoryP, name: "" },
    SlotData { key: 'q', slot: Slot::InventoryQ, name: "" },
    SlotData { key: 'r', slot: Slot::InventoryR, name: "" },
    SlotData { key: 's', slot: Slot::InventoryS, name: "" },
    SlotData { key: 't', slot: Slot::InventoryT, name: "" },
    SlotData { key: 'u', slot: Slot::InventoryU, name: "" },
    SlotData { key: 'v', slot: Slot::InventoryV, name: "" },
    SlotData { key: 'w', slot: Slot::InventoryW, name: "" },
    SlotData { key: 'x', slot: Slot::InventoryX, name: "" },
    SlotData { key: 'y', slot: Slot::InventoryY, name: "" },
    SlotData { key: 'z', slot: Slot::InventoryZ, name: "" },
];
<commit_msg>Scancodes for slot data<commit_after>
use calx_ecs::Entity;
use calx_grid::Dir6;
use display;
use euclid::{Point2D, Rect, Size2D, vec2};
use rand;
use scancode::Scancode;
use std::fs::File;
use std::io::prelude::*;
use vitral::{Context, FracPoint2D, FracSize2D, FracRect, Align};
use world::{Command, Location, Slot, TerrainQuery, World, on_screen};

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum State {
    Main,
    Inventory(InventoryAction),
    Console,
    Aim(AimAction),
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum InventoryAction {
    View,
    Drop,
    Equip,
    Use,
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum AimAction {
    Zap(Entity),
    // Maybe add intrinsic abilities not tied to a specific entity later
}

pub struct GameLoop {
    pub world: World,
    pub console: display::Console,
    state: State,
}

impl GameLoop {
    pub fn new(world: World) -> GameLoop {
        GameLoop {
            world,
            console: display::Console::default(),
            state: State::Main,
        }
    }

    fn game_input(&mut self, scancode: Scancode) -> Result<(), ()> {
        use scancode::Scancode::*;
        match scancode {
            Tab => {
                self.state = State::Console;
                Ok(())
            }
            Q => self.world.step(Dir6::Northwest),
            W => self.world.step(Dir6::North),
            E => self.world.step(Dir6::Northeast),
            A => self.world.step(Dir6::Southwest),
            S => self.world.step(Dir6::South),
            D => self.world.step(Dir6::Southeast),
            I => {
                self.state = State::Inventory(InventoryAction::View);
                Ok(())
            }
            F5 => {
                self.world
                    .save(&mut File::create("save.gam").unwrap())
                    .unwrap();
                Ok(())
            }
            F9 => {
                let mut savefile = File::open("save.gam").unwrap();
                self.world = World::load(&mut savefile).unwrap();
                Ok(())
            }
            _ => Ok(()),
        }
    }

    fn inventory_input(&mut self, scancode: Scancode) -> Result<(), ()> {
        use scancode::Scancode::*;
        match scancode {
            Escape => {
                self.state = State::Main;
                Ok(())
            }
            _ => Ok(()),
        }
    }

    fn console_input(&mut self, scancode: Scancode) -> Result<(), ()> {
        use scancode::Scancode::*;
        match scancode {
            Tab => {
                self.state = State::Main;
                Ok(())
            }
            Enter | PadEnter => {
                let input = self.console.get_input();
                let _ = writeln!(&mut self.console, "{}", input);
                if let Err(e) = self.parse(&input) {
                    let _ = writeln!(&mut self.console, "{}", e);
                }
                Ok(())
            }
            _ => Ok(()),
        }
    }

    fn dump(&mut self) { dump_map(&self.world); }

    /// Generate a new random cave map.
    fn cave(&mut self) {
        use world::mapgen;
        self.world = World::new(1);
        mapgen::caves(
            &mut self.world,
            &mut rand::thread_rng(),
            Location::new(0, 0, 0),
            300,
        );
    }

    /// Generate a new random maze map.
    fn maze(&mut self, sparseness: usize) {
        use world::mapgen;
        self.world = World::new(1);
        mapgen::maze(&mut self.world, &mut rand::thread_rng(), sparseness);
    }

    /// Generate a new random rooms and corridors
    fn rooms(&mut self) {
        use world::mapgen;
        self.world = World::new(1);
        mapgen::rooms(&mut self.world, &mut rand::thread_rng());
    }

    command_parser!{
        fn cave(&mut self);
        fn maze(&mut self, sparseness: usize);
        fn rooms(&mut self);

        fn dump(&mut self);
    }

    fn draw_inventory(&mut self, c: &mut display::Backend, area: &Rect<f32>) {
        // Start with hardcoded invetory data to test the UI logic.
        c.fill_rect(
            FracRect::new(FracPoint2D::new(0.0, 0.0), FracSize2D::new(1.0, 1.0)),
            [0.0, 0.0, 0.0, 0.99],
        );

        let mut letter_pos = Point2D::new(0.0, 0.0);
        let mut slot_name_pos = Point2D::new(20.0, 0.0);
        let mut item_name_pos = Point2D::new(80.0, 0.0);
        let text_color = [1.0, 1.0, 1.0, 1.0];

        for slot in SLOT_DATA.iter() {
            // TODO: Bounding box for these is a button...
            letter_pos = c.draw_text(
                letter_pos,
                Align::Left,
                text_color,
                &format!("{})", slot.key),
            );
            slot_name_pos = c.draw_text(slot_name_pos, Align::Left, text_color, slot.name);
            item_name_pos = c.draw_text(item_name_pos, Align::Left, text_color, "[Inventory Item]");
        }
    }

    fn draw_console(&mut self, context: &mut display::Backend, screen_area: &Rect<f32>) {}

    pub fn draw(&mut self, context: &mut display::Backend, screen_area: &Rect<f32>) {
        let camera_loc = Location::new(0, 0, 0);
        let mut view = display::WorldView::new(camera_loc, *screen_area);
        view.show_cursor = true;

        view.draw(&self.world, context);

        match self.state {
            State::Inventory(_) => {
                self.draw_inventory(
                    context,
                    &Rect::new(Point2D::new(0.0, 0.0), Size2D::new(320.0, 360.0)),
                );
            }
            State::Console => {
                let mut console_area = *screen_area;
                console_area.size.height /= 2.0;
                self.console.draw_large(context, &console_area);
            }
            _ => {
                self.console.draw_small(context, screen_area);
            }
        }

        if let Some(scancode) = context.poll_key().and_then(|k| Scancode::new(k.scancode)) {
            let _ = match self.state {
                State::Inventory(_) => self.inventory_input(scancode),
                State::Console => self.console_input(scancode),
                _ => self.game_input(scancode),
            };
        }
    }
}

/// Print the world map as ASCII.
fn dump_map(world: &World) {
    for y in -21..21 {
        for x in -39..41 {
            if (x + y) % 2 != 0 {
                print!(" ");
                continue;
            }
            let pos = vec2((x + y) / 2, y);
            if on_screen(pos) {
                let t = world.terrain(Location::new(0, 0, 0) + pos);
                if t.is_open() {
                    print!(".");
                } else if t.is_door() {
                    print!("+");
                } else if t.is_wall() {
                    print!("#");
                } else {
                    print!("*");
                }
            } else {
                print!(" ");
            }
        }
        println!("");
    }
}

struct SlotData {
    key: char,
    code: Scancode,
    slot: Slot,
    name: &'static str,
}

#[cfg_attr(rustfmt, rustfmt_skip)]
static SLOT_DATA: [SlotData; 34] = [
    SlotData { key: '1', code: Scancode::Num1, slot: Slot::Spell1,     name: "Ability" },
    SlotData { key: '2', code: Scancode::Num2, slot: Slot::Spell2,     name: "Ability" },
    SlotData { key: '3', code: Scancode::Num3, slot: Slot::Spell3,     name: "Ability" },
    SlotData { key: '4', code: Scancode::Num4, slot: Slot::Spell4,     name: "Ability" },
    SlotData { key: '5', code: Scancode::Num5, slot: Slot::Spell5,     name: "Ability" },
    SlotData { key: '6', code: Scancode::Num6, slot: Slot::Spell6,     name: "Ability" },
    SlotData { key: '7', code: Scancode::Num7, slot: Slot::Spell7,     name: "Ability" },
    SlotData { key: '8', code: Scancode::Num8, slot: Slot::Spell8,     name: "Ability" },
    SlotData { key: 'a', code: Scancode::A,    slot: Slot::Melee,      name: "Weapon" },
    SlotData { key: 'b', code: Scancode::B,    slot: Slot::Ranged,     name: "Ranged" },
    SlotData { key: 'c', code: Scancode::C,    slot: Slot::Head,       name: "Head" },
    SlotData { key: 'd', code: Scancode::D,    slot: Slot::Body,       name: "Body" },
    SlotData { key: 'e', code: Scancode::E,    slot: Slot::Feet,       name: "Feet" },
    SlotData { key: 'f', code: Scancode::F,    slot: Slot::TrinketF,   name: "Trinket" },
    SlotData { key: 'g', code: Scancode::G,    slot: Slot::TrinketG,   name: "Trinket" },
    SlotData { key: 'h', code: Scancode::H,    slot: Slot::TrinketH,   name: "Trinket" },
    SlotData { key: 'i', code: Scancode::I,    slot: Slot::TrinketI,   name: "Trinket" },
    SlotData { key: 'j', code: Scancode::J,    slot: Slot::InventoryJ, name: "" },
    SlotData { key: 'k', code: Scancode::K,    slot: Slot::InventoryK, name: "" },
    SlotData { key: 'l', code: Scancode::L,    slot: Slot::InventoryL, name: "" },
    SlotData { key: 'm', code: Scancode::M,    slot: Slot::InventoryM, name: "" },
    SlotData { key: 'n', code: Scancode::N,    slot: Slot::InventoryN, name: "" },
    SlotData { key: 'o', code: Scancode::O,    slot: Slot::InventoryO, name: "" },
    SlotData { key: 'p', code: Scancode::P,    slot: Slot::InventoryP, name: "" },
    SlotData { key: 'q', code: Scancode::Q,    slot: Slot::InventoryQ, name: "" },
    SlotData { key: 'r', code: Scancode::R,    slot: Slot::InventoryR, name: "" },
    SlotData { key: 's', code: Scancode::S,    slot: Slot::InventoryS, name: "" },
    SlotData { key: 't', code: Scancode::T,    slot: Slot::InventoryT, name: "" },
    SlotData { key: 'u', code: Scancode::U,    slot: Slot::InventoryU, name: "" },
    SlotData { key: 'v', code: Scancode::V,    slot: Slot::InventoryV, name: "" },
    SlotData { key: 'w', code: Scancode::W,    slot: Slot::InventoryW, name: "" },
    SlotData { key: 'x', code: Scancode::X,    slot: Slot::InventoryX, name: "" },
    SlotData { key: 'y', code: Scancode::Y,    slot: Slot::InventoryY, name: "" },
    SlotData { key: 'z', code: Scancode::Z,    slot: Slot::InventoryZ, name: "" },
];
<|endoftext|>


<commit_before>use socket::Socket;

pub struct Generator {
    socket: Socket,
    started: bool,
    form: String,
    amplitude: f32,
    frequency: u32,
    dcyc: u32,
}

impl Generator {
    pub fn new(socket: Socket) -> Self {
        Generator {
            socket: socket,
            started: false,
            form: "SYN".into(),
            amplitude: 1.0,
            frequency: 1000,
            dcyc: 50,
        }
    }

    pub fn start(&mut self) {
        self.socket.send("OUTPUT1:STATE ON");
        self.started = true;
    }

    pub fn stop(&mut self) {
        self.socket.send("OUTPUT1:STATE OFF");
        self.started = false;
    }

    pub fn is_started(&self) -> bool {
        self.started
    }

    pub fn set_form<S>(&mut self, form: S) where S: Into<String> {
        self.form = form.into();
        self.socket.send(format!("SOUR1:FUNC {}", self.form))
    }

    pub fn get_form(&self) -> String {
        self.form.clone()
    }

    pub fn set_amplitude(&mut self, amplitude: f32) {
        self.socket.send(format!("SOUR1:VOLT {}", amplitude));
        self.amplitude = amplitude;
    }

    pub fn get_amplitude(&self) -> f32 {
        self.amplitude
    }

    pub fn set_frequency(&mut self, frequency: u32) {
        self.socket.send(format!("SOUR1:FREQ:FIX {}", frequency));
        self.frequency = frequency;
    }

    pub fn get_frequency(&self) -> u32 {
        self.frequency
    }

    pub fn set_dcyc(&mut self, dcyc: u32) {
        self.socket.send(format!("SOUR1:DCYC {}", dcyc));
        self.dcyc = dcyc;
    }

    pub fn get_dcyc(&self) -> u32 {
        self.dcyc
    }
}

#[cfg(test)]
mod test {
    macro_rules! generator_assert {
        ($f:ident, $e:expr) => {
            let (rx, mut generator) = create_generator();

            generator.$f();
            assert_eq!($e, rx.recv().unwrap());
        }
    }

    fn create_generator() -> (::std::sync::mpsc::Receiver<String>, ::generator::Generator) {
        let (addr, rx) = ::test::launch_server();
        let socket = ::socket::Socket::new(
            format!("{}", addr.ip()).as_str(),
            addr.port()
        );

        (rx, ::generator::Generator::new(socket))
    }

    #[test]
    fn test_start() {
        generator_assert!(start, "OUTPUT1:STATE ON\r\n");
    }

    #[test]
    fn test_stop() {
        generator_assert!(stop, "OUTPUT1:STATE OFF\r\n");
    }

    #[test]
    fn test_is_started() {
        let (_, mut generator) = create_generator();

        assert_eq!(generator.is_started(), false);
        generator.start();
        assert_eq!(generator.is_started(), true);
        generator.stop();
        assert_eq!(generator.is_started(), false);
    }

    #[test]
    fn test_form() {
        let (rx, mut generator) = create_generator();

        generator.set_form("SINE");
        assert_eq!("SOUR1:FUNC SINE\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_amplitude() {
        let (rx, mut generator) = create_generator();

        generator.set_amplitude(-0.9);
        assert_eq!("SOUR1:VOLT -0.9\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_set_frequency() {
        let (rx, mut generator) = create_generator();

        generator.set_frequency(500);
        assert_eq!("SOUR1:FREQ:FIX 500\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_get_frequency() {
        let (_, generator) = create_generator();

        assert_eq!(generator.get_frequency(), 1000);
    }

    #[test]
    fn test_dcyc() {
        let (rx, mut generator) = create_generator();

        generator.set_dcyc(100);
        assert_eq!("SOUR1:DCYC 100\r\n", rx.recv().unwrap());
    }
}
<commit_msg>[generator] Add all commands<commit_after>use socket::Socket;

pub struct Generator {
    socket: Socket,
    started: bool,
    form: String,
    amplitude: f32,
    frequency: u32,
    dcyc: u32,
}

impl Generator {
    pub fn new(socket: Socket) -> Self {
        Generator {
            socket: socket,
            started: false,
            form: "SYN".into(),
            amplitude: 1.0,
            frequency: 1000,
            dcyc: 50,
        }
    }

    pub fn start(&mut self) {
        self.socket.send("OUTPUT1:STATE ON");
        self.started = true;
    }

    pub fn stop(&mut self) {
        self.socket.send("OUTPUT1:STATE OFF");
        self.started = false;
    }

    pub fn is_started(&self) -> bool {
        self.started
    }

    pub fn set_form<S>(&mut self, form: S) where S: Into<String> {
        self.form = form.into();
        self.socket.send(format!("SOUR1:FUNC {}", self.form))
    }

    pub fn get_form(&self) -> String {
        self.form.clone()
    }

    pub fn set_amplitude(&mut self, amplitude: f32) {
        self.socket.send(format!("SOUR1:VOLT {}", amplitude));
        self.amplitude = amplitude;
    }

    pub fn get_amplitude(&self) -> f32 {
        self.amplitude
    }

    pub fn set_offset(&mut self, offset: f32) {
        self.socket.send(format!("SOUR1:VOLT:OFFS {}", offset));
    }

    pub fn set_phase(&mut self, phase: i32) {
        self.socket.send(format!("SOUR1:PHAS {}", phase));
    }

    pub fn set_dcyc(&mut self, dcyc: u32) {
        self.socket.send(format!("SOUR1:DCYC {}", dcyc));
        self.dcyc = dcyc;
    }

    pub fn get_dcyc(&self) -> u32 {
        self.dcyc
    }

    pub fn arbitrary_waveform(&mut self, data: Vec<f32>) {
        let mut data = data.iter()
            .fold(String::new(), |acc, e| {
                format!("{}{},", acc, e)
            });
        data.pop();

        self.socket.send(format!("SOUR1:TRAC:DATA:DATA {}", data));
    }

    pub fn set_frequency(&mut self, frequency: u32) {
        self.socket.send(format!("SOUR1:FREQ:FIX {}", frequency));
        self.frequency = frequency;
    }

    pub fn get_frequency(&self) -> u32 {
        self.frequency
    }

    pub fn set_trigger_source(&mut self, source: &str) {
        self.socket.send(format!("SOUR1:TRIG:SOUR {}", source));
    }

    pub fn trigger(&mut self) {
        self.socket.send("SOUR1:TRIG:IMM");
    }

    pub fn trigger_all(&mut self) {
        self.socket.send("TRIG:IMM");
    }

    pub fn reset(&mut self) {
        self.socket.send("GEN:RST");
    }
}

#[cfg(test)]
mod test {
    macro_rules! generator_assert {
        ($f:ident, $e:expr) => {
            let (rx, mut generator) = create_generator();

            generator.$f();
            assert_eq!($e, rx.recv().unwrap());
        }
    }

    #[test]
    fn test_start() {
        generator_assert!(start, "OUTPUT1:STATE ON\r\n");
    }

    #[test]
    fn test_stop() {
        generator_assert!(stop, "OUTPUT1:STATE OFF\r\n");
    }

    #[test]
    fn test_is_started() {
        let (_, mut generator) = create_generator();

        assert_eq!(generator.is_started(), false);
        generator.start();
        assert_eq!(generator.is_started(), true);
        generator.stop();
        assert_eq!(generator.is_started(), false);
    }

    #[test]
    fn test_form() {
        let (rx, mut generator) = create_generator();

        generator.set_form("SINE");
        assert_eq!("SOUR1:FUNC SINE\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_amplitude() {
        let (rx, mut generator) = create_generator();

        generator.set_amplitude(-0.9);
        assert_eq!("SOUR1:VOLT -0.9\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_set_offset() {
        let (rx, mut generator) = create_generator();

        generator.set_offset(-1.0);
        assert_eq!("SOUR1:VOLT:OFFS -1\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_set_phase() {
        let (rx, mut generator) = create_generator();

        generator.set_phase(-360);
        assert_eq!("SOUR1:PHAS -360\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_dcyc() {
        let (rx, mut generator) = create_generator();

        generator.set_dcyc(100);
        assert_eq!("SOUR1:DCYC 100\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_arbitrary_waveform() {
        let (rx, mut generator) = create_generator();

        generator.arbitrary_waveform(vec![1.0, 0.5, 0.2]);
        assert_eq!("SOUR1:TRAC:DATA:DATA 1,0.5,0.2\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_set_frequency() {
        let (rx, mut generator) = create_generator();

        generator.set_frequency(500);
        assert_eq!("SOUR1:FREQ:FIX 500\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_get_frequency() {
        let (_, generator) = create_generator();

        assert_eq!(generator.get_frequency(), 1000);
    }

    #[test]
    fn test_set_trigger_source() {
        let (rx, mut generator) = create_generator();

        generator.set_trigger_source("EXT");
        assert_eq!("SOUR1:TRIG:SOUR EXT\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_trigger() {
        generator_assert!(trigger, "SOUR1:TRIG:IMM\r\n");
    }

    #[test]
    fn test_trigger_all() {
        generator_assert!(trigger_all, "TRIG:IMM\r\n");
    }

    #[test]
    fn test_reset() {
        generator_assert!(reset, "GEN:RST\r\n");
    }

    fn create_generator() -> (::std::sync::mpsc::Receiver<String>, ::generator::Generator) {
        let (addr, rx) = ::test::launch_server();
        let socket = ::socket::Socket::new(
            format!("{}", addr.ip()).as_str(),
            addr.port()
        );

        (rx, ::generator::Generator::new(socket))
    }
}
<|endoftext|>


<commit_before>use syntax::abi;
use syntax::ast;
use syntax::ast_util;
use syntax::codemap::DUMMY_SP;
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::ptr::P;
use syntax::parse::token;

use block::{Block, Describe, It, Bench};

pub trait Generate {
    fn generate(self, cx: &mut ExtCtxt, up: Option<&Describe>) -> P<ast::Item>;
}

impl Generate for Block {
    fn generate(self, cx: &mut ExtCtxt, up: Option<&Describe>) -> P<ast::Item> {
        match self {
            Block::Describe(describe) => describe.generate(cx, up),
            Block::It(it) => it.generate(cx, up),
            Block::Bench(bench) => bench.generate(cx, up)
        }
    }
}

impl Generate for Describe {
    fn generate(mut self,
                cx: &mut ExtCtxt,
                up: Option<&Describe>) -> P<ast::Item> {
        let name = cx.ident_of(&*self.name);

        if let Some(ref up) = up {
            if let Some(ref before) = up.before {
                self.before = match self.before {
                    Some(ref now) => Some(merge_blocks(before, now)),
                    None => Some(before.clone())
                }
            }

            if let Some(ref after) = up.after {
                self.after = match self.after {
                    Some(ref now) => Some(merge_blocks(now, after)),
                    None => Some(after.clone())
                }
            }
        }

        let mut items = self.blocks.iter().map(|block| {
            block.clone().generate(cx, Some(&self))
        }).collect::<Vec<_>>();

        let pub_use_super_star = cx.item_use_glob(DUMMY_SP,
                                                  ast::Visibility::Public,
                                                  vec![cx.ident_of("super")]);

        items.push(pub_use_super_star);

        cx.item_mod(DUMMY_SP,
                    DUMMY_SP,
                    name,
                    vec![],
                    items)
    }
}

impl Generate for It {
    fn generate(self, cx: &mut ExtCtxt, up: Option<&Describe>) -> P<ast::Item> {
        let name = cx.ident_of(&*self.name);
        let attrs = vec![
            cx.attribute(
                DUMMY_SP,
                cx.meta_word(DUMMY_SP, token::InternedString::new("test"))
            )
        ];

        let block = if let Some(ref up) = up {
            match (&up.before, &up.after) {
                (&Some(ref before), &Some(ref after)) => {
                    merge_blocks(&merge_blocks(before, &self.block), after)
                },
                (&Some(ref before), &None) => merge_blocks(before, &self.block),
                (&None, &Some(ref after)) => merge_blocks(&self.block, after),
                (&None, &None) => self.block.clone()
            }
        } else {
            self.block
        };

        cx.item(DUMMY_SP, name, attrs,
                ast::ItemFn(
                    P(ast::FnDecl {
                        inputs: vec![],
                        output: ast::DefaultReturn(DUMMY_SP),
                        variadic: false
                    }),
                    ast::Unsafety::Normal,
                    abi::Rust,
                    ast_util::empty_generics(),
                    block
                ))
    }
}

impl Generate for Bench {
    fn generate(self, cx: &mut ExtCtxt, up: Option<&Describe>) -> P<ast::Item> {
        let name = cx.ident_of(&*self.name);

        let attrs = vec![
            cx.attribute(
                DUMMY_SP,
                cx.meta_word(DUMMY_SP, token::InternedString::new("bench"))
            )
        ];

        let args = vec![
            cx.arg(DUMMY_SP, self.ident, quote_ty!(cx, &mut ::test::Bencher))
        ];

        let block = if let Some(ref up) = up {
            match (&up.before, &up.after) {
                (&Some(ref before), &Some(ref after)) => {
                    merge_blocks(&merge_blocks(before, &self.block), after)
                },
                (&Some(ref before), &None) => merge_blocks(before, &self.block),
                (&None, &Some(ref after)) => merge_blocks(&self.block, after),
                (&None, &None) => self.block.clone()
            }
        } else {
            self.block
        };

        cx.item(DUMMY_SP, name, attrs,
                ast::ItemFn(
                    P(ast::FnDecl {
                        inputs: args,
                        output: ast::DefaultReturn(DUMMY_SP),
                        variadic: false
                    }),
                    ast::Unsafety::Normal,
                    abi::Rust,
                    ast_util::empty_generics(),
                    block
                ))
    }
}

fn merge_blocks(left: &P<ast::Block>, right: &P<ast::Block>) -> P<ast::Block> {
    use std::ops::Deref;

    let mut stmts = left.stmts.clone();
    stmts.push_all(&right.stmts);

    P(ast::Block {
        stmts: stmts,
        ..left.deref().clone()
    })
}
<commit_msg>Fix for `rustc 1.2.0-nightly (9cb7b3ffb 2015-06-01) (built 2015-05-31)`.<commit_after>use syntax::abi;
use syntax::ast;
use syntax::ast_util;
use syntax::codemap::DUMMY_SP;
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::ptr::P;
use syntax::parse::token;

use block::{Block, Describe, It, Bench};

pub trait Generate {
    fn generate(self, cx: &mut ExtCtxt, up: Option<&Describe>) -> P<ast::Item>;
}

impl Generate for Block {
    fn generate(self, cx: &mut ExtCtxt, up: Option<&Describe>) -> P<ast::Item> {
        match self {
            Block::Describe(describe) => describe.generate(cx, up),
            Block::It(it) => it.generate(cx, up),
            Block::Bench(bench) => bench.generate(cx, up)
        }
    }
}

impl Generate for Describe {
    fn generate(mut self,
                cx: &mut ExtCtxt,
                up: Option<&Describe>) -> P<ast::Item> {
        let name = cx.ident_of(&*self.name);

        if let Some(ref up) = up {
            if let Some(ref before) = up.before {
                self.before = match self.before {
                    Some(ref now) => Some(merge_blocks(before, now)),
                    None => Some(before.clone())
                }
            }

            if let Some(ref after) = up.after {
                self.after = match self.after {
                    Some(ref now) => Some(merge_blocks(now, after)),
                    None => Some(after.clone())
                }
            }
        }

        let mut items = self.blocks.iter().map(|block| {
            block.clone().generate(cx, Some(&self))
        }).collect::<Vec<_>>();

        let pub_use_super_star = cx.item_use_glob(DUMMY_SP,
                                                  ast::Visibility::Public,
                                                  vec![cx.ident_of("super")]);

        items.push(pub_use_super_star);

        cx.item_mod(DUMMY_SP,
                    DUMMY_SP,
                    name,
                    vec![],
                    items)
    }
}

impl Generate for It {
    fn generate(self, cx: &mut ExtCtxt, up: Option<&Describe>) -> P<ast::Item> {
        let name = cx.ident_of(&*self.name);
        let attrs = vec![
            cx.attribute(
                DUMMY_SP,
                cx.meta_word(DUMMY_SP, token::InternedString::new("test"))
            )
        ];

        let block = if let Some(ref up) = up {
            match (&up.before, &up.after) {
                (&Some(ref before), &Some(ref after)) => {
                    merge_blocks(&merge_blocks(before, &self.block), after)
                },
                (&Some(ref before), &None) => merge_blocks(before, &self.block),
                (&None, &Some(ref after)) => merge_blocks(&self.block, after),
                (&None, &None) => self.block.clone()
            }
        } else {
            self.block
        };

        cx.item(DUMMY_SP, name, attrs,
                ast::ItemFn(
                    P(ast::FnDecl {
                        inputs: vec![],
                        output: ast::DefaultReturn(DUMMY_SP),
                        variadic: false
                    }),
                    ast::Unsafety::Normal,
                    ast::Constness::NotConst,
                    abi::Rust,
                    ast_util::empty_generics(),
                    block
                ))
    }
}

impl Generate for Bench {
    fn generate(self, cx: &mut ExtCtxt, up: Option<&Describe>) -> P<ast::Item> {
        let name = cx.ident_of(&*self.name);

        let attrs = vec![
            cx.attribute(
                DUMMY_SP,
                cx.meta_word(DUMMY_SP, token::InternedString::new("bench"))
            )
        ];

        let args = vec![
            cx.arg(DUMMY_SP, self.ident, quote_ty!(cx, &mut ::test::Bencher))
        ];

        let block = if let Some(ref up) = up {
            match (&up.before, &up.after) {
                (&Some(ref before), &Some(ref after)) => {
                    merge_blocks(&merge_blocks(before, &self.block), after)
                },
                (&Some(ref before), &None) => merge_blocks(before, &self.block),
                (&None, &Some(ref after)) => merge_blocks(&self.block, after),
                (&None, &None) => self.block.clone()
            }
        } else {
            self.block
        };

        cx.item(DUMMY_SP, name, attrs,
                ast::ItemFn(
                    P(ast::FnDecl {
                        inputs: args,
                        output: ast::DefaultReturn(DUMMY_SP),
                        variadic: false
                    }),
                    ast::Unsafety::Normal,
                    ast::Constness::NotConst,
                    abi::Rust,
                    ast_util::empty_generics(),
                    block
                ))
    }
}

fn merge_blocks(left: &P<ast::Block>, right: &P<ast::Block>) -> P<ast::Block> {
    use std::ops::Deref;

    let mut stmts = left.stmts.clone();
    stmts.push_all(&right.stmts);

    P(ast::Block {
        stmts: stmts,
        ..left.deref().clone()
    })
}
<|endoftext|>