<commit_before>//#![feature(trace_macros)]
#![feature(test)]
extern crate test;

#[macro_use]
extern crate nom;

use nom::{digit, is_alphanumeric, alphanumeric, recognize_float};

use test::Bencher;

use std::str::{self, FromStr, from_utf8};
use std::collections::HashMap;

#[derive(Debug, PartialEq)]
pub enum JsonValue {
  Str(String),
  Num(f32),
  Array(Vec<JsonValue>),
  Object(HashMap<String, JsonValue>),
}

named!(float<f32>,
  flat_map!(recognize_float, parse_to!(f32))
);

//FIXME: verify how json strings are formatted
named!(string<&str>,
  delimited!(
    char!('\"'),
    map_res!(escaped!(call!(alphanumeric), '\\', one_of!("\"n\\")), str::from_utf8),
    //map_res!(escaped!(take_while1!(is_alphanumeric), '\\', one_of!("\"n\\")), str::from_utf8),
    char!('\"')
  )
);

named!(array < Vec<JsonValue> >,
  ws!(
    delimited!(
      char!('['),
      separated_list!(char!(','), value),
      char!(']')
    )
  )
);

named!(key_value<(&str,JsonValue)>,
  ws!(
    separated_pair!(
      string,
      char!(':'),
      value
    )
  )
);

named!(hash< HashMap<String,JsonValue> >,
  ws!(
    map!(
      delimited!(
        char!('{'),
        separated_list!(char!(','), key_value),
        char!('}')
        ),
      |tuple_vec| {
        tuple_vec.into_iter().map(|(k,v)| (String::from(k), v)).collect()
        /*let mut h: HashMap<String, JsonValue> = HashMap::new();
        for (k, v) in tuple_vec {
          h.insert(String::from(k), v);
        }
        h*/
      }
    )
  )
);

named!(value<JsonValue>,
  ws!(
    alt!(
      hash   => { |h|   JsonValue::Object(h)            } |
      array  => { |v|   JsonValue::Array(v)             } |
      string => { |s|   JsonValue::Str(String::from(s)) } |
      float  => { |num| JsonValue::Num(num)             }
    )
  )
);

#[bench]
fn json_bench(b: &mut Bencher) {
  let data = &b"  { \"a\"\t: 42,
  \"b\": [ \"x\", \"y\", 12 ] ,
  \"c\": { \"hello\" : \"world\"
  }
  }  \0";

  //println!("data:\n{:?}", value(&data[..]));
  b.iter(|| value(&data[..]));
}

#[bench]
fn recognize_float_bytes(b: &mut Bencher) {
  use nom::recognize_float;
  b.iter(|| recognize_float(&b"-1.234E-12"[..]));
}

#[bench]
fn recognize_float_str(b: &mut Bencher) {
  use nom::recognize_float;
  b.iter(|| recognize_float("-1.234E-12"));
}

#[bench]
fn float_bytes(b: &mut Bencher) {
  use nom::float;
  b.iter(|| float(&b"-1.234E-12"[..]));
}

#[bench]
fn float_str(b: &mut Bencher) {
  use nom::float_s;
  b.iter(|| float_s("-1.234E-12"));
}
<commit_msg>remove some warnings<commit_after>//#![feature(trace_macros)]
#![feature(test)]
extern crate test;

#[macro_use]
extern crate nom;

use nom::{alphanumeric, recognize_float};

use test::Bencher;

use std::str;
use std::collections::HashMap;

#[derive(Debug, PartialEq)]
pub enum JsonValue {
  Str(String),
  Num(f32),
  Array(Vec<JsonValue>),
  Object(HashMap<String, JsonValue>),
}

named!(float<f32>,
  flat_map!(recognize_float, parse_to!(f32))
);

//FIXME: verify how json strings are formatted
named!(string<&str>,
  delimited!(
    char!('\"'),
    map_res!(escaped!(call!(alphanumeric), '\\', one_of!("\"n\\")), str::from_utf8),
    //map_res!(escaped!(take_while1!(is_alphanumeric), '\\', one_of!("\"n\\")), str::from_utf8),
    char!('\"')
  )
);

named!(array < Vec<JsonValue> >,
  ws!(
    delimited!(
      char!('['),
      separated_list!(char!(','), value),
      char!(']')
    )
  )
);

named!(key_value<(&str,JsonValue)>,
  ws!(
    separated_pair!(
      string,
      char!(':'),
      value
    )
  )
);

named!(hash< HashMap<String,JsonValue> >,
  ws!(
    map!(
      delimited!(
        char!('{'),
        separated_list!(char!(','), key_value),
        char!('}')
        ),
      |tuple_vec| {
        tuple_vec.into_iter().map(|(k,v)| (String::from(k), v)).collect()
        /*let mut h: HashMap<String, JsonValue> = HashMap::new();
        for (k, v) in tuple_vec {
          h.insert(String::from(k), v);
        }
        h*/
      }
    )
  )
);

named!(value<JsonValue>,
  ws!(
    alt!(
      hash   => { |h|   JsonValue::Object(h)            } |
      array  => { |v|   JsonValue::Array(v)             } |
      string => { |s|   JsonValue::Str(String::from(s)) } |
      float  => { |num| JsonValue::Num(num)             }
    )
  )
);

#[bench]
fn json_bench(b: &mut Bencher) {
  let data = &b"  { \"a\"\t: 42,
  \"b\": [ \"x\", \"y\", 12 ] ,
  \"c\": { \"hello\" : \"world\"
  }
  }  \0";

  //println!("data:\n{:?}", value(&data[..]));
  b.iter(|| value(&data[..]));
}

#[bench]
fn recognize_float_bytes(b: &mut Bencher) {
  use nom::recognize_float;
  b.iter(|| recognize_float(&b"-1.234E-12"[..]));
}

#[bench]
fn recognize_float_str(b: &mut Bencher) {
  use nom::recognize_float;
  b.iter(|| recognize_float("-1.234E-12"));
}

#[bench]
fn float_bytes(b: &mut Bencher) {
  use nom::float;
  b.iter(|| float(&b"-1.234E-12"[..]));
}

#[bench]
fn float_str(b: &mut Bencher) {
  use nom::float_s;
  b.iter(|| float_s("-1.234E-12"));
}
<|endoftext|>


<commit_before>mod abbreviation;
mod bold;
mod citation;
mod code;
mod image;
mod italic;
mod link;
mod strikethrough;
mod subscript;
mod superscript;
mod underlined;

use parser::inline::abbreviation::parse_abbreviation;
use parser::inline::bold::parse_bold_text;
use parser::inline::italic::parse_italic_text;
use parser::inline::strikethrough::parse_strikethrough_text;
use parser::inline::underlined::parse_underlined_text;
use parser::inline::subscript::parse_subscript_text;
use parser::inline::superscript::parse_superscript_text;
use parser::inline::code::parse_code;
use parser::inline::citation::parse_citation;
use parser::inline::image::parse_image;
use parser::inline::link::parse_link;
use parser::Inline;

pub fn parse_inline_elements(text: &str) -> Vec<Inline> {
    let lines = text.lines().collect::<Vec<&str>>();
    let mut tokens = Vec::new();

    for (idx, line) in lines.iter().enumerate() {
        let mut tmp = String::new();
        let mut i = 0;

        while i < line.len() {
            match parse_inline_element(&line[i..line.len()]) {
                Some((span, consumed_chars)) => {
                    if !tmp.is_empty() {
                        tokens.push(Inline::Text(tmp));
                    }
                    tokens.push(span);
                    tmp = String::new();
                    i += consumed_chars;
                }
                None => {
                    tmp.push_str(&line[i..i + 1]);
                    i += 1;
                }
            }
        }
        if !tmp.is_empty() {
            tokens.push(Inline::Text(tmp));
        }
        if idx > 0 && idx < lines.len() - 1 {
            tokens.push(Inline::Break);
        }
    }

    tokens
}

fn parse_inline_element(text: &str) -> Option<(Inline, usize)> {
    pipe_opt!(
        text
        => parse_bold_text
        => parse_italic_text
        => parse_strikethrough_text
        => parse_underlined_text
        => parse_subscript_text
        => parse_superscript_text
        => parse_abbreviation
        => parse_code
        => parse_citation
        => parse_image
        => parse_link
    )
}
<commit_msg>Fix adding line break between lines in inline elements parser<commit_after>mod abbreviation;
mod bold;
mod citation;
mod code;
mod image;
mod italic;
mod link;
mod strikethrough;
mod subscript;
mod superscript;
mod underlined;

use parser::inline::abbreviation::parse_abbreviation;
use parser::inline::bold::parse_bold_text;
use parser::inline::italic::parse_italic_text;
use parser::inline::strikethrough::parse_strikethrough_text;
use parser::inline::underlined::parse_underlined_text;
use parser::inline::subscript::parse_subscript_text;
use parser::inline::superscript::parse_superscript_text;
use parser::inline::code::parse_code;
use parser::inline::citation::parse_citation;
use parser::inline::image::parse_image;
use parser::inline::link::parse_link;
use parser::Inline;

pub fn parse_inline_elements(text: &str) -> Vec<Inline> {
    let lines = text.lines().collect::<Vec<&str>>();
    let mut tokens = Vec::new();

    for (idx, line) in lines.iter().enumerate() {
        let mut tmp = String::new();
        let mut i = 0;

        while i < line.len() {
            match parse_inline_element(&line[i..line.len()]) {
                Some((span, consumed_chars)) => {
                    if !tmp.is_empty() {
                        tokens.push(Inline::Text(tmp));
                    }
                    tokens.push(span);
                    tmp = String::new();
                    i += consumed_chars;
                }
                None => {
                    tmp.push_str(&line[i..i + 1]);
                    i += 1;
                }
            }
        }
        if !tmp.is_empty() {
            tokens.push(Inline::Text(tmp));
        }
        if idx < lines.len() - 1 {
            tokens.push(Inline::Break);
        }
    }

    tokens
}

fn parse_inline_element(text: &str) -> Option<(Inline, usize)> {
    pipe_opt!(
        text
        => parse_bold_text
        => parse_italic_text
        => parse_strikethrough_text
        => parse_underlined_text
        => parse_subscript_text
        => parse_superscript_text
        => parse_abbreviation
        => parse_code
        => parse_citation
        => parse_image
        => parse_link
    )
}
<|endoftext|>


<commit_before>// Copyright 2014 Alexis Mousset. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Simple email (very incomplete)

use std::fmt::{Show, Formatter, Result};

use time::{now, Tm};

use email::header::{ToHeader, Header};
use email::address::ToAddress;
use common::CRLF;

pub mod header;
pub mod address;

/// Simple email representation
pub struct Email {
    /// Array of headers
    headers: Vec<Header>,
    /// Message body
    body: String,
    /// The enveloppe recipients addresses
    to: Vec<String>,
    /// The enveloppe sender address
    from: Option<String>,
}

impl Show for Email {
    fn fmt(&self, f: &mut Formatter) -> Result {
        let mut formatted_headers = String::new();
        for header in self.headers.iter() {
            formatted_headers.push_str(header.to_string().as_slice());
            formatted_headers.push_str(CRLF);
        }
        f.write(format!("{}{}{}", formatted_headers, CRLF, self.body).as_bytes())
    }
}

impl Email {
    /// Creates a new empty email
    pub fn new() -> Email {
        Email{headers: vec!(), body: "".to_string(), to: vec!(), from: None}
    }

    /// Clear the email content
    pub fn clear(&mut self) {
        self.headers.clear();
        self.body = "".to_string();
        self.to.clear();
        self.from = None;
    }

    /// Return the to addresses, and fails if it is not set
    pub fn get_to<'a>(&'a self) -> Vec<String> {
        if self.to.is_empty() {
            panic!("The To field is empty")
        }
        self.to.clone()
    }

    /// Return the from address, and fails if it is not set
    pub fn get_from(&self) -> String {
        match self.from {
            Some(ref from_address) => from_address.clone(),
            None => panic!("The From field is empty"),
        }
    }

    /// Sets the email body
    pub fn body(&mut self, body: &str) {
        self.body = body.to_string();
    }

    /// Add a generic header
    pub fn add_header<A: ToHeader>(&mut self, header: A) {
        self.headers.push(header.to_header());
    }

    /// Adds a From header and store the sender address
    pub fn from<A: ToAddress>(&mut self, address: A) {
        self.from = Some(address.to_address().get_address());
        self.headers.push(
            Header::new("From", address.to_address().to_string().as_slice())
        );
    }

    /// Adds a To header and store the recipient address
    pub fn to<A: ToAddress>(&mut self, address: A) {
        self.to.push(address.to_address().get_address());
        self.headers.push(
            Header::new("To", address.to_address().to_string().as_slice())
        );
    }

    /// Adds a Cc header and store the recipient address
    pub fn cc<A: ToAddress>(&mut self, address: A) {
        self.to.push(address.to_address().get_address());
        self.headers.push(
            Header::new("Cc", address.to_address().to_string().as_slice())
        );
    }

    /// Adds a Reply-To header
    pub fn reply_to<A: ToAddress>(&mut self, address: A) {
        self.headers.push(
            Header::new("Return-Path", address.to_address().to_string().as_slice())
        );
    }

    /// Adds a Subject header
    pub fn subject(&mut self, subject: &str) {
        self.headers.push(
            Header::new("Subject", subject)
        );
    }

    /// Adds a Date header with the current time
    pub fn date(&mut self) {
        self.headers.push(
            Header::new("Date", Tm::rfc822(&now()).to_string().as_slice())
        );
    }
}
<commit_msg>First tests on email<commit_after>// Copyright 2014 Alexis Mousset. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Simple email (very incomplete)

use std::fmt::{Show, Formatter, Result};

use time::{now, Tm};

use email::header::{ToHeader, Header};
use email::address::ToAddress;
use common::CRLF;

pub mod header;
pub mod address;

/// Simple email representation
#[deriving(PartialEq,Eq,Clone)]
pub struct Email {
    /// Array of headers
    headers: Vec<Header>,
    /// Message body
    body: String,
    /// The enveloppe recipients addresses
    to: Vec<String>,
    /// The enveloppe sender address
    from: Option<String>,
}

impl Show for Email {
    fn fmt(&self, f: &mut Formatter) -> Result {
        let mut formatted_headers = String::new();
        for header in self.headers.iter() {
            formatted_headers.push_str(header.to_string().as_slice());
            formatted_headers.push_str(CRLF);
        }
        f.write(format!("{}{}{}", formatted_headers, CRLF, self.body).as_bytes())
    }
}

impl Email {
    /// Creates a new empty email
    pub fn new() -> Email {
        Email{headers: vec!(), body: "".to_string(), to: vec!(), from: None}
    }

    /// Clear the email content
    pub fn clear(&mut self) {
        self.headers.clear();
        self.body = "".to_string();
        self.to.clear();
        self.from = None;
    }

    /// Return the to addresses, and fails if it is not set
    pub fn get_to<'a>(&'a self) -> Vec<String> {
        if self.to.is_empty() {
            panic!("The To field is empty")
        }
        self.to.clone()
    }

    /// Return the from address, and fails if it is not set
    pub fn get_from(&self) -> String {
        match self.from {
            Some(ref from_address) => from_address.clone(),
            None => panic!("The From field is empty"),
        }
    }

    /// Sets the email body
    pub fn body(&mut self, body: &str) {
        self.body = body.to_string();
    }

    /// Add a generic header
    pub fn add_header<A: ToHeader>(&mut self, header: A) {
        self.headers.push(header.to_header());
    }

    /// Adds a From header and store the sender address
    pub fn from<A: ToAddress>(&mut self, address: A) {
        self.from = Some(address.to_address().get_address());
        self.headers.push(
            Header::new("From", address.to_address().to_string().as_slice())
        );
    }

    /// Adds a To header and store the recipient address
    pub fn to<A: ToAddress>(&mut self, address: A) {
        self.to.push(address.to_address().get_address());
        self.headers.push(
            Header::new("To", address.to_address().to_string().as_slice())
        );
    }

    /// Adds a Cc header and store the recipient address
    pub fn cc<A: ToAddress>(&mut self, address: A) {
        self.to.push(address.to_address().get_address());
        self.headers.push(
            Header::new("Cc", address.to_address().to_string().as_slice())
        );
    }

    /// Adds a Reply-To header
    pub fn reply_to<A: ToAddress>(&mut self, address: A) {
        self.headers.push(
            Header::new("Return-Path", address.to_address().to_string().as_slice())
        );
    }

    /// Adds a Subject header
    pub fn subject(&mut self, subject: &str) {
        self.headers.push(
            Header::new("Subject", subject)
        );
    }

    /// Adds a Date header with the current time
    pub fn date(&mut self) {
        self.headers.push(
            Header::new("Date", Tm::rfc822(&now()).to_string().as_slice())
        );
    }
}

#[cfg(test)]
mod test {
    use super::Email;
    use email::header::Header;

    #[test]
    fn test_new() {
        assert_eq!(
            Email::new(),
            Email{headers: vec!(), body: "".to_string(), to: vec!(), from: None}
        )
    }

    #[test]
    fn test_body() {
        let mut email = Email::new();
        email.body("test message");
        assert_eq!(
            email,
            Email{headers: vec!(), body: "test message".to_string(), to: vec!(), from: None}
        )
    }

    #[test]
    fn test_add_header() {
        let mut email = Email::new();
        email.add_header(("X-My-Header", "value"));
        assert_eq!(
            email,
            Email{
                headers: vec!(Header::new("X-My-Header", "value")),
                body: "".to_string(),
                to: vec!(),
                from: None
            }
        )
        email.add_header(("X-My-Header-2", "value-2"));
        assert_eq!(
            email,
            Email{
                headers: vec!(Header::new("X-My-Header", "value"),
                Header::new("X-My-Header-2", "value-2")),
                body: "".to_string(),
                to: vec!(),
                from: None
            }
        )
    }
}
<|endoftext|>


<commit_before>use binary_encoding::{from_binary};
use lambda_encoding::{encode, decode};
use lambda_calculus::reduction::beta_full;
use self::Error::*;

/// An error that can occur during blc execution.
#[derive(Debug, PartialEq)]
pub enum Error {
    InvalidProgram
}

/// Executes a binary lambda calculus program, feeding it the given argument.
pub fn execute(blc_program: &[u8], blc_argument: &[u8]) -> Result<String, Error> {
    let program = from_binary(blc_program);
    if program.is_err() { return Err(InvalidProgram) }
    let calculation = beta_full(program.unwrap().app(encode(blc_argument))); // safe

    Ok(decode(calculation))
}

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

    #[test]
    fn inflating() {
        // program code from http://www.ioccc.org/2012/tromp/inflate.Blc
        let inflate = b"01000100010001000110100000010110000000010111100100011010000000000001011001\
            11111111111011110010111100111111011111011001011111101111101101000011110011110011100111\
            00111100111100111100001011011000001000000101100000101100000010110000011011000000";
        let s_compressed = [0x1u8, 0x7a, 0x74];

        assert_eq!(execute(&*inflate, &s_compressed[..]).unwrap(), "000000010111101001110100".to_owned());
    }

    #[test]
    fn deflating() {
        // program code from http://www.ioccc.org/2012/tromp/deflate.Blc
        let deflate = b"01000100011010000001011000000101011111100000000100010111000000001011111001\
            01010111111111111100000000110111000001100010111011001011000001101100001111100001111100\
            00101101110110000000010110011110000010010111111110111111101100010100100000111001110011\
            10100000011100111010000000";

        let s_blc = b"00000001011110100111010";

        assert_eq!(execute(&*deflate, &s_blc[..]).unwrap().as_bytes(), [0x1u8, 0x7a, 0x74]);
    }
}
<commit_msg>add a nice example for run<commit_after>use binary_encoding::{from_binary};
use lambda_encoding::{encode, decode};
use lambda_calculus::reduction::beta_full;
use self::Error::*;

/// An error that can occur during blc execution.
#[derive(Debug, PartialEq)]
pub enum Error {
    InvalidProgram
}

/// Executes a binary lambda calculus program, feeding it the given argument.
///
/// # Example
/// ```
/// use blc::execution::run;
///
/// let reverse = b"0001011001000110100000000001011100111110111100001011011110110000010";
///
/// assert_eq!(run(&*reverse, b"herp derp"), Ok("pred preh".into()));
/// ```
pub fn run(blc_program: &[u8], blc_argument: &[u8]) -> Result<String, Error> {
    let program = from_binary(blc_program);
    if program.is_err() { return Err(InvalidProgram) }
    let calculation = beta_full(program.unwrap().app(encode(blc_argument))); // safe

    Ok(decode(calculation))
}

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

    #[test]
    fn inflating() {
        // program code from http://www.ioccc.org/2012/tromp/inflate.Blc
        let inflate = b"01000100010001000110100000010110000000010111100100011010000000000001011001\
            11111111111011110010111100111111011111011001011111101111101101000011110011110011100111\
            00111100111100111100001011011000001000000101100000101100000010110000011011000000";
        let s_compressed = [0x1u8, 0x7a, 0x74];

        assert_eq!(run(&*inflate, &s_compressed[..]).unwrap(), "000000010111101001110100".to_owned());
    }
  /*
    #[test]
    fn deflating() {
        // program code from http://www.ioccc.org/2012/tromp/deflate.Blc
        let deflate = b"01000100011010000001011000000101011111100000000100010111000000001011111001\
            01010111111111111100000000110111000001100010111011001011000001101100001111100001111100\
            00101101110110000000010110011110000010010111111110111111101100010100100000111001110011\
            10100000011100111010000000";

        let s_blc = b"00000001011110100111010";

        assert_eq!(run(&*deflate, &s_blc[..]).unwrap().as_bytes(), [0x1u8, 0x7a, 0x74]);
    }*/
}
<|endoftext|>


<commit_before>pub mod ast;
pub mod rd_parser;

#[derive(PartialEq, Clone, Debug)]
pub struct Position {
    line: usize,
    col: usize,
}

impl Position {
    pub fn to_pair(&self) -> (usize, usize) {
        (self.line, self.col)
    }
}

impl Default for Position {
    fn default() -> Position {
        Position { line: 1, col: 1 }
    }
}
<commit_msg>Front: Add syntax specs for .gib files<commit_after>//! # The `.gib` Syntax
//!
//! Input files to Cleaver follow the grammar described here and are called gibs (singular: gib).
//! Expression written between slashes (`/`) are regular expressions (Javascript). Tokens are
//! written in double-quotes (`"`) and rules between angular brackets (`<`, `>`). Something between
//! brackets (`[`, `]`) is considered optional while something between braces (`{`, `}`) can occur
//! multiple times or not at all.
//!
//! ```text
//!     <identifier>        ::= /[A-Za-z][A-Za-z0-9_]*/
//!
//!     <bool_literal>      ::= "true" | "false"
//!
//!     <int_literal>       ::= /[0-9]+/
//!
//!     <float_literal>     ::= /[0-9]+\.[0-9]+/
//!
//!     <string_literal>    ::= /"[^"]"/
//!
//!     <type>              ::= "void" | "bool" | "int" | "float" | "string"
//!
//!     <un_op>             ::= "!" | "-"
//!
//!     <bin_op>            ::= "==" | "<" | "<=" | "+" | "-" | "*" | "/"
//!
//!     <variable>          ::= <identifier>
//!
//!     <expression>        ::= <bool_literal>
//!                           | <int_literal>
//!                           | <float_literal>
//!                           | <string_literal>
//!                           | <variable>
//!                           | "(" <expression> ")"
//!                           | <call_expression>
//!                           | <un_op> <expression>
//!                           | <expression> <bin_op> <expression>
//!
//!     <call_expression>   ::= <identifier> "(" [ <expression> { "," <expression> } ] ")"
//!
//!     <statement>         ::= <expression> ";"
//!                           | <declaration> ";"
//!                           | <assignment> ";"
//!                           | <if_statement>
//!                           | <while_statement>
//!                           | <return> ";"
//!                           | "{" { <statement } "}"
//!
//!     <declaration>       ::= <type> <variable>
//!
//!     <assignment>        ::= <variable> "=" <expression>
//!
//!     <if_statement>      ::= "if" "(" <expression> ")" <statement> [ "else" <statement> ]
//!
//!     <while_statement>   ::= "while" "(" <expression> ")" <statement>
//!
//!     <program>           ::= { <function> }
//!
//!     <function>          ::= <type> <identifier> "("
//!                                 [ <declaration> { "," <declaration> } ] ")" <statement>
//! ```

pub mod ast;
pub mod rd_parser;

#[derive(PartialEq, Clone, Debug)]
pub struct Position {
    line: usize,
    col: usize,
}

impl Position {
    pub fn to_pair(&self) -> (usize, usize) {
        (self.line, self.col)
    }
}

impl Default for Position {
    fn default() -> Position {
        Position { line: 1, col: 1 }
    }
}
<|endoftext|>


<commit_before>use std::io::File;
use std::io::fs::PathExtensions;
use std::collections::HashMap;
use calx::color;
use calx::Context;
use calx::Event;
use calx::Key;
use calx::{Fonter, V2};
use world;
use world::action;
use world::action::Input::{Step, Melee};
use world::action::ControlState::*;
use world::{Msg, FovStatus};
use world::Dir6;
use world::Dir6::*;
use world::{Entity};
use world::item::{Slot};
use worldview;
use sprite::{WorldSprites, GibSprite};
use tilecache;
use tilecache::icon;
use msg_queue::MsgQueue;

pub struct GameState {
    /// Transient effect sprites drawn in game world view.
    world_spr: WorldSprites,
    /// Counters for entities with flashing damage animation.
    damage_timers: HashMap<Entity, uint>,

    /// Flag for autoexploration.
    // TODO: Probably going to need a general "ongoing activity" system at
    // some point.
    exploring: bool,

    msg: MsgQueue,
    ui_state: UiState,
}

enum UiState {
    Gameplay,
    Inventory
}

impl GameState {
    pub fn new(seed: Option<u32>) -> GameState {
        world::init_world(seed);
        GameState {
            world_spr: WorldSprites::new(),
            damage_timers: HashMap::new(),
            exploring: false,
            msg: MsgQueue::new(),
            ui_state: UiState::Gameplay,
        }
    }

    fn draw_player_ui(&mut self, ctx: &mut Context, player: Entity) {
        let hp = player.hp();
        let max_hp = player.max_hp();

        // Draw heart containers.
        for i in range(0, (max_hp + 1) / 2) {
            let pos = V2(i as int * 8, 8);
            let idx = if hp >= (i + 1) * 2 { icon::HEART }
                else if hp == i * 2 + 1 { icon::HALF_HEART }
                else { icon::NO_HEART };
            ctx.draw_image(pos, 0.0, tilecache::get(idx), &color::FIREBRICK);
        }
    }

    fn base_paint(&mut self, ctx: &mut Context) {
        let camera = world::camera();
        worldview::draw_world(&camera, ctx, &self.damage_timers);

        self.world_spr.draw(|x| (camera + x).fov_status() == Some(FovStatus::Seen), &camera, ctx);
        self.world_spr.update();

        let location_name = camera.name();
        let _ = write!(&mut ctx.text_writer(V2(640 - location_name.len() as int * 8, 8), 0.1, color::LIGHTGRAY)
                       .set_border(color::BLACK),
                       "{}", location_name);

        self.msg.draw(ctx);
        if let Some(player) = action::player() {
            self.draw_player_ui(ctx, player);
        }

        let fps = 1.0 / ctx.render_duration;
        let _ = write!(&mut ctx.text_writer(V2(0, 16), 0.1, color::LIGHTGREEN)
                       .set_border(color::BLACK),
                       "FPS {:.0}", fps);
    }

    fn base_update(&mut self, ctx: &mut Context) {
        // Process events
        loop {
            match world::pop_msg() {
                Some(Msg::Gib(loc)) => {
                    self.world_spr.add(box GibSprite::new(loc));
                }
                Some(Msg::Damage(entity)) => {
                    self.damage_timers.insert(entity, 2);
                }
                Some(Msg::Text(txt)) => {
                    self.msg.msg(txt)
                }
                Some(Msg::Caption(txt)) => {
                    self.msg.caption(txt)
                }
                Some(x) => {
                    println!("Unhandled Msg type {}", x);
                }
                None => break
            }
        }

        self.base_paint(ctx);

        if action::control_state() == ReadyToUpdate {
            action::update();
        }

        if self.exploring {
            if action::control_state() == AwaitingInput {
                self.exploring = self.autoexplore();
            }
        }

        self.damage_timers = self.damage_timers.clone().into_iter()
            .filter(|&(_, t)| t > 0u)
            .map(|(e, t)| (e, t - 1))
            .collect();

        self.msg.update();
    }

    fn inventory_update(&mut self, ctx: &mut Context) {
        let player = action::player().unwrap();
        let mut cursor = ctx.text_writer(V2(0, 8), 0.1, color::GAINSBORO)
            .set_border(color::BLACK);
        for slot_data in SLOT_DATA.iter() {
            let name = match player.equipped(slot_data.slot) {
                Some(item) => item.name(),
                None => "".to_string()
            };
            let _ = write!(&mut cursor, "{}] {}: {}\n",
                slot_data.key, slot_data.name, name);
        }
    }

    /// Repaint view, update game world if needed.
    pub fn update(&mut self, ctx: &mut Context) {
        ctx.clear(&color::BLACK);

        match self.ui_state {
            UiState::Gameplay => self.base_update(ctx),
            UiState::Inventory => self.inventory_update(ctx),
        }
    }

    pub fn save_game(&self) {
        let save_data = world::save();
        let mut file = File::create(&Path::new("/tmp/magog_save.json"));
        file.write_str(save_data.as_slice()).unwrap();
    }

    pub fn load_game(&mut self) {
        let path = Path::new("/tmp/magog_save.json");
        if !path.exists() { return; }
        let save_data = File::open(&path).read_to_string().unwrap();
        // TODO: Handle failed load nicely.
        world::load(save_data.as_slice()).unwrap();
    }

    fn smart_move(&mut self, dir: Dir6) {
        let player = action::player().unwrap();
        let loc = player.location().unwrap();
        for &d in vec![dir, dir + 1, dir - 1].iter() {
            let target_loc = loc + d.to_v2();
            if target_loc.has_mobs() {
                action::input(Melee(d));
                return;
            } else if player.can_step(d) {
                action::input(Step(d));
                return;
            }
        }
    }

    fn autoexplore(&mut self) -> bool {
        let player = action::player().unwrap();
        if player.is_threatened() {
            return false;
        }
        if let Some(pathing) = action::autoexplore_map(32) {
            let loc = player.location().unwrap();
            let steps = pathing.sorted_neighbors(&loc);
            if steps.len() == 0 {
                return false;
            }

            action::input(Step(loc.dir6_towards(steps[0]).unwrap()));
            return true;
        }

        false
    }

    /// Context-specific interaction with the current cell.
    fn interact(&mut self) {
        let player = action::player().unwrap();
        let loc = player.location().unwrap();
        if let Some(item) = loc.top_item() {
            player.pick_up(item);
            return;
        }
    }

    /// Process a player control keypress.
    pub fn gameplay_process_key(&mut self, key: Key) -> bool {
        if action::control_state() != AwaitingInput {
            return false;
        }

        if self.exploring {
            self.exploring = false;
        }

        match key {
            Key::Q | Key::Pad7 => { self.smart_move(NorthWest); }
            Key::W | Key::Pad8 | Key::Up => { self.smart_move(North); }
            Key::E | Key::Pad9 => { self.smart_move(NorthEast); }
            Key::A | Key::Pad1 => { self.smart_move(SouthWest); }
            Key::S | Key::Pad2 | Key::Down => { self.smart_move(South); }
            Key::D | Key::Pad3 => { self.smart_move(SouthEast); }

            Key::Enter => { self.interact(); }
            Key::X => { self.exploring = true; }

            // Open inventory
            Key::Tab => { self.ui_state = UiState::Inventory; }

            Key::F5 => { self.save_game(); }
            Key::F9 => { self.load_game(); }
            _ => { return false; }
        }
        return true;
    }

    pub fn gameplay_process(&mut self, event: Event) -> bool {
        match event {
            Event::Render(ctx) => {
                self.update(ctx);
            }
            // TODO: Better quit confirmation than just pressing esc.
            Event::KeyPressed(Key::Escape) => {
                return false;
            }
            Event::KeyPressed(k) => {
                self.gameplay_process_key(k);
            }

            Event::Char(ch) => {
                // TODO: Chars and keypresses in same lookup (use variants?)
                match ch {
                    // Debug
                    '>' => { action::next_level(); }
                    _ => ()
                }
            }

            _ => ()
        }
        true
    }

    pub fn inventory_process(&mut self, event: Event) -> bool {
        match event {
            Event::Render(ctx) => {
                self.update(ctx);
            }
            Event::KeyPressed(Key::Escape) | Event::KeyPressed(Key::Tab) => {
                self.ui_state = UiState::Gameplay
            }
            Event::KeyPressed(_) => {}

            Event::Char(ch) => {
                // TODO: Chars and keypresses in same lookup (use variants?)
                match ch {
                    // Debug
                    '>' => { action::next_level(); }
                    _ => ()
                }
            }

            _ => ()
        }
        true
    }

    pub fn process(&mut self, event: Event) -> bool {
        match self.ui_state {
            UiState::Gameplay => self.gameplay_process(event),
            UiState::Inventory => self.inventory_process(event),
        }
    }
}

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

static SLOT_DATA: [SlotData, ..34] = [
    SlotData { key: '1', slot: Slot::Spell1,     name: "Ability" },
    SlotData { key: '2', slot: Slot::Spell2,     name: "Ability" },
    SlotData { key: '3', slot: Slot::Spell3,     name: "Ability" },
    SlotData { key: '4', slot: Slot::Spell4,     name: "Ability" },
    SlotData { key: '5', slot: Slot::Spell5,     name: "Ability" },
    SlotData { key: '6', slot: Slot::Spell6,     name: "Ability" },
    SlotData { key: '7', slot: Slot::Spell7,     name: "Ability" },
    SlotData { key: '8', slot: Slot::Spell8,     name: "Ability" },
    SlotData { key: 'a', slot: Slot::Melee,      name: "Weapon " },
    SlotData { key: 'b', slot: Slot::Ranged,     name: "Ranged " },
    SlotData { key: 'c', slot: Slot::Head,       name: "Helmet " },
    SlotData { key: 'd', slot: Slot::Torso,      name: "Armor  " },
    SlotData { key: 'e', slot: Slot::Boots,      name: "Boots  " },
    SlotData { key: 'f', slot: Slot::TrinketF,   name: "Trinket" },
    SlotData { key: 'g', slot: Slot::TrinketG,   name: "Trinket" },
    SlotData { key: 'h', slot: Slot::TrinketH,   name: "Trinket" },
    SlotData { key: 'i', slot: Slot::TrinketI,   name: "Trinket" },
    SlotData { key: 'j', slot: Slot::InventoryJ, name: "       " },
    SlotData { key: 'k', slot: Slot::InventoryK, name: "       " },
    SlotData { key: 'l', slot: Slot::InventoryL, name: "       " },
    SlotData { key: 'm', slot: Slot::InventoryM, name: "       " },
    SlotData { key: 'n', slot: Slot::InventoryN, name: "       " },
    SlotData { key: 'o', slot: Slot::InventoryO, name: "       " },
    SlotData { key: 'p', slot: Slot::InventoryP, name: "       " },
    SlotData { key: 'q', slot: Slot::InventoryQ, name: "       " },
    SlotData { key: 'r', slot: Slot::InventoryR, name: "       " },
    SlotData { key: 's', slot: Slot::InventoryS, name: "       " },
    SlotData { key: 't', slot: Slot::InventoryT, name: "       " },
    SlotData { key: 'u', slot: Slot::InventoryU, name: "       " },
    SlotData { key: 'v', slot: Slot::InventoryV, name: "       " },
    SlotData { key: 'w', slot: Slot::InventoryW, name: "       " },
    SlotData { key: 'x', slot: Slot::InventoryX, name: "       " },
    SlotData { key: 'y', slot: Slot::InventoryY, name: "       " },
    SlotData { key: 'z', slot: Slot::InventoryZ, name: "       " },
];
<commit_msg>Font outline messes up descenders, remove it<commit_after>use std::io::File;
use std::io::fs::PathExtensions;
use std::collections::HashMap;
use calx::color;
use calx::Context;
use calx::Event;
use calx::Key;
use calx::{Fonter, V2};
use world;
use world::action;
use world::action::Input::{Step, Melee};
use world::action::ControlState::*;
use world::{Msg, FovStatus};
use world::Dir6;
use world::Dir6::*;
use world::{Entity};
use world::item::{Slot};
use worldview;
use sprite::{WorldSprites, GibSprite};
use tilecache;
use tilecache::icon;
use msg_queue::MsgQueue;

pub struct GameState {
    /// Transient effect sprites drawn in game world view.
    world_spr: WorldSprites,
    /// Counters for entities with flashing damage animation.
    damage_timers: HashMap<Entity, uint>,

    /// Flag for autoexploration.
    // TODO: Probably going to need a general "ongoing activity" system at
    // some point.
    exploring: bool,

    msg: MsgQueue,
    ui_state: UiState,
}

enum UiState {
    Gameplay,
    Inventory
}

impl GameState {
    pub fn new(seed: Option<u32>) -> GameState {
        world::init_world(seed);
        GameState {
            world_spr: WorldSprites::new(),
            damage_timers: HashMap::new(),
            exploring: false,
            msg: MsgQueue::new(),
            ui_state: UiState::Gameplay,
        }
    }

    fn draw_player_ui(&mut self, ctx: &mut Context, player: Entity) {
        let hp = player.hp();
        let max_hp = player.max_hp();

        // Draw heart containers.
        for i in range(0, (max_hp + 1) / 2) {
            let pos = V2(i as int * 8, 8);
            let idx = if hp >= (i + 1) * 2 { icon::HEART }
                else if hp == i * 2 + 1 { icon::HALF_HEART }
                else { icon::NO_HEART };
            ctx.draw_image(pos, 0.0, tilecache::get(idx), &color::FIREBRICK);
        }
    }

    fn base_paint(&mut self, ctx: &mut Context) {
        let camera = world::camera();
        worldview::draw_world(&camera, ctx, &self.damage_timers);

        self.world_spr.draw(|x| (camera + x).fov_status() == Some(FovStatus::Seen), &camera, ctx);
        self.world_spr.update();

        let location_name = camera.name();
        let _ = write!(&mut ctx.text_writer(V2(640 - location_name.len() as int * 8, 8), 0.1, color::LIGHTGRAY)
                       .set_border(color::BLACK),
                       "{}", location_name);

        self.msg.draw(ctx);
        if let Some(player) = action::player() {
            self.draw_player_ui(ctx, player);
        }

        let fps = 1.0 / ctx.render_duration;
        let _ = write!(&mut ctx.text_writer(V2(0, 16), 0.1, color::LIGHTGREEN)
                       .set_border(color::BLACK),
                       "FPS {:.0}", fps);
    }

    fn base_update(&mut self, ctx: &mut Context) {
        // Process events
        loop {
            match world::pop_msg() {
                Some(Msg::Gib(loc)) => {
                    self.world_spr.add(box GibSprite::new(loc));
                }
                Some(Msg::Damage(entity)) => {
                    self.damage_timers.insert(entity, 2);
                }
                Some(Msg::Text(txt)) => {
                    self.msg.msg(txt)
                }
                Some(Msg::Caption(txt)) => {
                    self.msg.caption(txt)
                }
                Some(x) => {
                    println!("Unhandled Msg type {}", x);
                }
                None => break
            }
        }

        self.base_paint(ctx);

        if action::control_state() == ReadyToUpdate {
            action::update();
        }

        if self.exploring {
            if action::control_state() == AwaitingInput {
                self.exploring = self.autoexplore();
            }
        }

        self.damage_timers = self.damage_timers.clone().into_iter()
            .filter(|&(_, t)| t > 0u)
            .map(|(e, t)| (e, t - 1))
            .collect();

        self.msg.update();
    }

    fn inventory_update(&mut self, ctx: &mut Context) {
        let player = action::player().unwrap();
        let mut cursor = ctx.text_writer(V2(0, 8), 0.1, color::GAINSBORO);
        for slot_data in SLOT_DATA.iter() {
            let name = match player.equipped(slot_data.slot) {
                Some(item) => item.name(),
                None => "".to_string()
            };
            let _ = write!(&mut cursor, "{}] {}: {}\n",
                slot_data.key, slot_data.name, name);
        }
    }

    /// Repaint view, update game world if needed.
    pub fn update(&mut self, ctx: &mut Context) {
        ctx.clear(&color::BLACK);

        match self.ui_state {
            UiState::Gameplay => self.base_update(ctx),
            UiState::Inventory => self.inventory_update(ctx),
        }
    }

    pub fn save_game(&self) {
        let save_data = world::save();
        let mut file = File::create(&Path::new("/tmp/magog_save.json"));
        file.write_str(save_data.as_slice()).unwrap();
    }

    pub fn load_game(&mut self) {
        let path = Path::new("/tmp/magog_save.json");
        if !path.exists() { return; }
        let save_data = File::open(&path).read_to_string().unwrap();
        // TODO: Handle failed load nicely.
        world::load(save_data.as_slice()).unwrap();
    }

    fn smart_move(&mut self, dir: Dir6) {
        let player = action::player().unwrap();
        let loc = player.location().unwrap();
        for &d in vec![dir, dir + 1, dir - 1].iter() {
            let target_loc = loc + d.to_v2();
            if target_loc.has_mobs() {
                action::input(Melee(d));
                return;
            } else if player.can_step(d) {
                action::input(Step(d));
                return;
            }
        }
    }

    fn autoexplore(&mut self) -> bool {
        let player = action::player().unwrap();
        if player.is_threatened() {
            return false;
        }
        if let Some(pathing) = action::autoexplore_map(32) {
            let loc = player.location().unwrap();
            let steps = pathing.sorted_neighbors(&loc);
            if steps.len() == 0 {
                return false;
            }

            action::input(Step(loc.dir6_towards(steps[0]).unwrap()));
            return true;
        }

        false
    }

    /// Context-specific interaction with the current cell.
    fn interact(&mut self) {
        let player = action::player().unwrap();
        let loc = player.location().unwrap();
        if let Some(item) = loc.top_item() {
            player.pick_up(item);
            return;
        }
    }

    /// Process a player control keypress.
    pub fn gameplay_process_key(&mut self, key: Key) -> bool {
        if action::control_state() != AwaitingInput {
            return false;
        }

        if self.exploring {
            self.exploring = false;
        }

        match key {
            Key::Q | Key::Pad7 => { self.smart_move(NorthWest); }
            Key::W | Key::Pad8 | Key::Up => { self.smart_move(North); }
            Key::E | Key::Pad9 => { self.smart_move(NorthEast); }
            Key::A | Key::Pad1 => { self.smart_move(SouthWest); }
            Key::S | Key::Pad2 | Key::Down => { self.smart_move(South); }
            Key::D | Key::Pad3 => { self.smart_move(SouthEast); }

            Key::Enter => { self.interact(); }
            Key::X => { self.exploring = true; }

            // Open inventory
            Key::Tab => { self.ui_state = UiState::Inventory; }

            Key::F5 => { self.save_game(); }
            Key::F9 => { self.load_game(); }
            _ => { return false; }
        }
        return true;
    }

    pub fn gameplay_process(&mut self, event: Event) -> bool {
        match event {
            Event::Render(ctx) => {
                self.update(ctx);
            }
            // TODO: Better quit confirmation than just pressing esc.
            Event::KeyPressed(Key::Escape) => {
                return false;
            }
            Event::KeyPressed(k) => {
                self.gameplay_process_key(k);
            }

            Event::Char(ch) => {
                // TODO: Chars and keypresses in same lookup (use variants?)
                match ch {
                    // Debug
                    '>' => { action::next_level(); }
                    _ => ()
                }
            }

            _ => ()
        }
        true
    }

    pub fn inventory_process(&mut self, event: Event) -> bool {
        match event {
            Event::Render(ctx) => {
                self.update(ctx);
            }
            Event::KeyPressed(Key::Escape) | Event::KeyPressed(Key::Tab) => {
                self.ui_state = UiState::Gameplay
            }
            Event::KeyPressed(_) => {}

            Event::Char(ch) => {
                // TODO: Chars and keypresses in same lookup (use variants?)
                match ch {
                    // Debug
                    '>' => { action::next_level(); }
                    _ => ()
                }
            }

            _ => ()
        }
        true
    }

    pub fn process(&mut self, event: Event) -> bool {
        match self.ui_state {
            UiState::Gameplay => self.gameplay_process(event),
            UiState::Inventory => self.inventory_process(event),
        }
    }
}

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

static SLOT_DATA: [SlotData, ..34] = [
    SlotData { key: '1', slot: Slot::Spell1,     name: "Ability" },
    SlotData { key: '2', slot: Slot::Spell2,     name: "Ability" },
    SlotData { key: '3', slot: Slot::Spell3,     name: "Ability" },
    SlotData { key: '4', slot: Slot::Spell4,     name: "Ability" },
    SlotData { key: '5', slot: Slot::Spell5,     name: "Ability" },
    SlotData { key: '6', slot: Slot::Spell6,     name: "Ability" },
    SlotData { key: '7', slot: Slot::Spell7,     name: "Ability" },
    SlotData { key: '8', slot: Slot::Spell8,     name: "Ability" },
    SlotData { key: 'a', slot: Slot::Melee,      name: "Weapon " },
    SlotData { key: 'b', slot: Slot::Ranged,     name: "Ranged " },
    SlotData { key: 'c', slot: Slot::Head,       name: "Helmet " },
    SlotData { key: 'd', slot: Slot::Torso,      name: "Armor  " },
    SlotData { key: 'e', slot: Slot::Boots,      name: "Boots  " },
    SlotData { key: 'f', slot: Slot::TrinketF,   name: "Trinket" },
    SlotData { key: 'g', slot: Slot::TrinketG,   name: "Trinket" },
    SlotData { key: 'h', slot: Slot::TrinketH,   name: "Trinket" },
    SlotData { key: 'i', slot: Slot::TrinketI,   name: "Trinket" },
    SlotData { key: 'j', slot: Slot::InventoryJ, name: "       " },
    SlotData { key: 'k', slot: Slot::InventoryK, name: "       " },
    SlotData { key: 'l', slot: Slot::InventoryL, name: "       " },
    SlotData { key: 'm', slot: Slot::InventoryM, name: "       " },
    SlotData { key: 'n', slot: Slot::InventoryN, name: "       " },
    SlotData { key: 'o', slot: Slot::InventoryO, name: "       " },
    SlotData { key: 'p', slot: Slot::InventoryP, name: "       " },
    SlotData { key: 'q', slot: Slot::InventoryQ, name: "       " },
    SlotData { key: 'r', slot: Slot::InventoryR, name: "       " },
    SlotData { key: 's', slot: Slot::InventoryS, name: "       " },
    SlotData { key: 't', slot: Slot::InventoryT, name: "       " },
    SlotData { key: 'u', slot: Slot::InventoryU, name: "       " },
    SlotData { key: 'v', slot: Slot::InventoryV, name: "       " },
    SlotData { key: 'w', slot: Slot::InventoryW, name: "       " },
    SlotData { key: 'x', slot: Slot::InventoryX, name: "       " },
    SlotData { key: 'y', slot: Slot::InventoryY, name: "       " },
    SlotData { key: 'z', slot: Slot::InventoryZ, name: "       " },
];
<|endoftext|>


<commit_before>#![forbid(unsafe_code)]

use sha2::Digest;
use std::borrow::Cow;
use std::path::Path;
use std::time::SystemTime;
use std::{fs, io};

#[cfg_attr(all(debug_assertions, not(feature = "debug-embed")), allow(unused))]
pub struct FileEntry {
  pub rel_path: String,
  pub full_canonical_path: String,
}

#[cfg(not(feature = "include-exclude"))]
pub fn is_path_included(_path: &str, _includes: &[&str], _excludes: &[&str]) -> bool {
  true
}

#[cfg(feature = "include-exclude")]
pub fn is_path_included(rel_path: &str, includes: &[&str], excludes: &[&str]) -> bool {
  use globset::Glob;

  // ignore path matched by exclusion pattern
  for exclude in excludes {
    let pattern = Glob::new(exclude)
      .unwrap_or_else(|_| panic!("invalid exclude pattern '{}'", exclude))
      .compile_matcher();

    if pattern.is_match(rel_path) {
      return false;
    }
  }

  // accept path if no includes provided
  if includes.is_empty() {
    return true;
  }

  // accept path if matched by inclusion pattern
  for include in includes {
    let pattern = Glob::new(include)
      .unwrap_or_else(|_| panic!("invalid include pattern '{}'", include))
      .compile_matcher();

    if pattern.is_match(rel_path) {
      return true;
    }
  }

  false
}

#[cfg_attr(all(debug_assertions, not(feature = "debug-embed")), allow(unused))]
pub fn get_files<'patterns>(folder_path: String, includes: &'patterns [&str], excludes: &'patterns [&str]) -> impl Iterator<Item = FileEntry> + 'patterns {
  walkdir::WalkDir::new(&folder_path)
    .follow_links(true)
    .into_iter()
    .filter_map(|e| e.ok())
    .filter(|e| e.file_type().is_file())
    .filter_map(move |e| {
      let rel_path = path_to_str(e.path().strip_prefix(&folder_path).unwrap());
      let full_canonical_path = path_to_str(std::fs::canonicalize(e.path()).expect("Could not get canonical path"));

      let rel_path = if std::path::MAIN_SEPARATOR == '\\' {
        rel_path.replace('\\', "/")
      } else {
        rel_path
      };

      if is_path_included(&rel_path, includes, excludes) {
        Some(FileEntry { rel_path, full_canonical_path })
      } else {
        None
      }
    })
}

/// A file embedded into the binary
pub struct EmbeddedFile {
  pub data: Cow<'static, [u8]>,
  pub metadata: Metadata,
}

/// Metadata about an embedded file
pub struct Metadata {
  hash: [u8; 32],
  last_modified: Option<u64>,
}

impl Metadata {
  #[doc(hidden)]
  pub fn __rust_embed_new(hash: [u8; 32], last_modified: Option<u64>) -> Self {
    Self { hash, last_modified }
  }

  /// The SHA256 hash of the file
  pub fn sha256_hash(&self) -> [u8; 32] {
    self.hash
  }

  /// The last modified date in seconds since the UNIX epoch. If the underlying
  /// platform/file-system does not support this, None is returned.
  pub fn last_modified(&self) -> Option<u64> {
    self.last_modified
  }
}

pub fn read_file_from_fs(file_path: &Path) -> io::Result<EmbeddedFile> {
  let data = fs::read(file_path)?;
  let data = Cow::from(data);

  let mut hasher = sha2::Sha256::new();
  hasher.update(&data);
  let hash: [u8; 32] = hasher.finalize().into();

  let last_modified = fs::metadata(file_path)?.modified().ok().map(|last_modified| {
    last_modified
      .duration_since(SystemTime::UNIX_EPOCH)
      .expect("Time before the UNIX epoch is unsupported")
      .as_secs()
  });

  Ok(EmbeddedFile {
    data,
    metadata: Metadata { hash, last_modified },
  })
}

fn path_to_str<P: AsRef<std::path::Path>>(p: P) -> String {
  p.as_ref().to_str().expect("Path does not have a string representation").to_owned()
}
<commit_msg>Sort directory entries by file name to provide consistent ordering in embedded entries.<commit_after>#![forbid(unsafe_code)]

use sha2::Digest;
use std::borrow::Cow;
use std::path::Path;
use std::time::SystemTime;
use std::{fs, io};

#[cfg_attr(all(debug_assertions, not(feature = "debug-embed")), allow(unused))]
pub struct FileEntry {
  pub rel_path: String,
  pub full_canonical_path: String,
}

#[cfg(not(feature = "include-exclude"))]
pub fn is_path_included(_path: &str, _includes: &[&str], _excludes: &[&str]) -> bool {
  true
}

#[cfg(feature = "include-exclude")]
pub fn is_path_included(rel_path: &str, includes: &[&str], excludes: &[&str]) -> bool {
  use globset::Glob;

  // ignore path matched by exclusion pattern
  for exclude in excludes {
    let pattern = Glob::new(exclude)
      .unwrap_or_else(|_| panic!("invalid exclude pattern '{}'", exclude))
      .compile_matcher();

    if pattern.is_match(rel_path) {
      return false;
    }
  }

  // accept path if no includes provided
  if includes.is_empty() {
    return true;
  }

  // accept path if matched by inclusion pattern
  for include in includes {
    let pattern = Glob::new(include)
      .unwrap_or_else(|_| panic!("invalid include pattern '{}'", include))
      .compile_matcher();

    if pattern.is_match(rel_path) {
      return true;
    }
  }

  false
}

#[cfg_attr(all(debug_assertions, not(feature = "debug-embed")), allow(unused))]
pub fn get_files<'patterns>(folder_path: String, includes: &'patterns [&str], excludes: &'patterns [&str]) -> impl Iterator<Item = FileEntry> + 'patterns {
  walkdir::WalkDir::new(&folder_path)
    .follow_links(true)
    .sort_by_file_name()
    .into_iter()
    .filter_map(|e| e.ok())
    .filter(|e| e.file_type().is_file())
    .filter_map(move |e| {
      let rel_path = path_to_str(e.path().strip_prefix(&folder_path).unwrap());
      let full_canonical_path = path_to_str(std::fs::canonicalize(e.path()).expect("Could not get canonical path"));

      let rel_path = if std::path::MAIN_SEPARATOR == '\\' {
        rel_path.replace('\\', "/")
      } else {
        rel_path
      };

      if is_path_included(&rel_path, includes, excludes) {
        Some(FileEntry { rel_path, full_canonical_path })
      } else {
        None
      }
    })
}

/// A file embedded into the binary
pub struct EmbeddedFile {
  pub data: Cow<'static, [u8]>,
  pub metadata: Metadata,
}

/// Metadata about an embedded file
pub struct Metadata {
  hash: [u8; 32],
  last_modified: Option<u64>,
}

impl Metadata {
  #[doc(hidden)]
  pub fn __rust_embed_new(hash: [u8; 32], last_modified: Option<u64>) -> Self {
    Self { hash, last_modified }
  }

  /// The SHA256 hash of the file
  pub fn sha256_hash(&self) -> [u8; 32] {
    self.hash
  }

  /// The last modified date in seconds since the UNIX epoch. If the underlying
  /// platform/file-system does not support this, None is returned.
  pub fn last_modified(&self) -> Option<u64> {
    self.last_modified
  }
}

pub fn read_file_from_fs(file_path: &Path) -> io::Result<EmbeddedFile> {
  let data = fs::read(file_path)?;
  let data = Cow::from(data);

  let mut hasher = sha2::Sha256::new();
  hasher.update(&data);
  let hash: [u8; 32] = hasher.finalize().into();

  let last_modified = fs::metadata(file_path)?.modified().ok().map(|last_modified| {
    last_modified
      .duration_since(SystemTime::UNIX_EPOCH)
      .expect("Time before the UNIX epoch is unsupported")
      .as_secs()
  });

  Ok(EmbeddedFile {
    data,
    metadata: Metadata { hash, last_modified },
  })
}

fn path_to_str<P: AsRef<std::path::Path>>(p: P) -> String {
  p.as_ref().to_str().expect("Path does not have a string representation").to_owned()
}
<|endoftext|>


<commit_before>use cgmath::*;
use mesh::{Vertex, Mesh, Model};

pub fn generate_plane() -> Result<Model, String> {
    let mut mesh = Mesh::new();
    let mut model = Model::new();
    let mut vb: Vec<Vertex> = vec![Vertex::new(); 4];
    vb[0].position = Vector3::new(-0.5_f32,  0.5_f32, 0.0_f32);
    vb[0].normal   = Vector3::new( 0.0_f32,  0.0_f32, 1.0_f32);
    vb[1].position = Vector3::new( 0.5_f32,  0.5_f32, 0.0_f32);
    vb[1].normal   = Vector3::new( 0.0_f32,  0.0_f32, 1.0_f32);
    vb[2].position = Vector3::new( 0.5_f32, -0.5_f32, 0.0_f32);
    vb[2].normal   = Vector3::new( 0.0_f32,  0.0_f32, 1.0_f32);
    vb[3].position = Vector3::new(-0.5_f32, -0.5_f32, 0.0_f32);
    vb[3].normal   = Vector3::new( 0.0_f32,  0.0_f32, 1.0_f32);
    mesh.vertex(vb);
    let mut ib: Vec<u32> = vec![0; 2 * 3];
    ib[0] = 0;
    ib[1] = 1;
    ib[2] = 2;
    ib[3] = 0;
    ib[4] = 2;
    ib[5] = 3;
    try!(mesh.index(ib));
    model.add(mesh);

    Ok(model)
}

#[allow(dead_code)]
pub fn generate_cube() -> Result<Mesh, String> {
    let mut mesh = Mesh::new();
    let mut vb: Vec<Vertex> = vec![Vertex::new(); 24];
	vb[ 0].position	= Vector3::new(-0.5_f32,-0.5_f32,-0.5_f32);
	vb[ 1].position	= Vector3::new(-0.5_f32, 0.5_f32,-0.5_f32);
	vb[ 2].position	= Vector3::new( 0.5_f32, 0.5_f32,-0.5_f32);
	vb[ 3].position	= Vector3::new( 0.5_f32,-0.5_f32,-0.5_f32);
	vb[ 4].position	= Vector3::new( 0.5_f32,-0.5_f32, 0.5_f32);
	vb[ 5].position	= Vector3::new( 0.5_f32, 0.5_f32, 0.5_f32);
	vb[ 6].position	= Vector3::new(-0.5_f32, 0.5_f32, 0.5_f32);
	vb[ 7].position	= Vector3::new(-0.5_f32,-0.5_f32, 0.5_f32);
	vb[ 8].position	= Vector3::new(-0.5_f32,-0.5_f32, 0.5_f32);
	vb[ 9].position	= Vector3::new(-0.5_f32, 0.5_f32, 0.5_f32);
	vb[10].position	= Vector3::new(-0.5_f32, 0.5_f32,-0.5_f32);
	vb[11].position	= Vector3::new(-0.5_f32,-0.5_f32,-0.5_f32);
	vb[12].position	= Vector3::new( 0.5_f32,-0.5_f32,-0.5_f32);
	vb[13].position	= Vector3::new( 0.5_f32, 0.5_f32,-0.5_f32);
	vb[14].position	= Vector3::new( 0.5_f32, 0.5_f32, 0.5_f32);
	vb[15].position	= Vector3::new( 0.5_f32,-0.5_f32, 0.5_f32);
	vb[16].position	= Vector3::new(-0.5_f32,-0.5_f32, 0.5_f32);
	vb[17].position	= Vector3::new(-0.5_f32,-0.5_f32,-0.5_f32);
	vb[18].position	= Vector3::new( 0.5_f32,-0.5_f32,-0.5_f32);
	vb[19].position	= Vector3::new( 0.5_f32,-0.5_f32, 0.5_f32);
	vb[20].position	= Vector3::new(-0.5_f32, 0.5_f32,-0.5_f32);
	vb[21].position	= Vector3::new(-0.5_f32, 0.5_f32, 0.5_f32);
	vb[22].position	= Vector3::new( 0.5_f32, 0.5_f32, 0.5_f32);
	vb[23].position	= Vector3::new( 0.5_f32, 0.5_f32,-0.5_f32);
    mesh.vertex(vb);
    let mut ib: Vec<u32> = vec![0; 12 * 3];
	for i in 0..6 {
		let sm = (i * 4) as u32;
        let ind = i * 6;
		ib[ind + 0] = sm + 0; ib[ind + 1] = sm + 1; ib[ind + 2] = sm + 2;
		ib[ind + 3] = sm + 0; ib[ind + 4] = sm + 2; ib[ind + 5] = sm + 3;
	}
    try!(mesh.index(ib));

    Ok(mesh)
}
<commit_msg>generate sphere<commit_after>use std;
use cgmath::*;
use mesh::{Vertex, Mesh, Model};

pub fn generate_plane() -> Result<Model, String> {
    let mut model = Model::new();
    let mut mesh = Mesh::new();
    let mut vb: Vec<Vertex> = vec![Vertex::new(); 4];
    vb[0].position = Vector3::new(-0.5_f32,  0.5_f32, 0.0_f32);
    vb[0].normal   = Vector3::new( 0.0_f32,  0.0_f32, 1.0_f32);
    vb[1].position = Vector3::new( 0.5_f32,  0.5_f32, 0.0_f32);
    vb[1].normal   = Vector3::new( 0.0_f32,  0.0_f32, 1.0_f32);
    vb[2].position = Vector3::new( 0.5_f32, -0.5_f32, 0.0_f32);
    vb[2].normal   = Vector3::new( 0.0_f32,  0.0_f32, 1.0_f32);
    vb[3].position = Vector3::new(-0.5_f32, -0.5_f32, 0.0_f32);
    vb[3].normal   = Vector3::new( 0.0_f32,  0.0_f32, 1.0_f32);
    mesh.vertex(vb);
    let mut ib: Vec<u32> = vec![0; 2 * 3];
    ib[0] = 0;
    ib[1] = 1;
    ib[2] = 2;
    ib[3] = 0;
    ib[4] = 2;
    ib[5] = 3;
    try!(mesh.index(ib));
    model.add(mesh);

    Ok(model)
}

#[allow(dead_code)]
pub fn generate_cube() -> Result<Mesh, String> {
    let mut mesh = Mesh::new();
    let mut vb: Vec<Vertex> = vec![Vertex::new(); 24];
	vb[ 0].position	= Vector3::new(-0.5_f32,-0.5_f32,-0.5_f32);
	vb[ 1].position	= Vector3::new(-0.5_f32, 0.5_f32,-0.5_f32);
	vb[ 2].position	= Vector3::new( 0.5_f32, 0.5_f32,-0.5_f32);
	vb[ 3].position	= Vector3::new( 0.5_f32,-0.5_f32,-0.5_f32);
	vb[ 4].position	= Vector3::new( 0.5_f32,-0.5_f32, 0.5_f32);
	vb[ 5].position	= Vector3::new( 0.5_f32, 0.5_f32, 0.5_f32);
	vb[ 6].position	= Vector3::new(-0.5_f32, 0.5_f32, 0.5_f32);
	vb[ 7].position	= Vector3::new(-0.5_f32,-0.5_f32, 0.5_f32);
	vb[ 8].position	= Vector3::new(-0.5_f32,-0.5_f32, 0.5_f32);
	vb[ 9].position	= Vector3::new(-0.5_f32, 0.5_f32, 0.5_f32);
	vb[10].position	= Vector3::new(-0.5_f32, 0.5_f32,-0.5_f32);
	vb[11].position	= Vector3::new(-0.5_f32,-0.5_f32,-0.5_f32);
	vb[12].position	= Vector3::new( 0.5_f32,-0.5_f32,-0.5_f32);
	vb[13].position	= Vector3::new( 0.5_f32, 0.5_f32,-0.5_f32);
	vb[14].position	= Vector3::new( 0.5_f32, 0.5_f32, 0.5_f32);
	vb[15].position	= Vector3::new( 0.5_f32,-0.5_f32, 0.5_f32);
	vb[16].position	= Vector3::new(-0.5_f32,-0.5_f32, 0.5_f32);
	vb[17].position	= Vector3::new(-0.5_f32,-0.5_f32,-0.5_f32);
	vb[18].position	= Vector3::new( 0.5_f32,-0.5_f32,-0.5_f32);
	vb[19].position	= Vector3::new( 0.5_f32,-0.5_f32, 0.5_f32);
	vb[20].position	= Vector3::new(-0.5_f32, 0.5_f32,-0.5_f32);
	vb[21].position	= Vector3::new(-0.5_f32, 0.5_f32, 0.5_f32);
	vb[22].position	= Vector3::new( 0.5_f32, 0.5_f32, 0.5_f32);
	vb[23].position	= Vector3::new( 0.5_f32, 0.5_f32,-0.5_f32);
    mesh.vertex(vb);
    let mut ib: Vec<u32> = vec![0; 12 * 3];
	for i in 0..6 {
		let sm = (i * 4) as u32;
        let ind = i * 6;
		ib[ind + 0] = sm + 0; ib[ind + 1] = sm + 1; ib[ind + 2] = sm + 2;
		ib[ind + 3] = sm + 0; ib[ind + 4] = sm + 2; ib[ind + 5] = sm + 3;
	}
    try!(mesh.index(ib));

    Ok(mesh)
}

pub fn generate_sphere(cnt_vertex: usize) -> Result<Model, String> {
    let mut model = Model::new();
    let mut mesh = Mesh::new();

	let plg = cnt_vertex / 2 - 1;
	let vertex_cnt = plg * cnt_vertex + 2;
	let index_cnt = 6 * (cnt_vertex - 1) * plg;

    let mut vb: Vec<Vertex> = vec![Vertex::new(); vertex_cnt];
    let mut angle_b = rad(-std::f32::consts::PI / 2.0_f32);
	let step_a = rad(std::f32::consts::PI * 2.0_f32 / (cnt_vertex as f32 - 1.0_f32));
	let step_b = rad(std::f32::consts::PI / (plg as f32 + 1.0_f32));
    let mut ind = 1;
    for _ in 0 .. plg {
		angle_b = angle_b + step_b;
        let (y, radius) = sin_cos(angle_b);

        let mut angle_a = rad(0.0_f32);
        for _ in 0 .. cnt_vertex {
            let (sin_a, cos_a) = sin_cos(angle_a);
			vb[ind].position = Vector3::new(radius * cos_a, y, radius * sin_a);
			vb[ind].normal   = Vector3::new(radius * cos_a, y, radius * sin_a).normalize();
            ind += 1;
            angle_a = angle_a + step_a;
		}
	}
	vb[0].position = Vector3::new(0.0_f32, -1.0_f32, 0.0_f32);
	vb[0].normal = Vector3::new(0.0_f32, -1.0_f32, 0.0_f32);
	vb[vertex_cnt - 1].position = Vector3::new(0.0_f32, 1.0_f32, 0.0_f32);
	vb[vertex_cnt - 1].normal = Vector3::new(0.0_f32, 1.0_f32, 0.0_f32);

    mesh.vertex(vb);

    let mut ib: Vec<u32> = vec![0; index_cnt];
    let mut ind = 0;
    for ix in 0 .. (plg-1) {
		let mut z1 = ix * cnt_vertex + 1;
        let mut z2 = z1 + 1;
		let mut z3 = z1 + cnt_vertex;
        let mut z4 = z3 + 1;
		for _ in 0 .. (cnt_vertex - 1) {
			ib[ind + 0] = z1 as u32;
            ib[ind + 1] = z2 as u32;
            ib[ind + 2] = z3 as u32;

			ib[ind + 3] = z4 as u32;
            ib[ind + 4] = z3 as u32;
            ib[ind + 5] = z2 as u32;
            z1 += 1;
            z2 += 1;
            z3 += 1;
            z4 += 1;
            ind += 6;
		}
	}

	// let iy = cnt_vertex * (plg - 1);
	// for ix in 1 .. cnt_vertex {
	// 	ib[ind + 0] = ix as u32;
    //     ib[ind + 1] = (ix + 1) as u32;
    //     ib[ind + 2] = 0 as u32;
	// 	ib[ind + 3] = (iy + ix + 1) as u32;
    //     ib[ind + 4] = (iy + ix) as u32;
    //     ib[ind + 5] = (vertex_cnt - 1) as u32;
    //     ind += 6;
	// }
    try!(mesh.index(ib));
    mesh.calc_normal();
    model.add(mesh);

    Ok(model)
}
<|endoftext|>


<commit_before>//! Fields which are common to all segment-section and gate descriptors

use shared::PrivilegeLevel;
use shared::segmentation;

/// System-Segment and Gate-Descriptor Types for IA32e mode.  When the `S`
/// (descriptor type) flag in a segment descriptor is clear, the descriptor type
/// is a system descriptor.
///
/// See Intel manual 3a, 3.5 "System Descriptor Types", and Table 3-2,
/// System-Segment and Gate-Descriptor Types".
#[repr(u8)]
pub enum SystemType {
    // Reserved = 0
    TssAvailable = 1,
    /// Only for 16-bit
    LocalDescriptorTable = 2,
    TssBusy = 3,
    CallGate = 4,
    /// Only for 16-bit
    TaskGate = 5,
    InterruptGate = 6,
    TrapGate = 7,
}

/// A high-level representation of a descriptor type. One can convert to and
/// from the `Flags` bitfield to encode/decode an actual descriptor.
#[repr(u8)]
pub enum Type {
    SystemDescriptor {
        /// false/0: 16-bit
        /// true/1: native (32- or 64-bit)
        size: bool,
        ty: SystemType
    },
    SegmentDescriptor {
        ty: segmentation::Type,
        accessed: bool
    }
}

impl Type {
    pub fn pack(self) -> u8 {
        match self {
            Type::SystemDescriptor { size, ty } =>
                (size as u8) << 3 | (ty as u8) | FLAGS_TYPE_SYS.bits,
            Type::SegmentDescriptor { ty, accessed } =>
                (accessed as u8)  | ty.pack()  | FLAGS_TYPE_SYS.bits,
        }
    }
}

bitflags!{
    /// Actual encoding of the flags in byte 6 common to all descriptors.
    ///
    /// See Intel manual 3a, figures 3-8, 6-2, and 6-7.
    pub flags Flags: u8 {
        /// Descriptor is Present.
        const FLAGS_PRESENT = 1 << 7,

        // Descriptor privilege level
        const FLAGS_DPL_RING_0 = 0b00 << 5,
        const FLAGS_DPL_RING_1 = 0b01 << 5,
        const FLAGS_DPL_RING_2 = 0b10 << 5,
        const FLAGS_DPL_RING_3 = 0b11 << 5,

        // Is system descriptor
        const FLAGS_TYPE_SYS = 0 << 4,
        const FLAGS_TYPE_SEG = 1 << 4,

        // System-Segment and Gate-Descriptor Types.
        // When the S (descriptor type) flag in a segment descriptor is clear,
        // the descriptor type is a system descriptor

        // All modes (supporting segments)
        const TYPE_SYS_LDT = 0b0_0010,

        // Protected Mode and older
        const FLAGS_TYPE_SYS_16BIT_TSS_AVAILABLE = 0b0_0001,
        const FLAGS_TYPE_SYS_16BIT_TSS_BUSY = 0b0_0011,
        const FLAGS_TYPE_SYS_16BIT_CALL_GATE = 0b0_0100,
        const FLAGS_TYPE_SYS_16BIT_TASK_GATE = 0b0_0101,
        const FLAGS_TYPE_SYS_16BIT_INTERRUPT_GATE = 0b0_0110,
        const FLAGS_TYPE_SYS_16BIT_TRAP_GATE = 0b0_0111,

        // 64-bit in IA-32e Mode (either submode), 32-bit in Protected Mode
        const FLAGS_TYPE_SYS_NATIVE_TSS_AVAILABLE = 0b0_1001,
        const FLAGS_TYPE_SYS_NATIVE_TSS_BUSY = 0b0_1011,
        const FLAGS_TYPE_SYS_NATIVE_CALL_GATE = 0b0_1100,
        const FLAGS_TYPE_SYS_NATIVE_INTERRUPT_GATE = 0b0_1110,
        const FLAGS_TYPE_SYS_NATIVE_TRAP_GATE = 0b0_1111,

        // Code- and Data-Segment Descriptor Types.
        // When the S (descriptor type) flag in a segment descriptor is set,
        // the descriptor is for either a code or a data segment.

        /// Data or code, accessed
        const FLAGS_TYPE_SEG_ACCESSED = 0b1_0001,

        const FLAGS_TYPE_DATA = 0b1_0000,
        const FLAGS_TYPE_CODE = 0b1_1000,

        // Data => permissions
        const FLAGS_TYPE_SEG_D_WRITE = 0b1_0010,
        const FLAGS_TYPE_SEG_D_EXPAND_DOWN = 0b1_0100,

        // Code => permissions
        const FLAGS_TYPE_SEG_C_READ = 0b1_0010,
        const FLAGS_TYPE_SEG_C_CONFORMING = 0b1_0100,

        /// Data Read-Only
        const FLAGS_TYPE_SEG_D_RO     = FLAGS_TYPE_DATA.bits,
        /// Data Read-Only, accessed
        const FLAGS_TYPE_SEG_D_ROA    = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Data Read/Write
        const FLAGS_TYPE_SEG_D_RW     = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_WRITE.bits,
        /// Data Read/Write, accessed
        const FLAGS_TYPE_SEG_D_RWA    = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_WRITE.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Data Read-Only, expand-down
        const FLAGS_TYPE_SEG_D_ROEXD  = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_EXPAND_DOWN.bits,
        /// Data Read-Only, expand-down, accessed
        const FLAGS_TYPE_SEG_D_ROEXDA = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_EXPAND_DOWN.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Data Read/Write, expand-down
        const FLAGS_TYPE_SEG_D_RWEXD  = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_WRITE.bits
                                      | FLAGS_TYPE_SEG_D_EXPAND_DOWN.bits,
        /// Data Read/Write, expand-down, accessed
        const FLAGS_TYPE_SEG_D_RWEXDA = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_WRITE.bits
                                      | FLAGS_TYPE_SEG_D_EXPAND_DOWN.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,

        /// Code Execute-Only
        const FLAGS_TYPE_SEG_C_EO     = FLAGS_TYPE_CODE.bits,
        /// Code Execute-Only, accessed
        const FLAGS_TYPE_SEG_C_EOA    = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Code Execute/Read
        const FLAGS_TYPE_SEG_C_ER     = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_C_READ.bits,
        /// Code Execute/Read, accessed
        const FLAGS_TYPE_SEG_C_ERA    = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_C_READ.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Code Execute-Only, conforming
        const FLAGS_TYPE_SEG_C_EOC    = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_C_CONFORMING.bits,
        /// Code Execute-Only, conforming, accessed
        const FLAGS_TYPE_SEG_C_EOCA   = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_C_CONFORMING.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Code Execute/Read, conforming
        const FLAGS_TYPE_SEG_C_ERC    = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_C_READ.bits
                                      | FLAGS_TYPE_SEG_C_CONFORMING.bits,
        /// Code Execute/Read, conforming, accessed
        const FLAGS_TYPE_SEG_C_ERCA   = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_C_READ.bits
                                      | FLAGS_TYPE_SEG_C_CONFORMING.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
    }
}

impl Flags {
    pub const BLANK: Flags = Flags { bits: 0 };

    pub const fn from_priv(dpl: PrivilegeLevel) -> Flags {
        Flags { bits: (dpl as u8) << 5 }
    }

    pub fn from_type(ty: Type) -> Flags {
        Flags { bits: ty.pack() }
    }

    pub const fn const_or(self, other: Self) -> Flags {
        Flags { bits: self.bits | other.bits }
    }

    pub const fn cond(self, cond: bool) -> Flags {
        Flags { bits: (-(cond as i8) as u8) & self.bits }
    }

    pub const fn const_mux(self, other: Self, cond: bool) -> Flags {
        self.cond(cond).const_or(other.cond(!cond))
    }
}
<commit_msg>Fix SegmentDescriptor type flag.<commit_after>//! Fields which are common to all segment-section and gate descriptors

use shared::PrivilegeLevel;
use shared::segmentation;

/// System-Segment and Gate-Descriptor Types for IA32e mode.  When the `S`
/// (descriptor type) flag in a segment descriptor is clear, the descriptor type
/// is a system descriptor.
///
/// See Intel manual 3a, 3.5 "System Descriptor Types", and Table 3-2,
/// System-Segment and Gate-Descriptor Types".
#[repr(u8)]
pub enum SystemType {
    // Reserved = 0
    TssAvailable = 1,
    /// Only for 16-bit
    LocalDescriptorTable = 2,
    TssBusy = 3,
    CallGate = 4,
    /// Only for 16-bit
    TaskGate = 5,
    InterruptGate = 6,
    TrapGate = 7,
}

/// A high-level representation of a descriptor type. One can convert to and
/// from the `Flags` bitfield to encode/decode an actual descriptor.
#[repr(u8)]
pub enum Type {
    SystemDescriptor {
        /// false/0: 16-bit
        /// true/1: native (32- or 64-bit)
        size: bool,
        ty: SystemType
    },
    SegmentDescriptor {
        ty: segmentation::Type,
        accessed: bool
    }
}

impl Type {
    pub fn pack(self) -> u8 {
        match self {
            Type::SystemDescriptor { size, ty } =>
                (size as u8) << 3 | (ty as u8) | FLAGS_TYPE_SYS.bits,
            Type::SegmentDescriptor { ty, accessed } =>
                (accessed as u8)  | ty.pack()  | FLAGS_TYPE_SEG.bits,
        }
    }
}

bitflags!{
    /// Actual encoding of the flags in byte 6 common to all descriptors.
    ///
    /// See Intel manual 3a, figures 3-8, 6-2, and 6-7.
    pub flags Flags: u8 {
        /// Descriptor is Present.
        const FLAGS_PRESENT = 1 << 7,

        // Descriptor privilege level
        const FLAGS_DPL_RING_0 = 0b00 << 5,
        const FLAGS_DPL_RING_1 = 0b01 << 5,
        const FLAGS_DPL_RING_2 = 0b10 << 5,
        const FLAGS_DPL_RING_3 = 0b11 << 5,

        // Is system descriptor
        const FLAGS_TYPE_SYS = 0 << 4,
        const FLAGS_TYPE_SEG = 1 << 4,

        // System-Segment and Gate-Descriptor Types.
        // When the S (descriptor type) flag in a segment descriptor is clear,
        // the descriptor type is a system descriptor

        // All modes (supporting segments)
        const TYPE_SYS_LDT = 0b0_0010,

        // Protected Mode and older
        const FLAGS_TYPE_SYS_16BIT_TSS_AVAILABLE = 0b0_0001,
        const FLAGS_TYPE_SYS_16BIT_TSS_BUSY = 0b0_0011,
        const FLAGS_TYPE_SYS_16BIT_CALL_GATE = 0b0_0100,
        const FLAGS_TYPE_SYS_16BIT_TASK_GATE = 0b0_0101,
        const FLAGS_TYPE_SYS_16BIT_INTERRUPT_GATE = 0b0_0110,
        const FLAGS_TYPE_SYS_16BIT_TRAP_GATE = 0b0_0111,

        // 64-bit in IA-32e Mode (either submode), 32-bit in Protected Mode
        const FLAGS_TYPE_SYS_NATIVE_TSS_AVAILABLE = 0b0_1001,
        const FLAGS_TYPE_SYS_NATIVE_TSS_BUSY = 0b0_1011,
        const FLAGS_TYPE_SYS_NATIVE_CALL_GATE = 0b0_1100,
        const FLAGS_TYPE_SYS_NATIVE_INTERRUPT_GATE = 0b0_1110,
        const FLAGS_TYPE_SYS_NATIVE_TRAP_GATE = 0b0_1111,

        // Code- and Data-Segment Descriptor Types.
        // When the S (descriptor type) flag in a segment descriptor is set,
        // the descriptor is for either a code or a data segment.

        /// Data or code, accessed
        const FLAGS_TYPE_SEG_ACCESSED = 0b1_0001,

        const FLAGS_TYPE_DATA = 0b1_0000,
        const FLAGS_TYPE_CODE = 0b1_1000,

        // Data => permissions
        const FLAGS_TYPE_SEG_D_WRITE = 0b1_0010,
        const FLAGS_TYPE_SEG_D_EXPAND_DOWN = 0b1_0100,

        // Code => permissions
        const FLAGS_TYPE_SEG_C_READ = 0b1_0010,
        const FLAGS_TYPE_SEG_C_CONFORMING = 0b1_0100,

        /// Data Read-Only
        const FLAGS_TYPE_SEG_D_RO     = FLAGS_TYPE_DATA.bits,
        /// Data Read-Only, accessed
        const FLAGS_TYPE_SEG_D_ROA    = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Data Read/Write
        const FLAGS_TYPE_SEG_D_RW     = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_WRITE.bits,
        /// Data Read/Write, accessed
        const FLAGS_TYPE_SEG_D_RWA    = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_WRITE.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Data Read-Only, expand-down
        const FLAGS_TYPE_SEG_D_ROEXD  = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_EXPAND_DOWN.bits,
        /// Data Read-Only, expand-down, accessed
        const FLAGS_TYPE_SEG_D_ROEXDA = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_EXPAND_DOWN.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Data Read/Write, expand-down
        const FLAGS_TYPE_SEG_D_RWEXD  = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_WRITE.bits
                                      | FLAGS_TYPE_SEG_D_EXPAND_DOWN.bits,
        /// Data Read/Write, expand-down, accessed
        const FLAGS_TYPE_SEG_D_RWEXDA = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_WRITE.bits
                                      | FLAGS_TYPE_SEG_D_EXPAND_DOWN.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,

        /// Code Execute-Only
        const FLAGS_TYPE_SEG_C_EO     = FLAGS_TYPE_CODE.bits,
        /// Code Execute-Only, accessed
        const FLAGS_TYPE_SEG_C_EOA    = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Code Execute/Read
        const FLAGS_TYPE_SEG_C_ER     = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_C_READ.bits,
        /// Code Execute/Read, accessed
        const FLAGS_TYPE_SEG_C_ERA    = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_C_READ.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Code Execute-Only, conforming
        const FLAGS_TYPE_SEG_C_EOC    = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_C_CONFORMING.bits,
        /// Code Execute-Only, conforming, accessed
        const FLAGS_TYPE_SEG_C_EOCA   = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_C_CONFORMING.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Code Execute/Read, conforming
        const FLAGS_TYPE_SEG_C_ERC    = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_C_READ.bits
                                      | FLAGS_TYPE_SEG_C_CONFORMING.bits,
        /// Code Execute/Read, conforming, accessed
        const FLAGS_TYPE_SEG_C_ERCA   = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_C_READ.bits
                                      | FLAGS_TYPE_SEG_C_CONFORMING.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
    }
}

impl Flags {
    pub const BLANK: Flags = Flags { bits: 0 };

    pub const fn from_priv(dpl: PrivilegeLevel) -> Flags {
        Flags { bits: (dpl as u8) << 5 }
    }

    pub fn from_type(ty: Type) -> Flags {
        Flags { bits: ty.pack() }
    }

    pub const fn const_or(self, other: Self) -> Flags {
        Flags { bits: self.bits | other.bits }
    }

    pub const fn cond(self, cond: bool) -> Flags {
        Flags { bits: (-(cond as i8) as u8) & self.bits }
    }

    pub const fn const_mux(self, other: Self, cond: bool) -> Flags {
        self.cond(cond).const_or(other.cond(!cond))
    }
}
<|endoftext|>


<commit_before>//
// sprocketnes/rom.rs
//
// Author: Patrick Walton
//

use core::cast::transmute;
use core::libc::{O_RDONLY, c_int, size_t, ssize_t};
use core::libc;
use core::str;
use core::sys::size_of;
use core::vec;

// Blech! This really should go in the standard library!
struct Fd(c_int);
impl Drop for Fd {
    fn finalize(&self) {
        unsafe {
            libc::close(**self);
        }
    }
}

pub struct Rom {
    header: INesHeader,
    prg: ~[u8],         // PRG-ROM
    chr: ~[u8],         // CHR-ROM
}

impl Rom {
    static fn from_fd(fd: c_int) -> Rom {
        let read: &fn(sz: size_t) -> ~[u8] = |sz| {
            unsafe {
                let mut result = vec::from_elem(sz as uint, 0);
                assert libc::read(fd, transmute(&mut result[0]), sz) as size_t == sz;
                result
            }
        };

        let buffer = read(size_of::<INesHeader>() as size_t);
        let header = INesHeader {
            magic: [ buffer[0], buffer[1], buffer[2], buffer[3] ],
            prg_rom_size: buffer[4],
            chr_rom_size: buffer[5],
            flags_6: buffer[6],
            flags_7: buffer[7],
            prg_ram_size: buffer[8],
            flags_9: buffer[9],
            flags_10: buffer[10],
            zero: [ 0, ..5 ]
        };

        assert header.magic == [ 'N' as u8, 'E' as u8, 'S' as u8, 0x1a ];

        let prg_rom = read(header.prg_rom_size as size_t * 16384);
        let chr_rom = read(header.chr_rom_size as size_t * 8192);
        Rom { header: header, prg: prg_rom, chr: chr_rom }
    }

    static fn from_path(path: &str) -> Rom {
        unsafe {
            do str::as_c_str(path) |c_path| {
                // FIXME: O_RDONLY should be a c_int in the first place!
                let fd = Fd(libc::open(c_path, O_RDONLY as c_int, 0));
                Rom::from_fd(*fd)
            }
        }
    }
}

struct INesHeader {
    magic: [u8 * 4],    // 'N' 'E' 'S' '\x1a'
    prg_rom_size: u8,   // number of 16K units of PRG-ROM
    chr_rom_size: u8,   // number of 8K units of CHR-ROM
    flags_6: u8,
    flags_7: u8,
    prg_ram_size: u8,   // number of 8K units of PRG-RAM
    flags_9: u8,
    flags_10: u8,
    zero: [u8 * 5],     // always zero
}

impl INesHeader {
    fn mapper(&self) -> u8 { (self.flags_7 & 0xf0) | (self.flags_6 >> 4) }
    fn trainer(&self) -> bool { (self.flags_6 & 0x04) != 0 }

    fn to_str(&self) -> ~str {
        fmt!(
            "PRG-ROM size: %d\nCHR-ROM size: %d\nMapper: %d\nTrainer: %s",
            self.prg_rom_size as int,
            self.chr_rom_size as int,
            self.mapper() as int,
            if self.trainer() { "Yes" } else { "No" }
        )
    }
}

<commit_msg>Fix zero-length bug in read()<commit_after>//
// sprocketnes/rom.rs
//
// Author: Patrick Walton
//

use core::cast::transmute;
use core::libc::{O_RDONLY, c_int, size_t, ssize_t};
use core::libc;
use core::str;
use core::sys::size_of;
use core::vec;

// Blech! This really should go in the standard library!
struct Fd(c_int);
impl Drop for Fd {
    fn finalize(&self) {
        unsafe {
            libc::close(**self);
        }
    }
}

pub struct Rom {
    header: INesHeader,
    prg: ~[u8],         // PRG-ROM
    chr: ~[u8],         // CHR-ROM
}

impl Rom {
    static fn from_fd(fd: c_int) -> Rom {
        let read: &fn(sz: size_t) -> ~[u8] = |sz| {
            unsafe {
                let mut result = vec::from_elem(sz as uint, 0);
                if sz != 0 {
                    assert libc::read(fd, transmute(&mut result[0]), sz) as size_t == sz;
                }
                result
            }
        };

        let buffer = read(size_of::<INesHeader>() as size_t);
        let header = INesHeader {
            magic: [ buffer[0], buffer[1], buffer[2], buffer[3] ],
            prg_rom_size: buffer[4],
            chr_rom_size: buffer[5],
            flags_6: buffer[6],
            flags_7: buffer[7],
            prg_ram_size: buffer[8],
            flags_9: buffer[9],
            flags_10: buffer[10],
            zero: [ 0, ..5 ]
        };

        assert header.magic == [ 'N' as u8, 'E' as u8, 'S' as u8, 0x1a ];

        let prg_rom = read(header.prg_rom_size as size_t * 16384);
        let chr_rom = read(header.chr_rom_size as size_t * 8192);
        Rom { header: header, prg: prg_rom, chr: chr_rom }
    }

    static fn from_path(path: &str) -> Rom {
        unsafe {
            do str::as_c_str(path) |c_path| {
                // FIXME: O_RDONLY should be a c_int in the first place!
                let fd = Fd(libc::open(c_path, O_RDONLY as c_int, 0));
                Rom::from_fd(*fd)
            }
        }
    }
}

struct INesHeader {
    magic: [u8 * 4],    // 'N' 'E' 'S' '\x1a'
    prg_rom_size: u8,   // number of 16K units of PRG-ROM
    chr_rom_size: u8,   // number of 8K units of CHR-ROM
    flags_6: u8,
    flags_7: u8,
    prg_ram_size: u8,   // number of 8K units of PRG-RAM
    flags_9: u8,
    flags_10: u8,
    zero: [u8 * 5],     // always zero
}

impl INesHeader {
    fn mapper(&self) -> u8 { (self.flags_7 & 0xf0) | (self.flags_6 >> 4) }
    fn trainer(&self) -> bool { (self.flags_6 & 0x04) != 0 }

    fn to_str(&self) -> ~str {
        fmt!(
            "PRG-ROM size: %d\nCHR-ROM size: %d\nMapper: %d\nTrainer: %s",
            self.prg_rom_size as int,
            self.chr_rom_size as int,
            self.mapper() as int,
            if self.trainer() { "Yes" } else { "No" }
        )
    }
}

<|endoftext|>


<commit_before>/// Return two numbers found in a `Vec` that can be added up to a target, or
// `None` if no such numbers exist.
///
/// # Examples
///
/// ```
/// use targetsum::target_sum;
///
/// assert_eq!(Some((3, 7)), target_sum(&vec![1, 2, 3, 5, 7, 11, 13], 10));
/// assert_eq!(None, target_sum(&vec![1, 2, 3, 5, 7, 11, 13], 11));
/// ```
pub fn target_sum(search: &Vec<i32>, target: i32) -> Option<(i32, i32)> {
    if search.len() == 0 {
        return None;
    }
    // For some reason hash tables are not allowed so sort the vector and
    // search from the ends.
    let mut sorted_search = search.clone();
    sorted_search.sort();
    let mut lowest_index = 0;
    let mut highest_index = sorted_search.len() - 1;

    while lowest_index <= highest_index {
        match sorted_search.get(lowest_index) {
            Some(low) => match sorted_search.get(highest_index) {
                Some(high) => {
                    if low + high == target {
                        return Some((*low, *high));
                    }
                    if low + high > target {
                        if highest_index == 0 {
                            return None;
                        }
                        highest_index -= 1;
                    } else {
                        lowest_index += 1;
                    }
                },
                None => { break; }
            },
            None => { break; }
        }
    }
    None
}

#[test]
fn search_vector_empty() {
    assert_eq!(None, target_sum(&vec![], 11));
}

#[test]
fn search_vector_size_one() {
    assert_eq!(None, target_sum(&vec![5], 9));
    assert_eq!(Some((5, 5)), target_sum(&vec![5], 10));
}

#[test]
fn target_at_edges() {
    assert_eq!(Some((5, 5)), target_sum(&vec![1, 2, 5, 10], 10));
}

#[test]
fn target_same_number() {
    assert_eq!(Some((2, 2)), target_sum(&vec![1, 2, 2, 5, 10], 4));
}

#[test]
fn target_not_found() {
    assert_eq!(None, target_sum(&vec![1, 2, 3, 5, 7, 13, 17, 19, 23], 11));
}

#[test]
fn negative_target() {
    assert_eq!(
        Some((-23, 23)),
        target_sum(&vec![1, 2, 3, 5, 7, 13, 17, 19, 23, 29, 31, 37, -23], 0));
}

<commit_msg>Grammar fix.<commit_after>/// Return any two numbers found in a `Vec` that can be added up to a target, or
// `None` if no such numbers exist.
///
/// # Examples
///
/// ```
/// use targetsum::target_sum;
///
/// assert_eq!(Some((3, 7)), target_sum(&vec![1, 2, 3, 5, 7, 11, 13], 10));
/// assert_eq!(None, target_sum(&vec![1, 2, 3, 5, 7, 11, 13], 11));
/// ```
pub fn target_sum(search: &Vec<i32>, target: i32) -> Option<(i32, i32)> {
    if search.len() == 0 {
        return None;
    }
    // For some reason hash tables are not allowed so sort the vector and
    // search from the ends.
    let mut sorted_search = search.clone();
    sorted_search.sort();
    let mut lowest_index = 0;
    let mut highest_index = sorted_search.len() - 1;

    while lowest_index <= highest_index {
        match sorted_search.get(lowest_index) {
            Some(low) => match sorted_search.get(highest_index) {
                Some(high) => {
                    if low + high == target {
                        return Some((*low, *high));
                    }
                    if low + high > target {
                        if highest_index == 0 {
                            return None;
                        }
                        highest_index -= 1;
                    } else {
                        lowest_index += 1;
                    }
                },
                None => { break; }
            },
            None => { break; }
        }
    }
    None
}

#[test]
fn search_vector_empty() {
    assert_eq!(None, target_sum(&vec![], 11));
}

#[test]
fn search_vector_size_one() {
    assert_eq!(None, target_sum(&vec![5], 9));
    assert_eq!(Some((5, 5)), target_sum(&vec![5], 10));
}

#[test]
fn target_at_edges() {
    assert_eq!(Some((5, 5)), target_sum(&vec![1, 2, 5, 10], 10));
}

#[test]
fn target_same_number() {
    assert_eq!(Some((2, 2)), target_sum(&vec![1, 2, 2, 5, 10], 4));
}

#[test]
fn target_not_found() {
    assert_eq!(None, target_sum(&vec![1, 2, 3, 5, 7, 13, 17, 19, 23], 11));
}

#[test]
fn negative_target() {
    assert_eq!(
        Some((-23, 23)),
        target_sum(&vec![1, 2, 3, 5, 7, 13, 17, 19, 23, 29, 31, 37, -23], 0));
}

<|endoftext|>