<commit_before>//! # Flash drivers for the LM4F120H5QR
//!
//! The LM4F120 has a flash memory controller which supports:
//!
//! * 1 KiB page erase
//! * 32-bit word write
//! * 32 word (128 byte) block write

// ****************************************************************************
//
// Imports
//
// ****************************************************************************

use cortex_m::asm::nop;
use tm4c123x;

// ****************************************************************************
//
// Public Types
//
// ****************************************************************************

/// Represents an address in Flash memory. As flash memory starts at
/// 0x0000_0000, flash addresses are equal to CPU physical addresses.
pub struct FlashAddress(u32);

pub enum Error {
    /// Given address did not have the alignment
    /// specified here (as a u32).
    BadAlignment(u32),
    /// Buffer given was too long, it should be the length given.
    BufferTooLong(usize),
    /// Buffer given was too short, it should be the length given.
    BufferTooShort(usize),
}

// ****************************************************************************
//
// Public Data
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Private Types
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Private Data
//
// ****************************************************************************

// const PAGE_LENGTH: usize = 128;
const FLASH_KEY: u16 = 0x71D5;
// const FLASH_KEY: u16 = 0xA442;

// ****************************************************************************
//
// Public Functions
//
// ****************************************************************************

/// Erase a 1 KiB page of flash. The given address must be on 1 KiB boundary
/// (i.e. a multiple of 1024).
pub fn erase_page(address: FlashAddress) -> Result<(), Error> {
    if (address.0 & 1023) != 0 {
        return Err(Error::BadAlignment(1024))
    }

    unsafe {
        let reg = get_registers();
        // Write the page address to the FMA register
        reg.fma.write(|w| w.offset().bits(address.0));
        // Write the flash memory key and the erase bit
        reg.fmc.modify(|_, w| w.erase().bit(true).wrkey().bits(FLASH_KEY));
        // Poll the FMC register until the ERASE bit is cleared
        while reg.fmc.read().erase().bit() {
            nop();
        }
    }

    Ok(())
}

/// Write a 32-bit value to flash at the given address. The address
/// must be on a 4-byte boundary (i.e. a multiple of 4).
pub fn write_word(address: FlashAddress, word: u32) -> Result<(), Error> {
    if (address.0 & 3) != 0 {
        return Err(Error::BadAlignment(4))
    }

    unsafe {
        let reg = get_registers();
        // Write the data to the FMD register
        reg.fmd.write(|w| w.data().bits(word));
        // Write the target address to the FMA register
        reg.fma.write(|w| w.offset().bits(address.0));
        // Write the flash memory key and the write bit
        reg.fmc.modify(|_, w| w.write().bit(true).wrkey().bits(FLASH_KEY));
        // Poll the FMC register until the WRITE bit is cleared
        while reg.fmc.read().write().bit() {
            nop();
        }
    }

    Ok(())

}

/// Write a 128 byte buffer to flash at the given address. The address
/// must be on a 128-byte boundary (i.e. a multiple of 128) and the
/// buffer must have a length equal to 128. Pad with 0xFF if
/// your data is short.
// pub fn write_page(address: FlashAddress, data: &[u8]) -> Result<(), Error> {
//     if (address.0 & 127) != 0 {
//         return Err(Error::BadAlignment(128));
//     } else if data.len() < PAGE_LENGTH {
//         return Err(Error::BufferTooShort(PAGE_LENGTH));
//     } else if data.len() > PAGE_LENGTH {
//         return Err(Error::BufferTooLong(PAGE_LENGTH));
//     }

//     unsafe {
//         let reg = get_registers();
//         // Write the data to the FMBx registers
//         // I'm not sure the tmc4c123x crate has these correct, as it only
//         // exposes a single fmbn, not 32 fmbx registers.
//         reg.fmd.write(|w| w.data().bits(word));
//         // Write the target address to the FMA register
//         reg.fma.write(|w| w.offset().bits(address.0));
//         // Write the flash memory key and the write bit
//         reg.fmc.modify(|_, w| w.write().bit(true).wrkey().bits(FLASH_KEY));
//         // Poll the FMC register until the WRITE bit is cleared
//         while reg.fmc.read().write().bit() {
//             nop();
//         }
//     }

//     Ok(())

// }

// ****************************************************************************
//
// Private Functions
//
// ****************************************************************************

/// Get a reference to the UART control register struct in the chip.
unsafe fn get_registers() -> &'static tm4c123x::flash_ctrl::RegisterBlock {
    &*tm4c123x::FLASH_CTRL.get()
}

// ****************************************************************************
//
// End Of File
//
// ****************************************************************************
<commit_msg>Flash driver returns errors from hw. (Doesn't seem to actually work though)<commit_after>//! # Flash drivers for the LM4F120H5QR
//!
//! The LM4F120 has a flash memory controller which supports:
//!
//! * 1 KiB page erase
//! * 32-bit word write
//! * 32 word (128 byte) block write

// ****************************************************************************
//
// Imports
//
// ****************************************************************************

use cortex_m::asm::nop;
use tm4c123x;

// ****************************************************************************
//
// Public Types
//
// ****************************************************************************

/// Represents an address in Flash memory. As flash memory starts at
/// 0x0000_0000, flash addresses are equal to CPU physical addresses.
pub struct FlashAddress(pub u32);

#[derive(Debug)]
pub enum Error {
    /// A hardware error occured. The value is the
    /// contents of the FCRIS register.
    HardwareError(u32),
    /// Given address did not have the alignment
    /// specified here (as a u32).
    BadAlignment(u32),
    /// Buffer given was too long, it should be the length given.
    BufferTooLong(usize),
    /// Buffer given was too short, it should be the length given.
    BufferTooShort(usize),
}

// ****************************************************************************
//
// Public Data
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Private Types
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Private Data
//
// ****************************************************************************

// const PAGE_LENGTH: usize = 128;
// const FLASH_KEY: u16 = 0x71D5;
const FLASH_KEY: u16 = 0xA442;

// ****************************************************************************
//
// Public Functions
//
// ****************************************************************************

/// Erase a 1 KiB page of flash. The given address must be on 1 KiB boundary
/// (i.e. a multiple of 1024).
pub fn erase_page(address: FlashAddress) -> Result<(), Error> {
    if (address.0 & 1023) != 0 {
        return Err(Error::BadAlignment(1024));
    }

    unsafe {
        let reg = get_registers();
        clear_bits(reg);
        // Write the page address to the FMA register
        reg.fma.write(|w| w.offset().bits(address.0));
        // Write the flash memory key and the erase bit
        reg.fmc.modify(
            |_, w| w.erase().bit(true).wrkey().bits(FLASH_KEY),
        );
        // Poll the FMC register until the ERASE bit is cleared
        while reg.fmc.read().erase().bit() {
            nop();
        }
        get_status(reg)
    }
}

/// Write a 32-bit value to flash at the given address. The address
/// must be on a 4-byte boundary (i.e. a multiple of 4).
pub fn write_word(address: FlashAddress, word: u32) -> Result<(), Error> {
    if (address.0 & 3) != 0 {
        return Err(Error::BadAlignment(4));
    }

    unsafe {
        let reg = get_registers();
        clear_bits(reg);
        // Write the target address to the FMA register
        reg.fma.write(|w| w.offset().bits(address.0));
        // Write the data to the FMD register
        reg.fmd.write(|w| w.data().bits(word));
        // Write the flash memory key and the write bit
        reg.fmc.modify(
            |_, w| w.write().bit(true).wrkey().bits(FLASH_KEY),
        );
        // Poll the FMC register until the WRITE bit is cleared
        while reg.fmc.read().write().bit() {
            nop();
        }
        get_status(reg)
    }
}

/// Write a 128 byte buffer to flash at the given address. The address
/// must be on a 128-byte boundary (i.e. a multiple of 128) and the
/// buffer must have a length equal to 128. Pad with 0xFF if
/// your data is short.
// pub fn write_page(address: FlashAddress, data: &[u8]) -> Result<(), Error> {
//     if (address.0 & 127) != 0 {
//         return Err(Error::BadAlignment(128));
//     } else if data.len() < PAGE_LENGTH {
//         return Err(Error::BufferTooShort(PAGE_LENGTH));
//     } else if data.len() > PAGE_LENGTH {
//         return Err(Error::BufferTooLong(PAGE_LENGTH));
//     }

//     unsafe {
//         let reg = get_registers();
//         // Write the data to the FMBx registers
//         // I'm not sure the tmc4c123x crate has these correct, as it only
//         // exposes a single fmbn, not 32 fmbx registers.
//         reg.fmd.write(|w| w.data().bits(word));
//         // Write the target address to the FMA register
//         reg.fma.write(|w| w.offset().bits(address.0));
//         // Write the flash memory key and the write bit
//         reg.fmc.modify(|_, w| w.write().bit(true).wrkey().bits(FLASH_KEY));
//         // Poll the FMC register until the WRITE bit is cleared
//         while reg.fmc.read().write().bit() {
//             nop();
//         }
//     }

//     Ok(())

// }

// ****************************************************************************
//
// Private Functions
//
// ****************************************************************************
/// Get a reference to the UART control register struct in the chip.
unsafe fn get_registers() -> &'static tm4c123x::flash_ctrl::RegisterBlock {
    &*tm4c123x::FLASH_CTRL.get()
}

/// Clear all the status bits
fn clear_bits(reg: &'static tm4c123x::flash_ctrl::RegisterBlock) {
    reg.fcmisc.write(|w| {
        w.amisc()
            .bit(true)
            .voltmisc()
            .bit(true)
            .invdmisc()
            .bit(true)
            .progmisc()
            .bit(true)
            .ermisc()
            .bit(true)
    });
}

/// Get pass/fail from the controller
fn get_status(reg: &'static tm4c123x::flash_ctrl::RegisterBlock) -> Result<(), Error> {
    let fcris = reg.fcris.read();
    if fcris.aris().bit() || fcris.voltris().bit() || fcris.invdris().bit() ||
        fcris.progris().bit() || fcris.erris().bit()
    {
        Err(Error::HardwareError(fcris.bits()))
    } else {
        Ok(())
    }
}

// ****************************************************************************
//
// End Of File
//
// ****************************************************************************
<|endoftext|>


<commit_before>//! This module provides the Gf256 type which is used to represent
//! elements of a finite field wich 256 elements.
//! Originally from https://github.com/sellibitze/secretshare/blob/master/src/gf256.rs

use std::num::Wrapping;
use std::ops::{ Add, Sub, Mul, Div };
use std::sync::{ Once, ONCE_INIT };

const POLY: u8 = 0x1D; // represents x^8 + x^4 + x^3 + x^2 + 1

/// replicates the least significant bit to every other bit
#[inline]
fn mask(bit: u8) -> u8 {
    (Wrapping(0u8) - Wrapping(bit & 1)).0
}

/// multiplies a polynomial with x and returns the residual
/// of the polynomial division with POLY as divisor
#[inline]
fn xtimes(poly: u8) -> u8 {
  (poly << 1) ^ (mask(poly >> 7) & POLY)
}

/// Tables used for multiplication and division
struct Tables {
  exp: [u8; 256],
  log: [u8; 256],
  inv: [u8; 256]
}

static INIT: Once = ONCE_INIT;
static mut TABLES: Tables = Tables {
  exp: [0; 256],
  log: [0; 256],
  inv: [0; 256]
};

fn get_tables() -> &'static Tables {
  INIT.call_once(|| {
    // mutable access is fine because of synchronization via INIT
    let tabs = unsafe { &mut TABLES };
    let mut tmp = 1;
    for power in 0..255usize {
      tabs.exp[power] = tmp;
      tabs.log[tmp as usize] = power as u8;
      tmp = xtimes(tmp);
    }
    tabs.exp[255] = 1;
    for x in 1..256usize {
      let l = tabs.log[x];
      let nl = if l==0 { 0 } else { 255 - l };
      let i = tabs.exp[nl as usize];
      tabs.inv[x] = i;
    }
  });
  // We're guaranteed to have TABLES initialized by now
  return unsafe { &TABLES };
}

/// Type for elements of a finite field with 256 elements
#[derive(Copy,Clone,PartialEq,Eq)]
pub struct Gf256 {
  pub poly: u8
}

impl Gf256 {
  /// returns the additive neutral element of the field
  #[inline]
  pub fn zero() -> Gf256 {
    Gf256 { poly: 0 }
  }
  /// returns the multiplicative neutral element of the field
  #[inline]
  pub fn one() -> Gf256 {
    Gf256 { poly: 1 }
  }
  #[inline]
  pub fn from_byte(b: u8) -> Gf256 {
    Gf256 { poly: b }
  }
  #[inline]
  pub fn to_byte(&self) -> u8 {
    self.poly
  }
  pub fn log(&self) -> Option<u8> {
    if self.poly == 0 {
      None
    } else {
      let tabs = get_tables();
      Some(tabs.log[self.poly as usize])
    }
  }
  pub fn exp(power: u8) -> Gf256 {
    let tabs = get_tables();
    Gf256 { poly: tabs.exp[power as usize] }
  }
/*
  pub fn inv(&self) -> Option<Gf256> {
    self.log().map(|l| Gf256::exp(255 - l))
  }
*/
}

impl Add<Gf256> for Gf256 {
  type Output = Gf256;
  #[inline]
  fn add(self, rhs: Gf256) -> Gf256 {
    Gf256::from_byte(self.poly ^ rhs.poly)
  }
}

impl Sub<Gf256> for Gf256 {
  type Output = Gf256;
  #[inline]
  fn sub(self, rhs: Gf256) -> Gf256 {
    Gf256::from_byte(self.poly ^ rhs.poly)
  }
}

impl Mul<Gf256> for Gf256 {
  type Output = Gf256;
  fn mul(self, rhs: Gf256) -> Gf256 {
    if let (Some(l1), Some(l2)) = (self.log(), rhs.log()) {
      let tmp = ((l1 as u16) + (l2 as u16)) % 255;
      Gf256::exp(tmp as u8)
    } else {
      Gf256 { poly: 0 }
    }
  }
}

impl Div<Gf256> for Gf256 {
  type Output = Gf256;
  fn div(self, rhs: Gf256) -> Gf256 {
    let l2 = rhs.log().expect("division by zero");
    if let Some(l1) = self.log() {
      let tmp = ((l1 as u16) + 255 - (l2 as u16)) % 255;
      Gf256::exp(tmp as u8)
    } else {
      Gf256 { poly: 0 }
    }
  }
}
<commit_msg>did not end up migrating that version<commit_after><|endoftext|>


<commit_before>//! Compiler plugin defining macros that create PHF data structures.
//!
//! # Example
//!
//! ```rust
//! #![feature(plugin, core)]
//! #![plugin(phf_macros)]
//!
//! extern crate phf;
//!
//! #[derive(Clone)]
//! pub enum Keyword {
//!     Loop,
//!     Continue,
//!     Break,
//!     Fn,
//!     Extern,
//! }
//!
//! static KEYWORDS: phf::Map<&'static str, Keyword> = phf_map! {
//!     "loop" => Keyword::Loop,
//!     "continue" => Keyword::Continue,
//!     "break" => Keyword::Break,
//!     "fn" => Keyword::Fn,
//!     "extern" => Keyword::Extern,
//! };
//!
//! pub fn parse_keyword(keyword: &str) -> Option<Keyword> {
//!     KEYWORDS.get(keyword).cloned()
//! }
//! # fn main() {}
//! ```
#![doc(html_root_url="http://sfackler.github.io/rust-phf/doc/v0.7.8")]
#![feature(plugin_registrar, quote, rustc_private)]

extern crate syntax;
#[cfg(feature = "stats")]
extern crate time;
extern crate rustc;
extern crate phf_shared;
extern crate phf_generator;

use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use syntax::ast::{self, TokenTree, LitStr, LitByteStr, LitByte, LitChar, Expr, ExprLit, ExprVec};
use syntax::codemap::{Span, Spanned};
use syntax::ext::base::{DummyResult, ExtCtxt, MacResult};
use syntax::fold::Folder;
use syntax::parse;
use syntax::parse::token::{InternedString, Comma, Eof, FatArrow};
use syntax::print::pprust;
use rustc::plugin::Registry;
use phf_generator::HashState;
use std::env;

use util::{Entry, Key};
use util::{create_map, create_set, create_ordered_map, create_ordered_set};

pub mod util;
mod macros;

#[plugin_registrar]
#[doc(hidden)]
pub fn macro_registrar(reg: &mut Registry) {
    reg.register_macro("phf_map", expand_phf_map);
    reg.register_macro("phf_set", expand_phf_set);
    reg.register_macro("phf_ordered_map", expand_phf_ordered_map);
    reg.register_macro("phf_ordered_set", expand_phf_ordered_set);
}

fn generate_hash(cx: &mut ExtCtxt, sp: Span, entries: &[Entry]) -> HashState {
    #[cfg(feature = "stats")]
    use time::precise_time_s;
    #[cfg(not(feature = "stats"))]
    fn precise_time_s() -> f64 {
        0.
    }

    let start = precise_time_s();
    let state = phf_generator::generate_hash(entries);
    let time = precise_time_s() - start;

    if cfg!(feature = "stats") && env::var_os("PHF_STATS").is_some() {
        cx.span_note(sp, &format!("PHF generation took {} seconds", time));
    }

    state
}

fn expand_phf_map(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult + 'static> {
    let entries = match parse_map(cx, tts) {
        Some(entries) => entries,
        None => return DummyResult::expr(sp),
    };

    if has_duplicates(cx, sp, &*entries) {
        return DummyResult::expr(sp);
    }

    let state = generate_hash(cx, sp, &*entries);

    create_map(cx, sp, entries, state)
}

fn expand_phf_set(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult + 'static> {
    let entries = match parse_set(cx, tts) {
        Some(entries) => entries,
        None => return DummyResult::expr(sp),
    };

    if has_duplicates(cx, sp, &*entries) {
        return DummyResult::expr(sp);
    }

    let state = generate_hash(cx, sp, &*entries);

    create_set(cx, sp, entries, state)
}

fn expand_phf_ordered_map(cx: &mut ExtCtxt,
                          sp: Span,
                          tts: &[TokenTree])
                          -> Box<MacResult + 'static> {
    let entries = match parse_map(cx, tts) {
        Some(entries) => entries,
        None => return DummyResult::expr(sp),
    };

    if has_duplicates(cx, sp, &*entries) {
        return DummyResult::expr(sp);
    }

    let state = generate_hash(cx, sp, &*entries);

    create_ordered_map(cx, sp, entries, state)
}

fn expand_phf_ordered_set(cx: &mut ExtCtxt,
                          sp: Span,
                          tts: &[TokenTree])
                          -> Box<MacResult + 'static> {
    let entries = match parse_set(cx, tts) {
        Some(entries) => entries,
        None => return DummyResult::expr(sp),
    };

    if has_duplicates(cx, sp, &*entries) {
        return DummyResult::expr(sp);
    }

    let state = generate_hash(cx, sp, &*entries);

    create_ordered_set(cx, sp, entries, state)
}

fn parse_map(cx: &mut ExtCtxt, tts: &[TokenTree]) -> Option<Vec<Entry>> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), tts.to_vec());
    let mut entries = Vec::new();

    let mut bad = false;
    while parser.token != Eof {
        let key = cx.expander().fold_expr(parser.parse_expr().unwrap());
        let key_contents = parse_key(cx, &*key).unwrap_or_else(|| {
            bad = true;
            Key::Str(InternedString::new(""))
        });

        if !parser.eat(&FatArrow).ok().unwrap() {
            cx.span_err(parser.span, "expected `=>`");
            return None;
        }

        let value = parser.parse_expr().unwrap();

        entries.push(Entry {
            key_contents: key_contents,
            key: key,
            value: value,
        });

        if !parser.eat(&Comma).ok().unwrap() && parser.token != Eof {
            cx.span_err(parser.span, "expected `,`");
            return None;
        }
    }

    if bad {
        return None;
    }

    Some(entries)
}

fn parse_set(cx: &mut ExtCtxt, tts: &[TokenTree]) -> Option<Vec<Entry>> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), tts.to_vec());
    let mut entries = Vec::new();
    let value = quote_expr!(&*cx, ());

    let mut bad = false;
    while parser.token != Eof {
        let key = cx.expander().fold_expr(parser.parse_expr().unwrap());
        let key_contents = parse_key(cx, &*key).unwrap_or_else(|| {
            bad = true;
            Key::Str(InternedString::new(""))
        });

        entries.push(Entry {
            key_contents: key_contents,
            key: key,
            value: value.clone(),
        });

        if !parser.eat(&Comma).ok().unwrap() && parser.token != Eof {
            cx.span_err(parser.span, "expected `,`");
            return None;
        }
    }

    if bad {
        return None;
    }

    Some(entries)
}

fn parse_key(cx: &mut ExtCtxt, e: &Expr) -> Option<Key> {
    match e.node {
        ExprLit(ref lit) => {
            match lit.node {
                ast::LitStr(ref s, _) => Some(Key::Str(s.clone())),
                ast::LitByteStr(ref b) => Some(Key::Binary(b.clone())),
                ast::LitByte(b) => Some(Key::U8(b)),
                ast::LitChar(c) => Some(Key::Char(c)),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI8, ast::Plus)) => Some(Key::I8(i as i8)),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI8, ast::Minus)) =>
                    Some(Key::I8(-(i as i8))),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI16, ast::Plus)) =>
                    Some(Key::I16(i as i16)),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI16, ast::Minus)) =>
                    Some(Key::I16(-(i as i16))),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI32, ast::Plus)) =>
                    Some(Key::I32(i as i32)),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI32, ast::Minus)) =>
                    Some(Key::I32(-(i as i32))),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI64, ast::Plus)) =>
                    Some(Key::I64(i as i64)),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI64, ast::Minus)) =>
                    Some(Key::I64(-(i as i64))),
                ast::LitInt(i, ast::UnsignedIntLit(ast::TyU8)) => Some(Key::U8(i as u8)),
                ast::LitInt(i, ast::UnsignedIntLit(ast::TyU16)) => Some(Key::U16(i as u16)),
                ast::LitInt(i, ast::UnsignedIntLit(ast::TyU32)) => Some(Key::U32(i as u32)),
                ast::LitInt(i, ast::UnsignedIntLit(ast::TyU64)) => Some(Key::U64(i as u64)),
                ast::LitBool(b) => Some(Key::Bool(b)),
                _ => {
                    cx.span_err(e.span, "unsupported literal type");
                    None
                }
            }
        }
        ExprVec(ref v) => {
            let bytes: Vec<Option<u8>> = v.iter().map(|expr|
                if let ExprLit(ref p) = expr.node {
                    match **p {
                        Spanned {node: ast::LitInt(val, ast::UnsignedIntLit(ast::UintTy::TyU8)), ..} if val < 256 => Some(val as u8),
                        Spanned {node: ast::LitInt(val, ast::UnsuffixedIntLit(ast::Plus)), ..} if val < 256 => Some(val as u8),
                        _ => None,
                    }
                } else {
                    None
            }).collect();
            if bytes.iter().all(|x| x.is_some()) {
                Some(Key::Binary(std::rc::Rc::new(bytes.iter().map(|x| x.unwrap()).collect())))
            } else {
                cx.span_err(e.span,
                            "not all elements of an expected u8 array literal were u8 literals");
                None
            }
        }
        _ => {
            cx.span_err(e.span, "expected a literal");
            None
        }
    }
}

fn has_duplicates(cx: &mut ExtCtxt, sp: Span, entries: &[Entry]) -> bool {
    let mut dups = false;
    let mut strings = HashMap::new();
    for entry in entries.iter() {
        let &mut (ref mut spans, _) = match strings.entry(&entry.key_contents) {
            Occupied(e) => e.into_mut(),
            Vacant(e) => e.insert((vec![], &entry.key)),
        };
        spans.push(entry.key.span);
    }

    for &(ref spans, key) in strings.values() {
        if spans.len() == 1 {
            continue;
        }

        dups = true;
        cx.span_err(sp,
                    &*format!("duplicate key {}", pprust::expr_to_string(&**key)));
        for span in spans.iter() {
            cx.span_note(*span, "one occurrence here");
        }
    }

    dups
}
<commit_msg>Registry now seems to live in rustc_plugin instead of rustc::plugin<commit_after>//! Compiler plugin defining macros that create PHF data structures.
//!
//! # Example
//!
//! ```rust
//! #![feature(plugin, core)]
//! #![plugin(phf_macros)]
//!
//! extern crate phf;
//!
//! #[derive(Clone)]
//! pub enum Keyword {
//!     Loop,
//!     Continue,
//!     Break,
//!     Fn,
//!     Extern,
//! }
//!
//! static KEYWORDS: phf::Map<&'static str, Keyword> = phf_map! {
//!     "loop" => Keyword::Loop,
//!     "continue" => Keyword::Continue,
//!     "break" => Keyword::Break,
//!     "fn" => Keyword::Fn,
//!     "extern" => Keyword::Extern,
//! };
//!
//! pub fn parse_keyword(keyword: &str) -> Option<Keyword> {
//!     KEYWORDS.get(keyword).cloned()
//! }
//! # fn main() {}
//! ```
#![doc(html_root_url="http://sfackler.github.io/rust-phf/doc/v0.7.8")]
#![feature(plugin_registrar, quote, rustc_private)]

extern crate syntax;
#[cfg(feature = "stats")]
extern crate time;
extern crate rustc_plugin;
extern crate phf_shared;
extern crate phf_generator;

use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use syntax::ast::{self, TokenTree, LitStr, LitByteStr, LitByte, LitChar, Expr, ExprLit, ExprVec};
use syntax::codemap::{Span, Spanned};
use syntax::ext::base::{DummyResult, ExtCtxt, MacResult};
use syntax::fold::Folder;
use syntax::parse;
use syntax::parse::token::{InternedString, Comma, Eof, FatArrow};
use syntax::print::pprust;
use rustc_plugin::Registry;
use phf_generator::HashState;
use std::env;

use util::{Entry, Key};
use util::{create_map, create_set, create_ordered_map, create_ordered_set};

pub mod util;
mod macros;

#[plugin_registrar]
#[doc(hidden)]
pub fn macro_registrar(reg: &mut Registry) {
    reg.register_macro("phf_map", expand_phf_map);
    reg.register_macro("phf_set", expand_phf_set);
    reg.register_macro("phf_ordered_map", expand_phf_ordered_map);
    reg.register_macro("phf_ordered_set", expand_phf_ordered_set);
}

fn generate_hash(cx: &mut ExtCtxt, sp: Span, entries: &[Entry]) -> HashState {
    #[cfg(feature = "stats")]
    use time::precise_time_s;
    #[cfg(not(feature = "stats"))]
    fn precise_time_s() -> f64 {
        0.
    }

    let start = precise_time_s();
    let state = phf_generator::generate_hash(entries);
    let time = precise_time_s() - start;

    if cfg!(feature = "stats") && env::var_os("PHF_STATS").is_some() {
        cx.span_note(sp, &format!("PHF generation took {} seconds", time));
    }

    state
}

fn expand_phf_map(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult + 'static> {
    let entries = match parse_map(cx, tts) {
        Some(entries) => entries,
        None => return DummyResult::expr(sp),
    };

    if has_duplicates(cx, sp, &*entries) {
        return DummyResult::expr(sp);
    }

    let state = generate_hash(cx, sp, &*entries);

    create_map(cx, sp, entries, state)
}

fn expand_phf_set(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult + 'static> {
    let entries = match parse_set(cx, tts) {
        Some(entries) => entries,
        None => return DummyResult::expr(sp),
    };

    if has_duplicates(cx, sp, &*entries) {
        return DummyResult::expr(sp);
    }

    let state = generate_hash(cx, sp, &*entries);

    create_set(cx, sp, entries, state)
}

fn expand_phf_ordered_map(cx: &mut ExtCtxt,
                          sp: Span,
                          tts: &[TokenTree])
                          -> Box<MacResult + 'static> {
    let entries = match parse_map(cx, tts) {
        Some(entries) => entries,
        None => return DummyResult::expr(sp),
    };

    if has_duplicates(cx, sp, &*entries) {
        return DummyResult::expr(sp);
    }

    let state = generate_hash(cx, sp, &*entries);

    create_ordered_map(cx, sp, entries, state)
}

fn expand_phf_ordered_set(cx: &mut ExtCtxt,
                          sp: Span,
                          tts: &[TokenTree])
                          -> Box<MacResult + 'static> {
    let entries = match parse_set(cx, tts) {
        Some(entries) => entries,
        None => return DummyResult::expr(sp),
    };

    if has_duplicates(cx, sp, &*entries) {
        return DummyResult::expr(sp);
    }

    let state = generate_hash(cx, sp, &*entries);

    create_ordered_set(cx, sp, entries, state)
}

fn parse_map(cx: &mut ExtCtxt, tts: &[TokenTree]) -> Option<Vec<Entry>> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), tts.to_vec());
    let mut entries = Vec::new();

    let mut bad = false;
    while parser.token != Eof {
        let key = cx.expander().fold_expr(parser.parse_expr().unwrap());
        let key_contents = parse_key(cx, &*key).unwrap_or_else(|| {
            bad = true;
            Key::Str(InternedString::new(""))
        });

        if !parser.eat(&FatArrow).ok().unwrap() {
            cx.span_err(parser.span, "expected `=>`");
            return None;
        }

        let value = parser.parse_expr().unwrap();

        entries.push(Entry {
            key_contents: key_contents,
            key: key,
            value: value,
        });

        if !parser.eat(&Comma).ok().unwrap() && parser.token != Eof {
            cx.span_err(parser.span, "expected `,`");
            return None;
        }
    }

    if bad {
        return None;
    }

    Some(entries)
}

fn parse_set(cx: &mut ExtCtxt, tts: &[TokenTree]) -> Option<Vec<Entry>> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), tts.to_vec());
    let mut entries = Vec::new();
    let value = quote_expr!(&*cx, ());

    let mut bad = false;
    while parser.token != Eof {
        let key = cx.expander().fold_expr(parser.parse_expr().unwrap());
        let key_contents = parse_key(cx, &*key).unwrap_or_else(|| {
            bad = true;
            Key::Str(InternedString::new(""))
        });

        entries.push(Entry {
            key_contents: key_contents,
            key: key,
            value: value.clone(),
        });

        if !parser.eat(&Comma).ok().unwrap() && parser.token != Eof {
            cx.span_err(parser.span, "expected `,`");
            return None;
        }
    }

    if bad {
        return None;
    }

    Some(entries)
}

fn parse_key(cx: &mut ExtCtxt, e: &Expr) -> Option<Key> {
    match e.node {
        ExprLit(ref lit) => {
            match lit.node {
                ast::LitStr(ref s, _) => Some(Key::Str(s.clone())),
                ast::LitByteStr(ref b) => Some(Key::Binary(b.clone())),
                ast::LitByte(b) => Some(Key::U8(b)),
                ast::LitChar(c) => Some(Key::Char(c)),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI8, ast::Plus)) => Some(Key::I8(i as i8)),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI8, ast::Minus)) =>
                    Some(Key::I8(-(i as i8))),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI16, ast::Plus)) =>
                    Some(Key::I16(i as i16)),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI16, ast::Minus)) =>
                    Some(Key::I16(-(i as i16))),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI32, ast::Plus)) =>
                    Some(Key::I32(i as i32)),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI32, ast::Minus)) =>
                    Some(Key::I32(-(i as i32))),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI64, ast::Plus)) =>
                    Some(Key::I64(i as i64)),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI64, ast::Minus)) =>
                    Some(Key::I64(-(i as i64))),
                ast::LitInt(i, ast::UnsignedIntLit(ast::TyU8)) => Some(Key::U8(i as u8)),
                ast::LitInt(i, ast::UnsignedIntLit(ast::TyU16)) => Some(Key::U16(i as u16)),
                ast::LitInt(i, ast::UnsignedIntLit(ast::TyU32)) => Some(Key::U32(i as u32)),
                ast::LitInt(i, ast::UnsignedIntLit(ast::TyU64)) => Some(Key::U64(i as u64)),
                ast::LitBool(b) => Some(Key::Bool(b)),
                _ => {
                    cx.span_err(e.span, "unsupported literal type");
                    None
                }
            }
        }
        ExprVec(ref v) => {
            let bytes: Vec<Option<u8>> = v.iter().map(|expr|
                if let ExprLit(ref p) = expr.node {
                    match **p {
                        Spanned {node: ast::LitInt(val, ast::UnsignedIntLit(ast::UintTy::TyU8)), ..} if val < 256 => Some(val as u8),
                        Spanned {node: ast::LitInt(val, ast::UnsuffixedIntLit(ast::Plus)), ..} if val < 256 => Some(val as u8),
                        _ => None,
                    }
                } else {
                    None
            }).collect();
            if bytes.iter().all(|x| x.is_some()) {
                Some(Key::Binary(std::rc::Rc::new(bytes.iter().map(|x| x.unwrap()).collect())))
            } else {
                cx.span_err(e.span,
                            "not all elements of an expected u8 array literal were u8 literals");
                None
            }
        }
        _ => {
            cx.span_err(e.span, "expected a literal");
            None
        }
    }
}

fn has_duplicates(cx: &mut ExtCtxt, sp: Span, entries: &[Entry]) -> bool {
    let mut dups = false;
    let mut strings = HashMap::new();
    for entry in entries.iter() {
        let &mut (ref mut spans, _) = match strings.entry(&entry.key_contents) {
            Occupied(e) => e.into_mut(),
            Vacant(e) => e.insert((vec![], &entry.key)),
        };
        spans.push(entry.key.span);
    }

    for &(ref spans, key) in strings.values() {
        if spans.len() == 1 {
            continue;
        }

        dups = true;
        cx.span_err(sp,
                    &*format!("duplicate key {}", pprust::expr_to_string(&**key)));
        for span in spans.iter() {
            cx.span_note(*span, "one occurrence here");
        }
    }

    dups
}
<|endoftext|>


<commit_before>extern crate glium;

pub mod input {

    use input::glium::glutin::Event;

    pub struct Input;

    impl Input {

        pub fn new() -> Input {
            Input {}
        }

        pub fn process_input(&self, event:Event) -> bool {

            use input::glium::glutin::{ElementState, VirtualKeyCode as KeyCode};
            match event {
                Event::Closed => true,
                Event::KeyboardInput(ElementState::Pressed, _, Some(KeyCode::Escape)) => true,

                _ => false,
            }
        }

    }
}<commit_msg>refactored the move logic to a different function<commit_after>extern crate glium;

pub mod input {

    use input::glium::glutin::Event;

    pub struct Input;

    pub enum Direction {
        UP,
        DOWN,
        LEFT,
        RIGHT,
    }

    impl Input {

        pub fn new() -> Input {
            Input {}
        }

        pub fn process_input(&self, event:Event) -> bool {
            use input::glium::glutin::Event::KeyboardInput as Keyboard;
            use input::glium::glutin::{ElementState as State, VirtualKeyCode as KeyCode};
            match event {
                Event::Closed => true,
                Keyboard(State::Pressed, _, Some(KeyCode::Escape)) => true,
                Keyboard(State::Pressed, _, Some(KeyCode::Up)) => self.move_dir(Direction::UP),
                Keyboard(State::Pressed, _, Some(KeyCode::Down)) => self.move_dir(Direction::DOWN),
                Keyboard(State::Pressed, _, Some(KeyCode::Left)) => self.move_dir(Direction::LEFT),
                Keyboard(State::Pressed, _, Some(KeyCode::Right)) => self.move_dir(Direction::RIGHT),
                Keyboard(State::Pressed, _, Some(KeyCode::Return)) => false,
                _ => false,
            }
        }

        pub fn move_dir(&self, dir:Direction) -> bool{

            false
        }
    }
}<|endoftext|>


<commit_before>use super::*;

ast_struct! {
    pub struct Crate {
        pub shebang: Option<String>,
        pub attrs: Vec<Attribute>,
        pub items: Vec<Item>,
    }
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;

    use synom::{IResult, Synom, ParseError};
    use proc_macro2::TokenTree;

    impl Synom for Crate {
        fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
            do_parse! {
                input,
                attrs: many0!(call!(Attribute::parse_inner)) >>
                items: many0!(syn!(Item)) >>
                (Crate {
                    shebang: None,
                    attrs: attrs,
                    items: items,
                })
            }
        }

        fn description() -> Option<&'static str> {
            Some("crate")
        }

        fn parse_str_all(mut input: &str) -> Result<Self, ParseError> {
            // Strip the BOM if it is present
            const BOM: &'static str = "\u{feff}";
            if input.starts_with(BOM) {
                input = &input[BOM.len()..];
            }

            let mut shebang = None;
            if input.starts_with("#!") && !input.starts_with("#![") {
                if let Some(idx) = input.find('\n') {
                    shebang = Some(input[..idx].to_string());
                    input = &input[idx..];
                } else {
                    shebang = Some(input.to_string());
                    input = "";
                }
            }

            let mut krate: Crate = Self::parse_all(input.parse()?)?;
            krate.shebang = shebang;
            Ok(krate)
        }
    }
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use attr::FilterAttrs;
    use quote::{Tokens, ToTokens};

    impl ToTokens for Crate {
        fn to_tokens(&self, tokens: &mut Tokens) {
            tokens.append_all(self.attrs.inner());
            tokens.append_all(&self.items);
        }
    }
}
<commit_msg>Use nom macro to declare parse method inside Synom trait<commit_after>use super::*;

ast_struct! {
    pub struct Crate {
        pub shebang: Option<String>,
        pub attrs: Vec<Attribute>,
        pub items: Vec<Item>,
    }
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;

    use synom::{IResult, Synom, ParseError};
    use proc_macro2::TokenTree;

    impl Synom for Crate {
        named!(parse -> Self, do_parse!(
            attrs: many0!(call!(Attribute::parse_inner)) >>
            items: many0!(syn!(Item)) >>
            (Crate {
                shebang: None,
                attrs: attrs,
                items: items,
            })
        ));

        fn description() -> Option<&'static str> {
            Some("crate")
        }

        fn parse_str_all(mut input: &str) -> Result<Self, ParseError> {
            // Strip the BOM if it is present
            const BOM: &'static str = "\u{feff}";
            if input.starts_with(BOM) {
                input = &input[BOM.len()..];
            }

            let mut shebang = None;
            if input.starts_with("#!") && !input.starts_with("#![") {
                if let Some(idx) = input.find('\n') {
                    shebang = Some(input[..idx].to_string());
                    input = &input[idx..];
                } else {
                    shebang = Some(input.to_string());
                    input = "";
                }
            }

            let mut krate: Crate = Self::parse_all(input.parse()?)?;
            krate.shebang = shebang;
            Ok(krate)
        }
    }
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use attr::FilterAttrs;
    use quote::{Tokens, ToTokens};

    impl ToTokens for Crate {
        fn to_tokens(&self, tokens: &mut Tokens) {
            tokens.append_all(self.attrs.inner());
            tokens.append_all(&self.items);
        }
    }
}
<|endoftext|>


<commit_before>// rustfmt-wrap_comments: true
// Test attributes and doc comments are preserved.
#![doc(
    html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
    html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
    html_root_url = "https://doc.rust-lang.org/nightly/",
    html_playground_url = "https://play.rust-lang.org/",
    test(attr(deny(warnings)))
)]

//! Doc comment

#![attribute]

//! Crate doc comment

// Comment

// Comment on attribute
#![the(attribute)]

// Another comment

#[invalid attribute]
fn foo() {}

/// Blah blah blah.
/// Blah blah blah.
/// Blah blah blah.
/// Blah blah blah.

/// Blah blah blah.
impl Bar {
    /// Blah blah blooo.
    /// Blah blah blooo.
    /// Blah blah blooo.
    /// Blah blah blooo.
    #[an_attribute]
    fn foo(&mut self) -> isize {}

    /// Blah blah bing.
    /// Blah blah bing.
    /// Blah blah bing.

    /// Blah blah bing.
    /// Blah blah bing.
    /// Blah blah bing.
    pub fn f2(self) {
        (foo, bar)
    }

    #[another_attribute]
    fn f3(self) -> Dog {}

    /// Blah blah bing.

    #[attrib1]
    /// Blah blah bing.
    #[attrib2]
    // Another comment that needs rewrite because it's tooooooooooooooooooooooooooooooo
    // loooooooooooong.
    /// Blah blah bing.
    fn f4(self) -> Cat {}

    // We want spaces around `=`
    #[cfg(feature = "nightly")]
    fn f5(self) -> Monkey {}
}

// #984
struct Foo {
    #[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
    foo: usize,
}

// #1668

/// Default path (*nix)
#[cfg(
    all(
        unix,
        not(target_os = "macos"),
        not(target_os = "ios"),
        not(target_os = "android")
    )
)]
fn foo() {
    #[cfg(target_os = "freertos")]
    match port_id {
        'a' | 'A' => GpioPort {
            port_address: GPIO_A,
        },
        'b' | 'B' => GpioPort {
            port_address: GPIO_B,
        },
        _ => panic!(),
    }

    #[cfg_attr(not(target_os = "freertos"), allow(unused_variables))]
    let x = 3;
}

// #1777
#[test]
#[should_panic(expected = "(")]
#[should_panic(expected = /* ( */ "(")]
#[should_panic(/* ((((( */expected /* ((((( */= /* ((((( */ "("/* ((((( */)]
#[should_panic(
    /* (((((((( *//*
    (((((((((()(((((((( */
    expected = "("
    // ((((((((
)]
fn foo() {}

// #1799
fn issue_1799() {
    #[allow(unreachable_code)] // https://github.com/rust-lang/rust/issues/43336
    Some(Err(error));

    #[allow(unreachable_code)]
    // https://github.com/rust-lang/rust/issues/43336
    Some(Err(error));
}

// Formatting inner attributes
fn inner_attributes() {
    #![this_is_an_inner_attribute(foo)]

    foo();
}

impl InnerAttributes() {
    #![this_is_an_inner_attribute(foo)]

    fn foo() {}
}

mod InnerAttributes {
    #![this_is_an_inner_attribute(foo)]
}

fn attributes_on_statements() {
    // Local
    #[attr(on(local))]
    let x = 3;

    // Item
    #[attr(on(item))]
    use foo;

    // Expr
    #[attr(on(expr))]
    {}

    // Semi
    #[attr(on(semi))]
    foo();

    // Mac
    #[attr(on(mac))]
    foo!();
}

// Large derives
#[derive(
    Add, Sub, Mul, Div, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Serialize, Mul,
)]

/// Foo bar baz

#[derive(
    Add,
    Sub,
    Mul,
    Div,
    Clone,
    Copy,
    Eq,
    PartialEq,
    Ord,
    PartialOrd,
    Debug,
    Hash,
    Serialize,
    Deserialize,
)]
pub struct HP(pub u8);

// Long `#[doc = "..."]`
struct A {
    #[doc = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"]
    b: i32,
}

// #2647
#[cfg(
    feature = "this_line_is_101_characters_long_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
)]
pub fn foo() {}

// path attrs
#[clippy::bar]
#[clippy::bar=foo]
#[clippy::bar(a, b, c)]
pub fn foo() {}

mod issue_2620 {
    #[derive(Debug, StructOpt)]
    #[structopt(about = "Display information about the character on FF Logs")]
    pub struct Params {
        #[structopt(help = "The server the character is on")]
        server: String,
        #[structopt(help = "The character's first name")]
        first_name: String,
        #[structopt(help = "The character's last name")]
        last_name: String,
        #[structopt(
            short = "j",
            long = "job",
            help = "The job to look at",
            parse(try_from_str)
        )]
        job: Option<Job>,
    }
}
<commit_msg>Update test<commit_after>// rustfmt-wrap_comments: true
// Test attributes and doc comments are preserved.
#![doc(
    html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
    html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
    html_root_url = "https://doc.rust-lang.org/nightly/",
    html_playground_url = "https://play.rust-lang.org/",
    test(attr(deny(warnings)))
)]

//! Doc comment

#![attribute]

//! Crate doc comment

// Comment

// Comment on attribute
#![the(attribute)]

// Another comment

#[invalid attribute]
fn foo() {}

/// Blah blah blah.
/// Blah blah blah.
/// Blah blah blah.
/// Blah blah blah.

/// Blah blah blah.
impl Bar {
    /// Blah blah blooo.
    /// Blah blah blooo.
    /// Blah blah blooo.
    /// Blah blah blooo.
    #[an_attribute]
    fn foo(&mut self) -> isize {}

    /// Blah blah bing.
    /// Blah blah bing.
    /// Blah blah bing.

    /// Blah blah bing.
    /// Blah blah bing.
    /// Blah blah bing.
    pub fn f2(self) {
        (foo, bar)
    }

    #[another_attribute]
    fn f3(self) -> Dog {}

    /// Blah blah bing.

    #[attrib1]
    /// Blah blah bing.
    #[attrib2]
    // Another comment that needs rewrite because it's tooooooooooooooooooooooooooooooo
    // loooooooooooong.
    /// Blah blah bing.
    fn f4(self) -> Cat {}

    // We want spaces around `=`
    #[cfg(feature = "nightly")]
    fn f5(self) -> Monkey {}
}

// #984
struct Foo {
    #[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
    foo: usize,
}

// #1668

/// Default path (*nix)
#[cfg(all(
    unix,
    not(target_os = "macos"),
    not(target_os = "ios"),
    not(target_os = "android")
))]
fn foo() {
    #[cfg(target_os = "freertos")]
    match port_id {
        'a' | 'A' => GpioPort {
            port_address: GPIO_A,
        },
        'b' | 'B' => GpioPort {
            port_address: GPIO_B,
        },
        _ => panic!(),
    }

    #[cfg_attr(not(target_os = "freertos"), allow(unused_variables))]
    let x = 3;
}

// #1777
#[test]
#[should_panic(expected = "(")]
#[should_panic(expected = /* ( */ "(")]
#[should_panic(/* ((((( */expected /* ((((( */= /* ((((( */ "("/* ((((( */)]
#[should_panic(
    /* (((((((( *//*
    (((((((((()(((((((( */
    expected = "("
    // ((((((((
)]
fn foo() {}

// #1799
fn issue_1799() {
    #[allow(unreachable_code)] // https://github.com/rust-lang/rust/issues/43336
    Some(Err(error));

    #[allow(unreachable_code)]
    // https://github.com/rust-lang/rust/issues/43336
    Some(Err(error));
}

// Formatting inner attributes
fn inner_attributes() {
    #![this_is_an_inner_attribute(foo)]

    foo();
}

impl InnerAttributes() {
    #![this_is_an_inner_attribute(foo)]

    fn foo() {}
}

mod InnerAttributes {
    #![this_is_an_inner_attribute(foo)]
}

fn attributes_on_statements() {
    // Local
    #[attr(on(local))]
    let x = 3;

    // Item
    #[attr(on(item))]
    use foo;

    // Expr
    #[attr(on(expr))]
    {}

    // Semi
    #[attr(on(semi))]
    foo();

    // Mac
    #[attr(on(mac))]
    foo!();
}

// Large derives
#[derive(
    Add, Sub, Mul, Div, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Serialize, Mul,
)]

/// Foo bar baz

#[derive(
    Add,
    Sub,
    Mul,
    Div,
    Clone,
    Copy,
    Eq,
    PartialEq,
    Ord,
    PartialOrd,
    Debug,
    Hash,
    Serialize,
    Deserialize,
)]
pub struct HP(pub u8);

// Long `#[doc = "..."]`
struct A {
    #[doc = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"]
    b: i32,
}

// #2647
#[cfg(
    feature = "this_line_is_101_characters_long_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
)]
pub fn foo() {}

// path attrs
#[clippy::bar]
#[clippy::bar=foo]
#[clippy::bar(a, b, c)]
pub fn foo() {}

mod issue_2620 {
    #[derive(Debug, StructOpt)]
    #[structopt(about = "Display information about the character on FF Logs")]
    pub struct Params {
        #[structopt(help = "The server the character is on")]
        server: String,
        #[structopt(help = "The character's first name")]
        first_name: String,
        #[structopt(help = "The character's last name")]
        last_name: String,
        #[structopt(
            short = "j",
            long = "job",
            help = "The job to look at",
            parse(try_from_str)
        )]
        job: Option<Job>,
    }
}
<|endoftext|>


<commit_before>//
// FlightVars
// Copyright (c) 2015, 2016 Alvaro Polo
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::fmt;
use std::io;
use std::str::FromStr;

use byteorder::{BigEndian, ReadBytesExt};
use hex::FromHex;

#[derive(Debug, PartialEq)]
pub struct OffsetAddr(u16);

impl FromHex for OffsetAddr {
    type Error = io::Error;
    fn from_hex(s: &str) -> Result<Self, Self::Error> {
        let error = || io::Error::new(
            io::ErrorKind::InvalidInput,
            format!("invalid FSUIPC offset address in '{}'", s));
        let buf: Vec<u8> = try!(FromHex::from_hex(s).map_err(|_| error()));
        if buf.len() > 2 { Err(error()) }
        else {
            (&buf[..]).read_u16::<BigEndian>()
                .map(|v| OffsetAddr(v))
                .map_err(|_| error())
        }
    }
}

impl fmt::Display for OffsetAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{:x}", self.0)
    }
}

#[derive(Debug, PartialEq)]
pub enum OffsetLength { Ub, Sb, Uw, Sw, Ud, Sd }

impl fmt::Display for OffsetLength {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            OffsetLength::Ub => write!(f, "UB"),
            OffsetLength::Sb => write!(f, "SB"),
            OffsetLength::Uw => write!(f, "UW"),
            OffsetLength::Sw => write!(f, "SW"),
            OffsetLength::Ud => write!(f, "UD"),
            OffsetLength::Sd => write!(f, "SD"),
        }
    }
}

impl FromStr for OffsetLength {
    type Err = io::Error;
    fn from_str(s: &str) -> Result<OffsetLength, io::Error> {
        match s {
            "UB" => Ok(OffsetLength::Ub),
            "SB" => Ok(OffsetLength::Sb),
            "UW" => Ok(OffsetLength::Uw),
            "SW" => Ok(OffsetLength::Sw),
            "UD" => Ok(OffsetLength::Ud),
            "SD" => Ok(OffsetLength::Sd),
            _ => Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                format!("invalid FSUIPC offset length in '{}'", s))),
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum Message {
    Begin { version: u16, client_id: String },
    WriteLvar { lvar: String, value: i64 },
    WriteOffset { address: OffsetAddr, length: OffsetLength, value: i64 },
    ObserveLvar { lvar: String }
}

impl Message {

    pub fn begin(version: u16, client_id: &str) -> Message {
        Message::Begin { version: version, client_id: client_id.to_string() }
    }

    pub fn write_lvar(lvar: &str, value: i64) -> Message {
        Message::WriteLvar { lvar: lvar.to_string(), value: value }
    }

    pub fn write_offset(addr: OffsetAddr, len: OffsetLength, value: i64) -> Message {
        Message::WriteOffset { address: addr, length: len, value: value }
    }

    pub fn obs_lvar(lvar: &str) -> Message {
        Message::ObserveLvar { lvar: lvar.to_string() }
    }

    pub fn decode<R: io::BufRead>(r: &mut R) -> io::Result<Message> {
        let mut line = String::new();
        try!(r.read_line(&mut line));
        let mut split = line.split_whitespace();
        let cmd = try!(split.next().ok_or(Message::input_error(&line)));
        match &cmd.to_uppercase()[..] {
            "BEGIN" => Message::decode_begin(&line, &mut split),
            "WRITE_LVAR" => Message::decode_write_lvar(&line, &mut split),
            "WRITE_OFFSET" => Message::decode_write_offset(&line, &mut split),
            "OBS_LVAR" => Message::decode_obs_lvar(&line, &mut split),
            _ => Err(Message::input_error(&line)),
        }
    }

    pub fn encode<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
        match self {
            &Message::Begin { version, ref client_id } =>
                write!(w, "BEGIN {} {}\n", version, client_id),
            &Message::WriteLvar { ref lvar, value} =>
                write!(w, "WRITE_LVAR {} {}\n", lvar, value),
            &Message::WriteOffset { ref address, ref length, value } =>
                write!(w, "WRITE_OFFSET {}:{} {}\n", address, length, value),
            &Message::ObserveLvar { ref lvar } =>
                write!(w, "OBS_LVAR {}\n", lvar),
        }
    }

    fn decode_begin<'a, I: Iterator<Item=&'a str>>(
            line: &str, args: &mut I) -> io::Result<Message> {
        let error = || Message::input_error(line);
        let version = try!(args.next().ok_or_else(&error));
        let client_id = try!(args.next().ok_or_else(&error));
        let version = try!(version.parse().map_err(|_| error()));
        Ok(Message::begin(version, &client_id))
    }

    fn decode_write_lvar<'a, I: Iterator<Item=&'a str>>(
            line: &str, args: &mut I) -> io::Result<Message> {
        let error = || Message::input_error(line);
        let lvar = try!(args.next().ok_or_else(&error));
        let value = try!(args.next().ok_or_else(&error));
        let value = try!(value.parse().map_err(|_| error()));
        Ok(Message::write_lvar(&lvar, value))
    }

    fn decode_write_offset<'a, I: Iterator<Item=&'a str>>(
            line: &str, args: &mut I) -> io::Result<Message> {
        let error = || Message::input_error(line);
        let mut offset = try!(args.next().ok_or_else(&error)).split(":");
        let addr = try!(offset.next().ok_or_else(&error));
        let addr: OffsetAddr = try!(OffsetAddr::from_hex(&addr).map_err(|_| error()));
        let len = try!(offset.next().ok_or_else(&error));
        let len = try!(len.parse().map_err(|_| error()));
        let value = try!(args.next().ok_or_else(&error));
        let value = try!(value.parse().map_err(|_| error()));
        Ok(Message::write_offset(addr, len, value))
    }

    fn decode_obs_lvar<'a, I: Iterator<Item=&'a str>>(
            line: &str, args: &mut I) -> io::Result<Message> {
        let lvar = try!(args.next().ok_or(Message::input_error(line)));
        Ok(Message::obs_lvar(&lvar))
    }

    fn input_error(line: &str) -> io::Error {
        io::Error::new(
            io::ErrorKind::InvalidInput,
            format!("invalid oacsp message in '{}'", line))
    }
}

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

    #[test]
    fn should_encode_begin_msg() {
        let mut buf = vec![];
        let msg = Message::begin(1, "arduino");
        msg.encode(&mut buf).unwrap();
        assert_eq!(buf, b"BEGIN 1 arduino\n")
    }

    #[test]
    fn should_decode_begin_msg() {
        let mut buf = &b"BEGIN 1 arduino\n"[..];
        let msg = Message::decode(&mut buf).unwrap();
        assert_eq!(msg, Message::begin(1, "arduino"));
    }

    #[test]
    fn should_encode_write_lvar_msg() {
        let mut buf = vec![];
        let msg = Message::write_lvar("foobar", 42);
        msg.encode(&mut buf).unwrap();
        assert_eq!(buf, b"WRITE_LVAR foobar 42\n")
    }

    #[test]
    fn should_decode_write_lvar_msg() {
        let mut buf = &b"WRITE_LVAR foobar 42\n"[..];
        let msg = Message::decode(&mut buf).unwrap();
        assert_eq!(msg, Message::write_lvar("foobar", 42));
    }

    #[test]
    fn should_encode_write_offset_msg() {
        let mut buf = vec![];
        let msg = Message::write_offset(OffsetAddr(0x1234), OffsetLength::Uw, 42);
        msg.encode(&mut buf).unwrap();
        assert_eq!(buf, b"WRITE_OFFSET 1234:UW 42\n")
    }

    #[test]
    fn should_decode_write_offset_msg() {
        let mut buf = &b"WRITE_OFFSET 1234:UW 42\n"[..];
        let msg = Message::decode(&mut buf).unwrap();
        assert_eq!(msg, Message::write_offset(OffsetAddr(0x1234), OffsetLength::Uw, 42));
    }

    #[test]
    fn should_encode_obs_lvar_msg() {
        let mut buf = vec![];
        let msg = Message::obs_lvar("foobar");
        msg.encode(&mut buf).unwrap();
        assert_eq!(buf, b"OBS_LVAR foobar\n")
    }

    #[test]
    fn should_decode_obs_lvar_msg() {
        let mut buf = &b"OBS_LVAR foobar\n"[..];
        let msg = Message::decode(&mut buf).unwrap();
        assert_eq!(msg, Message::obs_lvar("foobar"));
    }
}
<commit_msg>Introduce `Offset` type in `oacsp` module<commit_after>//
// FlightVars
// Copyright (c) 2015, 2016 Alvaro Polo
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::fmt;
use std::io;
use std::str::FromStr;

use byteorder::{BigEndian, ReadBytesExt};
use hex::FromHex;

#[derive(Debug, PartialEq)]
pub struct OffsetAddr(u16);

impl FromHex for OffsetAddr {
    type Error = io::Error;
    fn from_hex(s: &str) -> Result<Self, Self::Error> {
        let error = || io::Error::new(
            io::ErrorKind::InvalidInput,
            format!("invalid FSUIPC offset address in '{}'", s));
        let buf: Vec<u8> = try!(FromHex::from_hex(s).map_err(|_| error()));
        if buf.len() > 2 { Err(error()) }
        else {
            (&buf[..]).read_u16::<BigEndian>()
                .map(|v| OffsetAddr(v))
                .map_err(|_| error())
        }
    }
}

impl fmt::Display for OffsetAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{:x}", self.0)
    }
}

#[derive(Debug, PartialEq)]
pub enum OffsetLength { Ub, Sb, Uw, Sw, Ud, Sd }

impl fmt::Display for OffsetLength {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            OffsetLength::Ub => write!(f, "UB"),
            OffsetLength::Sb => write!(f, "SB"),
            OffsetLength::Uw => write!(f, "UW"),
            OffsetLength::Sw => write!(f, "SW"),
            OffsetLength::Ud => write!(f, "UD"),
            OffsetLength::Sd => write!(f, "SD"),
        }
    }
}

impl FromStr for OffsetLength {
    type Err = io::Error;
    fn from_str(s: &str) -> Result<OffsetLength, io::Error> {
        match s {
            "UB" => Ok(OffsetLength::Ub),
            "SB" => Ok(OffsetLength::Sb),
            "UW" => Ok(OffsetLength::Uw),
            "SW" => Ok(OffsetLength::Sw),
            "UD" => Ok(OffsetLength::Ud),
            "SD" => Ok(OffsetLength::Sd),
            _ => Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                format!("invalid FSUIPC offset length in '{}'", s))),
        }
    }
}

#[derive(Debug, PartialEq)]
pub struct Offset(OffsetAddr, OffsetLength);

impl fmt::Display for Offset {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{}:{}", self.0, self.1)
    }
}

impl FromStr for Offset {
    type Err = io::Error;
    fn from_str(s: &str) -> Result<Offset, io::Error> {
        let pair: Vec<&str> = s.split(":").collect();
        if pair.len() == 2 {
            let addr = try!(OffsetAddr::from_hex(pair[0]));
            let len = try!(OffsetLength::from_str(pair[1]));
            Ok(Offset(addr, len))
        } else {
            Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                format!("invalid FSUIPC offset in '{}'", s)))
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum Message {
    Begin { version: u16, client_id: String },
    WriteLvar { lvar: String, value: i64 },
    WriteOffset { offset: Offset, value: i64 },
    ObserveLvar { lvar: String }
}

impl Message {

    pub fn begin(version: u16, client_id: &str) -> Message {
        Message::Begin { version: version, client_id: client_id.to_string() }
    }

    pub fn write_lvar(lvar: &str, value: i64) -> Message {
        Message::WriteLvar { lvar: lvar.to_string(), value: value }
    }

    pub fn write_offset(offset: Offset, value: i64) -> Message {
        Message::WriteOffset { offset: offset, value: value }
    }

    pub fn obs_lvar(lvar: &str) -> Message {
        Message::ObserveLvar { lvar: lvar.to_string() }
    }

    pub fn decode<R: io::BufRead>(r: &mut R) -> io::Result<Message> {
        let mut line = String::new();
        try!(r.read_line(&mut line));
        let mut split = line.split_whitespace();
        let cmd = try!(split.next().ok_or(Message::input_error(&line)));
        match &cmd.to_uppercase()[..] {
            "BEGIN" => Message::decode_begin(&line, &mut split),
            "WRITE_LVAR" => Message::decode_write_lvar(&line, &mut split),
            "WRITE_OFFSET" => Message::decode_write_offset(&line, &mut split),
            "OBS_LVAR" => Message::decode_obs_lvar(&line, &mut split),
            _ => Err(Message::input_error(&line)),
        }
    }

    pub fn encode<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
        match self {
            &Message::Begin { version, ref client_id } =>
                write!(w, "BEGIN {} {}\n", version, client_id),
            &Message::WriteLvar { ref lvar, value} =>
                write!(w, "WRITE_LVAR {} {}\n", lvar, value),
            &Message::WriteOffset { ref offset, value } =>
                write!(w, "WRITE_OFFSET {} {}\n", offset, value),
            &Message::ObserveLvar { ref lvar } =>
                write!(w, "OBS_LVAR {}\n", lvar),
        }
    }

    fn decode_begin<'a, I: Iterator<Item=&'a str>>(
            line: &str, args: &mut I) -> io::Result<Message> {
        let error = || Message::input_error(line);
        let version = try!(args.next().ok_or_else(&error));
        let client_id = try!(args.next().ok_or_else(&error));
        let version = try!(version.parse().map_err(|_| error()));
        Ok(Message::begin(version, &client_id))
    }

    fn decode_write_lvar<'a, I: Iterator<Item=&'a str>>(
            line: &str, args: &mut I) -> io::Result<Message> {
        let error = || Message::input_error(line);
        let lvar = try!(args.next().ok_or_else(&error));
        let value = try!(args.next().ok_or_else(&error));
        let value = try!(value.parse().map_err(|_| error()));
        Ok(Message::write_lvar(&lvar, value))
    }

    fn decode_write_offset<'a, I: Iterator<Item=&'a str>>(
            line: &str, args: &mut I) -> io::Result<Message> {
        let error = || Message::input_error(line);
        let offset = try!(args.next().ok_or_else(&error));
        let offset = try!(offset.parse().map_err(|_| error()));
        let value = try!(args.next().ok_or_else(&error));
        let value = try!(value.parse().map_err(|_| error()));
        Ok(Message::write_offset(offset, value))
    }

    fn decode_obs_lvar<'a, I: Iterator<Item=&'a str>>(
            line: &str, args: &mut I) -> io::Result<Message> {
        let lvar = try!(args.next().ok_or(Message::input_error(line)));
        Ok(Message::obs_lvar(&lvar))
    }

    fn input_error(line: &str) -> io::Error {
        io::Error::new(
            io::ErrorKind::InvalidInput,
            format!("invalid oacsp message in '{}'", line))
    }
}

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

    #[test]
    fn should_encode_begin_msg() {
        let mut buf = vec![];
        let msg = Message::begin(1, "arduino");
        msg.encode(&mut buf).unwrap();
        assert_eq!(buf, b"BEGIN 1 arduino\n")
    }

    #[test]
    fn should_decode_begin_msg() {
        let mut buf = &b"BEGIN 1 arduino\n"[..];
        let msg = Message::decode(&mut buf).unwrap();
        assert_eq!(msg, Message::begin(1, "arduino"));
    }

    #[test]
    fn should_encode_write_lvar_msg() {
        let mut buf = vec![];
        let msg = Message::write_lvar("foobar", 42);
        msg.encode(&mut buf).unwrap();
        assert_eq!(buf, b"WRITE_LVAR foobar 42\n")
    }

    #[test]
    fn should_decode_write_lvar_msg() {
        let mut buf = &b"WRITE_LVAR foobar 42\n"[..];
        let msg = Message::decode(&mut buf).unwrap();
        assert_eq!(msg, Message::write_lvar("foobar", 42));
    }

    #[test]
    fn should_encode_write_offset_msg() {
        let mut buf = vec![];
        let msg = Message::write_offset(Offset(OffsetAddr(0x1234), OffsetLength::Uw), 42);
        msg.encode(&mut buf).unwrap();
        assert_eq!(buf, b"WRITE_OFFSET 1234:UW 42\n")
    }

    #[test]
    fn should_decode_write_offset_msg() {
        let mut buf = &b"WRITE_OFFSET 1234:UW 42\n"[..];
        let msg = Message::decode(&mut buf).unwrap();
        assert_eq!(msg, Message::write_offset(Offset(OffsetAddr(0x1234), OffsetLength::Uw), 42));
    }

    #[test]
    fn should_encode_obs_lvar_msg() {
        let mut buf = vec![];
        let msg = Message::obs_lvar("foobar");
        msg.encode(&mut buf).unwrap();
        assert_eq!(buf, b"OBS_LVAR foobar\n")
    }

    #[test]
    fn should_decode_obs_lvar_msg() {
        let mut buf = &b"OBS_LVAR foobar\n"[..];
        let msg = Message::decode(&mut buf).unwrap();
        assert_eq!(msg, Message::obs_lvar("foobar"));
    }
}
<|endoftext|>


<commit_before>use rand::random;
use std::collections::HashMap;

use eval::Eval;

#[derive(Debug,PartialEq)]
pub struct SrcBlock {
    pub name: String,
    pub src: Vec<SrcKind>
}

#[derive(Debug,PartialEq)]
pub struct DefBlock {
    pub name: String,
    pub defs: Vec<(String,VarKind)>
}

#[derive(Debug,PartialEq)]
pub enum BlockKind {
    Src(SrcBlock),
    Def(DefBlock),
}

/// delimited by new line
#[derive(Debug,PartialEq)]
pub enum SrcKind {
    Logic(String, LogicKind), // ex: item_logic has_item

    // references logic in env and emits varkinds;
    // logic must resolve to true
    // ex: if item_logic give_quest
    // Can optionally end execution and begin next node
    If(ExpectKind, Vec<VarKind>, Option<String>),

    Composite(String,ExpectKind,Vec<String>),
    Next(String), // ends execution and begins next node
}

#[derive(Debug,PartialEq)]
pub enum ExpectKind {
    All,
    Any,
    None,

    Ref(String) // references env variable set from logic
}
impl ExpectKind {
    pub fn parse(s: String) -> ExpectKind {
        match &s[..] {
            "all" => ExpectKind::All,
            "any" => ExpectKind::Any,
            "none" => ExpectKind::None,
            _ => ExpectKind::Ref(s),
        }
    }
}

impl SrcKind {
    pub fn eval<D:Eval> (&self, state: &mut HashMap<String,bool>, data: &D)
                     -> (Vec<VarKind>,Option<String>)
    {
        match self {
            &SrcKind::Next(ref node) => {
                return (vec![],Some(node.clone()))
            },
            &SrcKind::Logic(ref name, ref logic) => { //logic updates state
                let name = name.clone();
                match logic {
                    &LogicKind::Is(ref lookup) => {
                        let r = data.eval(&lookup);
                        if r.is_some() {
                            match r.unwrap() {
                                VarKind::Bool(v) => { state.insert(name,v); },
                                _ => { state.insert(name,true); }, //if exists?
                            }
                        }
                    },
                    &LogicKind::IsNot(ref lookup) => { //inverse state
                        let r = data.eval(&lookup);
                        if r.is_some() {
                            match r.unwrap() {
                                VarKind::Bool(v) => {
                                    if !v { state.insert(name,true); }
                                },
                                _ => { state.insert(name,false); },
                            }
                        }
                    },

                    &LogicKind::GT(ref left, ref right) => {
                        let right = VarKind::get_num::<D>(right,data);
                        let left = VarKind::get_num::<D>(left,data);

                        if left.is_ok() && right.is_ok() {
                            state.insert(name, left.unwrap() > right.unwrap());
                        }
                    },
                    &LogicKind::LT(ref left, ref right) => {
                        let right = VarKind::get_num::<D>(right,data);
                        let left = VarKind::get_num::<D>(left,data);

                        if left.is_ok() && right.is_ok() {
                            state.insert(name, left.unwrap() < right.unwrap());
                        }
                    },
                }

                return (vec![],None) // logic does not return anything
            },
            &SrcKind::Composite(ref name, ref x, ref lookups) => {
                let mut comp_value = false;
                match x {
                    &ExpectKind::All => { // all must pass as true
                        for lookup in lookups.iter() {
                            let val = state.get(lookup);
                            if val.is_some() && *val.unwrap() {
                                comp_value = true;
                            }
                            else { comp_value = false; break }
                        }

                        state.insert(name.clone(),comp_value);
                    },
                    &ExpectKind::Any => { // first truth passes for set
                        for lookup in lookups.iter() {
                            let val = state.get(lookup);
                            if val.is_some() && *val.unwrap() {
                                comp_value = true;
                                break;
                            }
                        }

                        state.insert(name.clone(),comp_value);
                    },
                    &ExpectKind::None => { // inverse of any, none must be true
                        for lookup in lookups.iter() {
                            let val = state.get(lookup);
                            if val.is_some() && *val.unwrap() {
                                comp_value = false;
                                break;
                            }
                        }

                        state.insert(name.clone(),comp_value);
                    },
                    &ExpectKind::Ref(_) => panic!("ERROR: Unexpected parsing") // this should never hit
                }

                return (vec![],None) // composite does not return anything
            },
            &SrcKind::If(ref x, ref v, ref node) => {
                let mut if_value = false;
                match x {
                    &ExpectKind::All => {
                        for n in state.values() {
                            if !n { if_value = false; break }
                            else { if_value = true; }
                        }
                    },
                    &ExpectKind::Any => {
                        for n in state.values() {
                            if *n { if_value = true; break }
                        }
                    },
                    &ExpectKind::None => {
                        for n in state.values() {
                            if !n { if_value = true; }
                            else { if_value = true; break }
                        }
                    },
                    &ExpectKind::Ref(ref lookup) => {
                        let val = state.get(lookup);
                        if let Some(val) = val {
                            if_value = *val;
                        }
                    },
                }

                if if_value { return ((*v).clone(),node.clone()) }
                else { return (vec![],None) }
            }
        }
    }

    pub fn parse(mut exp: Vec<String>) -> SrcKind {
        if exp[0] == "if" {
            if exp.len() < 3 { panic!("ERROR: Invalid IF Logic {:?}",exp) }

            let x = exp.remove(1);

            let mut node = None;
            if exp.len() > 2 {
                let next = &exp[exp.len() - 2] == "next";
                if next {
                    node = exp.pop();
                    let _ = exp.pop(); // remove next tag
                }
            }

            let v = exp.drain(1..).map(|n| VarKind::parse(n)).collect();
            SrcKind::If(ExpectKind::parse(x),
                        v, node)
        }
        else if exp[0] == "next" {
            if exp.len() == 2 {
                SrcKind::Next(exp.pop().unwrap())
            }
            else { panic!("ERROR: Uneven NEXT Logic {:?}",exp) }
        }
        else {
            let keys = exp.remove(0);
            let mut keys: Vec<&str> = keys.split_terminator(':').collect();

            if keys.len() < 2 { // regular logic
                SrcKind::Logic(keys.pop().unwrap().to_owned(),
                               LogicKind::parse(exp))
            }
            else { // composite type
                let kind = ExpectKind::parse(keys.pop().unwrap().to_owned());
                match kind { // only formal expected types allowed
                    ExpectKind::Ref(_) => { panic!("ERROR: Informal ExpectKind found {:?}", kind) },
                    _ => {}
                }
                SrcKind::Composite(keys.pop().unwrap().to_owned(),
                                   kind,
                                   exp)
            }
        }
    }
}

/// delimited by new line
/// should resolve to boolean
#[derive(Debug,PartialEq)]
pub enum LogicKind {
    GT(VarKind,VarKind), // weight > 1
    LT(VarKind,VarKind),

    //boolean checks
    Is(String),
    IsNot(String),
}

impl LogicKind {
    pub fn parse(mut exp: Vec<String>) -> LogicKind {
        let len = exp.len();

        if len == 1 {
            let mut exp = exp.pop().unwrap();
            let inv = exp.remove(0);
            if inv == '!' {
                LogicKind::IsNot(exp)
            }
            else {
                exp.insert(0,inv);
                LogicKind::Is(exp)
            }
        }
        else if len == 3 {
            let var = exp.pop().unwrap();
            let var = VarKind::parse(var);

            let sym = exp.pop().unwrap();
            let key = exp.pop().unwrap();
            let key = VarKind::parse(key);

            if sym == ">" {
                LogicKind::GT(key,var)
            }
            else if sym == "<" {
                LogicKind::LT(key,var)
            }
            else { panic!("ERROR: Invalid LogicKind Syntax") }
        }
        else { panic!("ERROR: Unbalanced LogicKind Syntax ({:?})",exp) }
    }
}

#[derive(Debug,PartialEq, Clone)]
pub enum VarKind {
    String(String),
    Num(f32),
    Bool(bool),
}

impl ToString for VarKind {
    fn to_string(&self) -> String {
        match self {
            &VarKind::String(ref s) => s.clone(),
            &VarKind::Num(ref n) => n.to_string(),
            &VarKind::Bool(ref b) => b.to_string(),
        }
    }
}

impl From<bool> for VarKind {
    fn from(t:bool) -> VarKind {
        VarKind::Bool(t)
    }
}
impl From<f32> for VarKind {
    fn from(t:f32) -> VarKind {
        VarKind::Num(t)
    }
}
impl From<String> for VarKind {
    fn from(t:String) -> VarKind {
        VarKind::String(t)
    }
}
impl<'a> From<&'a str> for VarKind {
    fn from(t:&str) -> VarKind {
        VarKind::String(t.to_owned())
    }
}

impl VarKind {
    pub fn parse(t: String) -> VarKind {
        let val;

        if let Ok(v) = t.parse::<f32>() {
            val = VarKind::Num(v);
        }
        else if let Ok(v) = t.parse::<bool>() {
            val = VarKind::Bool(v);
        }
        else { val = VarKind::String(t) }

        val
    }

    pub fn get_num<D:Eval> (&self, data: &D) -> Result<f32,&'static str> {
        let num;
        match self {
            &VarKind::Num(n) => { num = n; },
            &VarKind::String(ref s) => {
                if let Some(n) = data.eval(s) {
                    match n {
                        VarKind::Num(n) => { num = n; },
                        _ => return Err("ERROR: NaN Evaluation")
                    }
                }
                else {  return Err("ERROR: Empty Evaluation") }
            },
            _ =>  return Err("ERROR: NaN Evaluation")
        }

        return Ok(num)
    }
}

pub struct Parser(Vec<BlockKind>);

use std::ops::Deref;
impl Deref for Parser {
    type Target = Vec<BlockKind>;
    fn deref(&self) -> &Self::Target { &self.0 }
}

impl Parser {
    pub fn parse_blocks (src: &str) -> Parser {
        let mut v = vec!();
        let mut exp = String::new();
        let mut exps: Vec<String> = vec!();
        let mut block: Option<BlockKind> = None;

        let mut in_string = false;
        let mut in_comment = false;
        let mut in_vec = false;

        for c in src.chars() {
            if c == '[' { in_vec = true; continue }
            else if c == ']' { in_vec = false; }
            else if c == '#' && !in_string { in_comment = true; }
            else if  c == '\n' && in_comment && !in_string {
                in_comment = false;
                continue;
            }

            if c == '\n' && in_vec { continue }

            if (c == ']' ||
                c == '#' ||
                c == '\n')
                && !in_string
            {
                for n in exp.split_whitespace() {
                    exps.push(n.trim().to_owned());
                }
                exp = String::new();

                if exps.len() < 1 { continue }

                // determine block type
                if block.is_none() {
                    let name = exps.pop().unwrap();

                    if name == "def" {
                        let b = DefBlock {
                            name: exps.pop().unwrap(),
                            defs: vec!()
                        };

                        block = Some(BlockKind::Def(b));
                    }
                    else {
                        let b = SrcBlock {
                            name: name,
                            src: vec!()
                        };

                        block = Some(BlockKind::Src(b));
                    }
                }
                else { // build block type
                    let mut qsyms = vec!();
                    for n in exps.iter_mut() {
                        if n.chars().next().expect("ERROR: Empty QSYM") == '\'' {
                            let mut qsym = "__".to_owned();
                            let sym = n[1..].trim().to_owned();
                            qsym.push_str(&random::<u16>().to_string());

                            qsyms.push(qsym.clone());
                            qsyms.push(sym);
                            *n = qsym;
                        }
                    }

                    match block {
                        Some(BlockKind::Def(ref mut b)) => {
                            b.defs.push((exps[0].to_owned(),
                                         VarKind::parse(exps[1].to_owned())));
                        },
                        Some(BlockKind::Src(ref mut b)) => {
                            //println!("EXPS{:?}",exps); //DEBUG
                            if qsyms.len() > 1 {
                                b.src.push(SrcKind::parse(qsyms));
                            }

                            b.src.push(SrcKind::parse(exps));
                        },
                        _ => {}
                    }

                    exps = vec!();
                }
            }
            else if c == '"' && !in_comment {
                in_string = !in_string;
                if in_string {
                    for n in exp.split_whitespace() {
                        exps.push(n.trim().to_owned());
                    }
                    exp = String::new();
                }
                else if !in_string {
                    exps.push(exp);
                    exp = String::new();
                }
            }
            else if c == ';' && !in_string && !in_comment {
                //fail otherwise, block should be built!
                v.push(block.unwrap());
                block = None;
            }
            else {
                if !in_comment {
                    exp.push(c);
                }
            }
        }

        Parser(v)
    }

    pub fn into_env (mut self) -> Env {
        let mut src = HashMap::new();
        let mut def = HashMap::new();

        for b in self.0.drain(..) {
            match b {
                BlockKind::Def(db) => {
                    def.insert(db.name.clone(), db);
                },
                BlockKind::Src(sb) => {
                    src.insert(sb.name.clone(), sb);
                },
            }

        }

        Env { def: def, src: src }
    }
}

pub struct Env {
    pub def: HashMap<String, DefBlock>,
    pub src: HashMap<String, SrcBlock>
}
<commit_msg>add emit<commit_after>use rand::random;
use std::collections::HashMap;

use eval::Eval;

#[derive(Debug,PartialEq)]
pub struct SrcBlock {
    pub name: String,
    pub src: Vec<SrcKind>
}

#[derive(Debug,PartialEq)]
pub struct DefBlock {
    pub name: String,
    pub defs: Vec<(String,VarKind)>
}

#[derive(Debug,PartialEq)]
pub enum BlockKind {
    Src(SrcBlock),
    Def(DefBlock),
}

/// delimited by new line
#[derive(Debug,PartialEq)]
pub enum SrcKind {
    Logic(String, LogicKind), // ex: item_logic has_item

    // references logic in env and emits varkinds;
    // logic must resolve to true
    // ex: if item_logic give_quest
    // Can optionally end execution and begin next node
    If(ExpectKind, Vec<VarKind>, Option<String>),

    Emit(Vec<VarKind>), //just emits variables

    Composite(String,ExpectKind,Vec<String>),
    Next(String), // ends execution and begins next node
}

#[derive(Debug,PartialEq)]
pub enum ExpectKind {
    All,
    Any,
    None,

    Ref(String) // references env variable set from logic
}
impl ExpectKind {
    pub fn parse(s: String) -> ExpectKind {
        match &s[..] {
            "all" => ExpectKind::All,
            "any" => ExpectKind::Any,
            "none" => ExpectKind::None,
            _ => ExpectKind::Ref(s),
        }
    }
}

impl SrcKind {
    pub fn eval<D:Eval> (&self, state: &mut HashMap<String,bool>, data: &D)
                     -> (Vec<VarKind>,Option<String>)
    {
        match self {
            &SrcKind::Next(ref node) => {
                return (vec![],Some(node.clone()))
            },
            &SrcKind::Emit(ref vars) => {
                return (vars.clone(),None)
            },
            &SrcKind::Logic(ref name, ref logic) => { //logic updates state
                let name = name.clone();
                match logic {
                    &LogicKind::Is(ref lookup) => {
                        let r = data.eval(&lookup);
                        if r.is_some() {
                            match r.unwrap() {
                                VarKind::Bool(v) => { state.insert(name,v); },
                                _ => { state.insert(name,true); }, //if exists?
                            }
                        }
                    },
                    &LogicKind::IsNot(ref lookup) => { //inverse state
                        let r = data.eval(&lookup);
                        if r.is_some() {
                            match r.unwrap() {
                                VarKind::Bool(v) => {
                                    if !v { state.insert(name,true); }
                                },
                                _ => { state.insert(name,false); },
                            }
                        }
                    },

                    &LogicKind::GT(ref left, ref right) => {
                        let right = VarKind::get_num::<D>(right,data);
                        let left = VarKind::get_num::<D>(left,data);

                        if left.is_ok() && right.is_ok() {
                            state.insert(name, left.unwrap() > right.unwrap());
                        }
                    },
                    &LogicKind::LT(ref left, ref right) => {
                        let right = VarKind::get_num::<D>(right,data);
                        let left = VarKind::get_num::<D>(left,data);

                        if left.is_ok() && right.is_ok() {
                            state.insert(name, left.unwrap() < right.unwrap());
                        }
                    },
                }

                return (vec![],None) // logic does not return anything
            },
            &SrcKind::Composite(ref name, ref x, ref lookups) => {
                let mut comp_value = false;
                match x {
                    &ExpectKind::All => { // all must pass as true
                        for lookup in lookups.iter() {
                            let val = state.get(lookup);
                            if val.is_some() && *val.unwrap() {
                                comp_value = true;
                            }
                            else { comp_value = false; break }
                        }

                        state.insert(name.clone(),comp_value);
                    },
                    &ExpectKind::Any => { // first truth passes for set
                        for lookup in lookups.iter() {
                            let val = state.get(lookup);
                            if val.is_some() && *val.unwrap() {
                                comp_value = true;
                                break;
                            }
                        }

                        state.insert(name.clone(),comp_value);
                    },
                    &ExpectKind::None => { // inverse of any, none must be true
                        for lookup in lookups.iter() {
                            let val = state.get(lookup);
                            if val.is_some() && *val.unwrap() {
                                comp_value = false;
                                break;
                            }
                        }

                        state.insert(name.clone(),comp_value);
                    },
                    &ExpectKind::Ref(_) => panic!("ERROR: Unexpected parsing") // this should never hit
                }

                return (vec![],None) // composite does not return anything
            },
            &SrcKind::If(ref x, ref v, ref node) => {
                let mut if_value = false;
                match x {
                    &ExpectKind::All => {
                        for n in state.values() {
                            if !n { if_value = false; break }
                            else { if_value = true; }
                        }
                    },
                    &ExpectKind::Any => {
                        for n in state.values() {
                            if *n { if_value = true; break }
                        }
                    },
                    &ExpectKind::None => {
                        for n in state.values() {
                            if !n { if_value = true; }
                            else { if_value = true; break }
                        }
                    },
                    &ExpectKind::Ref(ref lookup) => {
                        let val = state.get(lookup);
                        if let Some(val) = val {
                            if_value = *val;
                        }
                    },
                }

                if if_value { return ((*v).clone(),node.clone()) }
                else { return (vec![],None) }
            }
        }
    }

    pub fn parse(mut exp: Vec<String>) -> SrcKind {
        if exp[0] == "if" {
            if exp.len() < 3 { panic!("ERROR: Invalid IF Logic {:?}",exp) }

            let x = exp.remove(1);

            let mut node = None;
            if exp.len() > 2 {
                let next = &exp[exp.len() - 2] == "next";
                if next {
                    node = exp.pop();
                    let _ = exp.pop(); // remove next tag
                }
            }

            let v = exp.drain(1..).map(|n| VarKind::parse(n)).collect();
            SrcKind::If(ExpectKind::parse(x),
                        v, node)
        }
        else if exp[0] == "next" {
            if exp.len() == 2 {
                SrcKind::Next(exp.pop().unwrap())
            }
            else { panic!("ERROR: Uneven NEXT Logic {:?}",exp) }
        }
        else if exp[0] == "emit" {
            if exp.len() > 1 {
                let mut v = vec![];
                for e in exp.drain(1..) {
                    v.push(VarKind::parse(e));
                }

                SrcKind::Emit(v)
            }
            else { panic!("ERROR: Missing EMIT Logic {:?}",exp) }
        }
        else {
            let keys = exp.remove(0);
            let mut keys: Vec<&str> = keys.split_terminator(':').collect();

            if keys.len() < 2 { // regular logic
                SrcKind::Logic(keys.pop().unwrap().to_owned(),
                               LogicKind::parse(exp))
            }
            else { // composite type
                let kind = ExpectKind::parse(keys.pop().unwrap().to_owned());
                match kind { // only formal expected types allowed
                    ExpectKind::Ref(_) => { panic!("ERROR: Informal ExpectKind found {:?}", kind) },
                    _ => {}
                }
                SrcKind::Composite(keys.pop().unwrap().to_owned(),
                                   kind,
                                   exp)
            }
        }
    }
}

/// delimited by new line
/// should resolve to boolean
#[derive(Debug,PartialEq)]
pub enum LogicKind {
    GT(VarKind,VarKind), // weight > 1
    LT(VarKind,VarKind),

    //boolean checks
    Is(String),
    IsNot(String),
}

impl LogicKind {
    pub fn parse(mut exp: Vec<String>) -> LogicKind {
        let len = exp.len();

        if len == 1 {
            let mut exp = exp.pop().unwrap();
            let inv = exp.remove(0);
            if inv == '!' {
                LogicKind::IsNot(exp)
            }
            else {
                exp.insert(0,inv);
                LogicKind::Is(exp)
            }
        }
        else if len == 3 {
            let var = exp.pop().unwrap();
            let var = VarKind::parse(var);

            let sym = exp.pop().unwrap();
            let key = exp.pop().unwrap();
            let key = VarKind::parse(key);

            if sym == ">" {
                LogicKind::GT(key,var)
            }
            else if sym == "<" {
                LogicKind::LT(key,var)
            }
            else { panic!("ERROR: Invalid LogicKind Syntax") }
        }
        else { panic!("ERROR: Unbalanced LogicKind Syntax ({:?})",exp) }
    }
}

#[derive(Debug,PartialEq, Clone)]
pub enum VarKind {
    String(String),
    Num(f32),
    Bool(bool),
}

impl ToString for VarKind {
    fn to_string(&self) -> String {
        match self {
            &VarKind::String(ref s) => s.clone(),
            &VarKind::Num(ref n) => n.to_string(),
            &VarKind::Bool(ref b) => b.to_string(),
        }
    }
}

impl From<bool> for VarKind {
    fn from(t:bool) -> VarKind {
        VarKind::Bool(t)
    }
}
impl From<f32> for VarKind {
    fn from(t:f32) -> VarKind {
        VarKind::Num(t)
    }
}
impl From<String> for VarKind {
    fn from(t:String) -> VarKind {
        VarKind::String(t)
    }
}
impl<'a> From<&'a str> for VarKind {
    fn from(t:&str) -> VarKind {
        VarKind::String(t.to_owned())
    }
}

impl VarKind {
    pub fn parse(t: String) -> VarKind {
        let val;

        if let Ok(v) = t.parse::<f32>() {
            val = VarKind::Num(v);
        }
        else if let Ok(v) = t.parse::<bool>() {
            val = VarKind::Bool(v);
        }
        else { val = VarKind::String(t) }

        val
    }

    pub fn get_num<D:Eval> (&self, data: &D) -> Result<f32,&'static str> {
        let num;
        match self {
            &VarKind::Num(n) => { num = n; },
            &VarKind::String(ref s) => {
                if let Some(n) = data.eval(s) {
                    match n {
                        VarKind::Num(n) => { num = n; },
                        _ => return Err("ERROR: NaN Evaluation")
                    }
                }
                else {  return Err("ERROR: Empty Evaluation") }
            },
            _ =>  return Err("ERROR: NaN Evaluation")
        }

        return Ok(num)
    }
}

pub struct Parser(Vec<BlockKind>);

use std::ops::Deref;
impl Deref for Parser {
    type Target = Vec<BlockKind>;
    fn deref(&self) -> &Self::Target { &self.0 }
}

impl Parser {
    pub fn parse_blocks (src: &str) -> Parser {
        let mut v = vec!();
        let mut exp = String::new();
        let mut exps: Vec<String> = vec!();
        let mut block: Option<BlockKind> = None;

        let mut in_string = false;
        let mut in_comment = false;
        let mut in_vec = false;

        for c in src.chars() {
            if c == '[' { in_vec = true; continue }
            else if c == ']' { in_vec = false; }
            else if c == '#' && !in_string { in_comment = true; }
            else if  c == '\n' && in_comment && !in_string {
                in_comment = false;
                continue;
            }

            if c == '\n' && in_vec { continue }

            if (c == ']' ||
                c == '#' ||
                c == '\n')
                && !in_string
            {
                for n in exp.split_whitespace() {
                    exps.push(n.trim().to_owned());
                }
                exp = String::new();

                if exps.len() < 1 { continue }

                // determine block type
                if block.is_none() {
                    let name = exps.pop().unwrap();

                    if name == "def" {
                        let b = DefBlock {
                            name: exps.pop().unwrap(),
                            defs: vec!()
                        };

                        block = Some(BlockKind::Def(b));
                    }
                    else {
                        let b = SrcBlock {
                            name: name,
                            src: vec!()
                        };

                        block = Some(BlockKind::Src(b));
                    }
                }
                else { // build block type
                    let mut qsyms = vec!();
                    for n in exps.iter_mut() {
                        if n.chars().next().expect("ERROR: Empty QSYM") == '\'' {
                            let mut qsym = "__".to_owned();
                            let sym = n[1..].trim().to_owned();
                            qsym.push_str(&random::<u16>().to_string());

                            qsyms.push(qsym.clone());
                            qsyms.push(sym);
                            *n = qsym;
                        }
                    }

                    match block {
                        Some(BlockKind::Def(ref mut b)) => {
                            b.defs.push((exps[0].to_owned(),
                                         VarKind::parse(exps[1].to_owned())));
                        },
                        Some(BlockKind::Src(ref mut b)) => {
                            //println!("EXPS{:?}",exps); //DEBUG
                            if qsyms.len() > 1 {
                                b.src.push(SrcKind::parse(qsyms));
                            }

                            b.src.push(SrcKind::parse(exps));
                        },
                        _ => {}
                    }

                    exps = vec!();
                }
            }
            else if c == '"' && !in_comment {
                in_string = !in_string;
                if in_string {
                    for n in exp.split_whitespace() {
                        exps.push(n.trim().to_owned());
                    }
                    exp = String::new();
                }
                else if !in_string {
                    exps.push(exp);
                    exp = String::new();
                }
            }
            else if c == ';' && !in_string && !in_comment {
                //fail otherwise, block should be built!
                v.push(block.unwrap());
                block = None;
            }
            else {
                if !in_comment {
                    exp.push(c);
                }
            }
        }

        Parser(v)
    }

    pub fn into_env (mut self) -> Env {
        let mut src = HashMap::new();
        let mut def = HashMap::new();

        for b in self.0.drain(..) {
            match b {
                BlockKind::Def(db) => {
                    def.insert(db.name.clone(), db);
                },
                BlockKind::Src(sb) => {
                    src.insert(sb.name.clone(), sb);
                },
            }

        }

        Env { def: def, src: src }
    }
}

pub struct Env {
    pub def: HashMap<String, DefBlock>,
    pub src: HashMap<String, SrcBlock>
}
<|endoftext|>