<commit_before>extern crate core;

use std::mem;
use self::core::str::next_code_point;
use super::token::Token;
use super::token::Category;

pub struct StateFunction(pub fn(&mut Tokenizer) -> Option<StateFunction>);

/// The Tokenizer type is used to produce and store
/// tokens for the various language and format lexers.
pub struct Tokenizer {
    data: Vec<u8>,
    head: usize,
    tail: usize,
    tokens: Vec<Token>,
    pub states: Vec<StateFunction>,
}

/// Initializes a new tokenizer with the given data.
///
/// # Examples
///
/// ```
/// let tokenizer = luthor::tokenizer::new("luthor");
/// ```
pub fn new(data: &str) -> Tokenizer {
    Tokenizer{
      data: data.to_string().into_bytes(),
      head: 0,
      tail: 0,
      tokens: vec![],
      states: vec![]
    }
}

impl Tokenizer {
    /// Returns a copy of the tokens processed to date.
    ///
    /// # Examples
    ///
    /// ```
    /// let tokenizer = luthor::tokenizer::new("luthor");
    /// tokenizer.tokens();
    /// ```
    pub fn tokens(&self) -> Vec<Token> {
        self.tokens.clone()
    }

    /// Moves to the next character in the data.
    /// Does nothing if there is no more data to process.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut tokenizer = luthor::tokenizer::new("luthor");
    /// assert_eq!(tokenizer.current_char().unwrap(), 'l');
    /// tokenizer.advance();
    /// assert_eq!(tokenizer.current_char().unwrap(), 'u');
    /// ```
    pub fn advance(&mut self) {
        if self.has_more_data() {
            // Get the current character so that we can calculate
            // its byte length and advance the head appropriately.
            match self.current_char() {
                Some(c) => {
                    self.head += c.len_utf8();
                },
                None => (),
            }
        }
    }

    /// Determines whether or not there is more unprocessed data.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut tokenizer = luthor::tokenizer::new("l");
    /// assert_eq!(tokenizer.has_more_data(), true);
    /// tokenizer.advance();
    /// assert_eq!(tokenizer.has_more_data(), false);
    /// ```
    pub fn has_more_data(&self) -> bool {
        self.head < self.data.len()
    }

    /// Returns the character at the current position,
    /// unless all of the data has been processed.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut tokenizer = luthor::tokenizer::new("l");
    /// assert_eq!(tokenizer.current_char().unwrap(), 'l');
    /// tokenizer.advance();
    /// assert_eq!(tokenizer.current_char(), None);
    /// ```
    pub fn current_char(&self) -> Option<char> {
        if self.has_more_data() {
            // Create an iterator for the remaining data.
            let mut remaining_data = self.data[self.head..].iter();

            // Pull the first UTF-8 byte sequence and convert it to a char.
            next_code_point(&mut remaining_data).map(|code_point| {
                unsafe {
                    mem::transmute(code_point)
                }
            })
        } else {
            None
        }
    }

    /// Whether or not the remaining data starts
    /// with the specified string.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut tokenizer = luthor::tokenizer::new("luthor");
    /// assert!(tokenizer.starts_with("luth"));
    /// tokenizer.advance();
    /// assert!(tokenizer.starts_with("utho"));
    /// assert!(!tokenizer.starts_with("luth"));
    /// ```
    pub fn starts_with(&self, data: &str) -> bool {
        // Get a byte representation of the passed data
        // that we'll compare to the binary buffer.
        let data_bytes = data.as_bytes();

        // Don't even bother if the remaining data is smaller
        // than the string we're going to compare it to.
        let remaining_data_size = self.data.len() - self.head;
        if remaining_data_size >= data_bytes.len() {
            // There's enough data left. Take a leading slice of the same size for comparison.
            let leading_data = &self.data[self.head..(self.head+data_bytes.len())];

            // Compare!
            leading_data == data_bytes
        } else {
            // Not enough remaining data.
            false
        }
    }

    /// Creates and stores a token with the given category containing any
    /// data processed using `advance` since the last call to this method.
    ///
    /// # Examples
    ///
    /// ```
    /// use luthor::token::Category;
    /// let mut tokenizer = luthor::tokenizer::new("luthor");
    /// tokenizer.advance();
    /// tokenizer.advance();
    /// tokenizer.tokenize(Category::Text);
    /// assert_eq!(tokenizer.tokens()[0].lexeme, "lu");
    /// ```
    pub fn tokenize(&mut self, category: Category) {
        if self.head > self.tail {
            // Build the lexeme by slicing the currently
            // selected range out of the buffer.
            let lexeme = unsafe {
                String::from_utf8_unchecked(
                    self.data[self.tail..self.head].to_vec()
                )
            };
            let token = Token{
                lexeme: lexeme,
                category: category,
            };
            self.tokens.push(token);
            self.tail = self.head;
        }
    }

    /// Creates and stores a token with the given category and the
    /// next `amount` characters of the data. Before doing this, it
    /// tokenizes any previously processed characters with the generic
    /// Category::Text category.
    ///
    /// # Examples
    ///
    /// ```
    /// use luthor::token::Category;
    /// use luthor::token::Token;
    ///
    /// let mut tokenizer = luthor::tokenizer::new("luthor");
    /// tokenizer.advance();
    /// tokenizer.tokenize_next(5, Category::Keyword);
    /// assert_eq!(tokenizer.tokens()[0], Token{ lexeme: "l".to_string(), category: Category::Text});
    /// assert_eq!(tokenizer.tokens()[1], Token{ lexeme: "uthor".to_string(), category: Category::Keyword});
    /// ```
    pub fn tokenize_next(&mut self, amount: usize, category: Category) {
        // If there's any data that has yet
        // to be tokenized, take care of that.
        self.tokenize(Category::Text);

        // Mark the next series of characters.
        for _ in 0..amount { self.advance(); }

        // Tokenize the marked characters.
        self.tokenize(category);
    }
}

#[cfg(test)]
mod tests {
    use super::new;
    use super::super::token::Token;
    use super::super::token::Category;

    #[test]
    fn advance_does_nothing_when_there_is_no_more_data() {
        let data = "élégant";
        let mut tokenizer = new(data);

        // Try to go beyond the last character.
        for _ in 0..10 {
            tokenizer.advance();
        }

        assert!(!tokenizer.has_more_data())
    }

    #[test]
    fn has_more_data_works() {
        let data = "él";
        let mut tokenizer = new(data);

        tokenizer.advance();
        assert!(tokenizer.has_more_data());

        tokenizer.advance();
        assert!(!tokenizer.has_more_data());
    }

    #[test]
    fn current_char_returns_the_char_at_head() {
        let data = "él";
        let tokenizer = new(data);

        assert_eq!(tokenizer.current_char().unwrap(), 'é');
    }

    #[test]
    fn current_char_returns_none_if_at_the_end() {
        let data = "él";
        let mut tokenizer = new(data);
        tokenizer.advance();
        tokenizer.advance();

        assert_eq!(tokenizer.current_char(), None);
    }

    #[test]
    fn tokenize_creates_the_correct_token() {
        let data = "élégant";
        let mut tokenizer = new(data);
        tokenizer.advance();
        tokenizer.advance();
        tokenizer.tokenize(Category::Text);

        let token = tokenizer.tokens.pop().unwrap();
        let expected_token = Token{ lexeme: "él".to_string(), category: Category::Text};
        assert_eq!(token, expected_token);
    }

    #[test]
    fn tokenize_does_nothing_if_range_is_empty() {
        let data = "élégant";
        let mut tokenizer = new(data);
        tokenizer.tokenize(Category::Text);

        assert_eq!(tokenizer.tokens.len(), 0);
    }

    #[test]
    fn tokenize_next_tokenizes_previous_data_as_text() {
        let data = "élégant";
        let mut tokenizer = new(data);
        tokenizer.advance();
        tokenizer.advance();
        tokenizer.tokenize_next(1, Category::Keyword);

        let token = tokenizer.tokens.remove(0);
        let expected_token = Token{ lexeme: "él".to_string(), category: Category::Text};
        assert_eq!(token, expected_token);
    }

    #[test]
    fn tokenize_next_tokenizes_next_x_chars() {
        let data = "élégant";
        let mut tokenizer = new(data);
        tokenizer.advance();
        tokenizer.advance();
        tokenizer.tokenize_next(5, Category::Keyword);

        let token = tokenizer.tokens.pop().unwrap();
        let expected_token = Token{ lexeme: "égant".to_string(), category: Category::Keyword};
        assert_eq!(token, expected_token);
    }

    #[test]
    fn tokenize_next_takes_at_most_what_is_left() {
        let data = "élégant";
        let mut tokenizer = new(data);
        tokenizer.advance();
        tokenizer.advance();
        tokenizer.tokenize_next(15, Category::Keyword);

        let token = tokenizer.tokens.pop().unwrap();
        let expected_token = Token{ lexeme: "égant".to_string(), category: Category::Keyword};
        assert_eq!(token, expected_token);
    }
}
<commit_msg>Don't export has_more_data function.<commit_after>extern crate core;

use std::mem;
use self::core::str::next_code_point;
use super::token::Token;
use super::token::Category;

pub struct StateFunction(pub fn(&mut Tokenizer) -> Option<StateFunction>);

/// The Tokenizer type is used to produce and store
/// tokens for the various language and format lexers.
pub struct Tokenizer {
    data: Vec<u8>,
    head: usize,
    tail: usize,
    tokens: Vec<Token>,
    pub states: Vec<StateFunction>,
}

/// Initializes a new tokenizer with the given data.
///
/// # Examples
///
/// ```
/// let tokenizer = luthor::tokenizer::new("luthor");
/// ```
pub fn new(data: &str) -> Tokenizer {
    Tokenizer{
      data: data.to_string().into_bytes(),
      head: 0,
      tail: 0,
      tokens: vec![],
      states: vec![]
    }
}

impl Tokenizer {
    /// Returns a copy of the tokens processed to date.
    ///
    /// # Examples
    ///
    /// ```
    /// let tokenizer = luthor::tokenizer::new("luthor");
    /// tokenizer.tokens();
    /// ```
    pub fn tokens(&self) -> Vec<Token> {
        self.tokens.clone()
    }

    /// Moves to the next character in the data.
    /// Does nothing if there is no more data to process.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut tokenizer = luthor::tokenizer::new("luthor");
    /// assert_eq!(tokenizer.current_char().unwrap(), 'l');
    /// tokenizer.advance();
    /// assert_eq!(tokenizer.current_char().unwrap(), 'u');
    /// ```
    pub fn advance(&mut self) {
        if self.has_more_data() {
            // Get the current character so that we can calculate
            // its byte length and advance the head appropriately.
            match self.current_char() {
                Some(c) => {
                    self.head += c.len_utf8();
                },
                None => (),
            }
        }
    }

    /// Returns the character at the current position,
    /// unless all of the data has been processed.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut tokenizer = luthor::tokenizer::new("l");
    /// assert_eq!(tokenizer.current_char().unwrap(), 'l');
    /// tokenizer.advance();
    /// assert_eq!(tokenizer.current_char(), None);
    /// ```
    pub fn current_char(&self) -> Option<char> {
        if self.has_more_data() {
            // Create an iterator for the remaining data.
            let mut remaining_data = self.data[self.head..].iter();

            // Pull the first UTF-8 byte sequence and convert it to a char.
            next_code_point(&mut remaining_data).map(|code_point| {
                unsafe {
                    mem::transmute(code_point)
                }
            })
        } else {
            None
        }
    }

    /// Whether or not the remaining data starts
    /// with the specified string.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut tokenizer = luthor::tokenizer::new("luthor");
    /// assert!(tokenizer.starts_with("luth"));
    /// tokenizer.advance();
    /// assert!(tokenizer.starts_with("utho"));
    /// assert!(!tokenizer.starts_with("luth"));
    /// ```
    pub fn starts_with(&self, data: &str) -> bool {
        // Get a byte representation of the passed data
        // that we'll compare to the binary buffer.
        let data_bytes = data.as_bytes();

        // Don't even bother if the remaining data is smaller
        // than the string we're going to compare it to.
        let remaining_data_size = self.data.len() - self.head;
        if remaining_data_size >= data_bytes.len() {
            // There's enough data left. Take a leading slice of the same size for comparison.
            let leading_data = &self.data[self.head..(self.head+data_bytes.len())];

            // Compare!
            leading_data == data_bytes
        } else {
            // Not enough remaining data.
            false
        }
    }

    /// Creates and stores a token with the given category containing any
    /// data processed using `advance` since the last call to this method.
    ///
    /// # Examples
    ///
    /// ```
    /// use luthor::token::Category;
    /// let mut tokenizer = luthor::tokenizer::new("luthor");
    /// tokenizer.advance();
    /// tokenizer.advance();
    /// tokenizer.tokenize(Category::Text);
    /// assert_eq!(tokenizer.tokens()[0].lexeme, "lu");
    /// ```
    pub fn tokenize(&mut self, category: Category) {
        if self.head > self.tail {
            // Build the lexeme by slicing the currently
            // selected range out of the buffer.
            let lexeme = unsafe {
                String::from_utf8_unchecked(
                    self.data[self.tail..self.head].to_vec()
                )
            };
            let token = Token{
                lexeme: lexeme,
                category: category,
            };
            self.tokens.push(token);
            self.tail = self.head;
        }
    }

    /// Creates and stores a token with the given category and the
    /// next `amount` characters of the data. Before doing this, it
    /// tokenizes any previously processed characters with the generic
    /// Category::Text category.
    ///
    /// # Examples
    ///
    /// ```
    /// use luthor::token::Category;
    /// use luthor::token::Token;
    ///
    /// let mut tokenizer = luthor::tokenizer::new("luthor");
    /// tokenizer.advance();
    /// tokenizer.tokenize_next(5, Category::Keyword);
    /// assert_eq!(tokenizer.tokens()[0], Token{ lexeme: "l".to_string(), category: Category::Text});
    /// assert_eq!(tokenizer.tokens()[1], Token{ lexeme: "uthor".to_string(), category: Category::Keyword});
    /// ```
    pub fn tokenize_next(&mut self, amount: usize, category: Category) {
        // If there's any data that has yet
        // to be tokenized, take care of that.
        self.tokenize(Category::Text);

        // Mark the next series of characters.
        for _ in 0..amount { self.advance(); }

        // Tokenize the marked characters.
        self.tokenize(category);
    }

    /// Determines whether or not there is more unprocessed data.
    fn has_more_data(&self) -> bool {
        self.head < self.data.len()
    }
}

#[cfg(test)]
mod tests {
    use super::new;
    use super::super::token::Token;
    use super::super::token::Category;

    #[test]
    fn advance_does_nothing_when_there_is_no_more_data() {
        let data = "élégant";
        let mut tokenizer = new(data);

        // Try to go beyond the last character.
        for _ in 0..10 {
            tokenizer.advance();
        }

        assert!(!tokenizer.has_more_data())
    }

    #[test]
    fn current_char_returns_the_char_at_head() {
        let data = "él";
        let tokenizer = new(data);

        assert_eq!(tokenizer.current_char().unwrap(), 'é');
    }

    #[test]
    fn current_char_returns_none_if_at_the_end() {
        let data = "él";
        let mut tokenizer = new(data);
        tokenizer.advance();
        tokenizer.advance();

        assert_eq!(tokenizer.current_char(), None);
    }

    #[test]
    fn tokenize_creates_the_correct_token() {
        let data = "élégant";
        let mut tokenizer = new(data);
        tokenizer.advance();
        tokenizer.advance();
        tokenizer.tokenize(Category::Text);

        let token = tokenizer.tokens.pop().unwrap();
        let expected_token = Token{ lexeme: "él".to_string(), category: Category::Text};
        assert_eq!(token, expected_token);
    }

    #[test]
    fn tokenize_does_nothing_if_range_is_empty() {
        let data = "élégant";
        let mut tokenizer = new(data);
        tokenizer.tokenize(Category::Text);

        assert_eq!(tokenizer.tokens.len(), 0);
    }

    #[test]
    fn tokenize_next_tokenizes_previous_data_as_text() {
        let data = "élégant";
        let mut tokenizer = new(data);
        tokenizer.advance();
        tokenizer.advance();
        tokenizer.tokenize_next(1, Category::Keyword);

        let token = tokenizer.tokens.remove(0);
        let expected_token = Token{ lexeme: "él".to_string(), category: Category::Text};
        assert_eq!(token, expected_token);
    }

    #[test]
    fn tokenize_next_tokenizes_next_x_chars() {
        let data = "élégant";
        let mut tokenizer = new(data);
        tokenizer.advance();
        tokenizer.advance();
        tokenizer.tokenize_next(5, Category::Keyword);

        let token = tokenizer.tokens.pop().unwrap();
        let expected_token = Token{ lexeme: "égant".to_string(), category: Category::Keyword};
        assert_eq!(token, expected_token);
    }

    #[test]
    fn tokenize_next_takes_at_most_what_is_left() {
        let data = "élégant";
        let mut tokenizer = new(data);
        tokenizer.advance();
        tokenizer.advance();
        tokenizer.tokenize_next(15, Category::Keyword);

        let token = tokenizer.tokens.pop().unwrap();
        let expected_token = Token{ lexeme: "égant".to_string(), category: Category::Keyword};
        assert_eq!(token, expected_token);
    }
}
<|endoftext|>


<commit_before>extern crate toml;
extern crate rustc_serialize;
extern crate walkdir;
extern crate rpf;

use toml::decode;
use error::YabsError;
use ext::*;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, json};
use walkdir::WalkDir;

use std::ffi::OsStr;
use std::path::PathBuf;

#[derive(Debug,Default,RustcDecodable,RustcEncodable,Clone,PartialEq)]
pub struct Profile {
    name: String,
    proj_desc: Option<ProjDesc>,
    inst_desc: Option<InstallDesc>,
    doc_desc: Option<DocDesc>,
}

#[derive(Debug,Default,RustcDecodable,RustcEncodable)]
pub struct BuildFile {
    profiles: Vec<Profile>,
}

impl BuildFile {
    pub fn from_file(file: &str) -> Result<BuildFile, Vec<YabsError>> {
        let mut build_file: BuildFile = Default::default();
        parse_toml_file(file)
            .and_then(|toml| {
                for (key, table) in toml {
                    let mut profile: Profile = Default::default();
                    profile.name = key.clone();
                    match table {
                        toml::Value::Table(inner_table) => {
                            for (key, table) in inner_table {
                                match key.as_ref() {
                                    "project" => {
                                        profile.proj_desc = ProjDesc::from_toml_table(table).ok()
                                    }
                                    "install" => {
                                        profile.inst_desc = InstallDesc::from_toml_table(table).ok()
                                    }
                                    "doc" => {
                                        profile.doc_desc = DocDesc::from_toml_table(table).ok()
                                    }
                                    _ => (),
                                }
                            }
                        }
                        _ => (),
                    };
                    build_file.profiles.push(profile);
                }
                Ok(build_file)
            })
            .map_err(|err| err)
    }

    pub fn print_as_json(&self) {
        for profile in &self.profiles {
            profile.print_json();
        }
    }

    pub fn print_profile_as_json(&self, name: String) {
        for profile in &self.profiles {
            if profile.name == name {
                profile.print_json();
            }
        }
    }

    pub fn print_sources(&self) -> Result<(), YabsError> {
        for profile in &self.profiles {
            println!("{}", profile.name);
            if let Some(proj) = profile.proj_desc.as_ref() {
                let sources = try!(proj.gen_obj_list());
                for file in sources.files {
                    println!("{}", file.display());
                }
            }
        }
        Ok(())
    }
}

#[derive(Debug,Default,RustcDecodable,RustcEncodable,Clone,PartialEq)]
pub struct ProjDesc {
    name: Option<String>,
    target: Option<String>,
    lang: Option<String>,
    os: Option<String>,
    version: Option<String>,
    compiler: Option<String>,
    src: Option<Vec<String>>,
    libs: Option<Vec<String>>,
    lib_dir: Option<Vec<String>>,
    inc: Option<Vec<String>>,
    inc_dir: Option<Vec<String>>,
    cflags: Option<String>,
    lflags: Option<String>,
    ignore: Option<Vec<String>>,
    before_script: Option<Vec<String>>,
    after_script: Option<Vec<String>>,
    lib: Option<bool>,
    ar: Option<String>,
}

#[derive(Default,RustcDecodable,RustcEncodable,PartialEq)]
struct Sources {
    files: Vec<PathBuf>,
    objects: Vec<PathBuf>,
}

impl ProjDesc {
    fn gen_obj_list(&self) -> Result<Sources, YabsError> {
        let mut sources = Sources::new();
        for entry in WalkDir::new(".") {
            let entry = try!(entry);
            if entry.path().is_file() {
                let lang = &self.lang.clone().unwrap();
                let file_ext = entry.path().extension().unwrap_or(OsStr::new(""));
                if let Some(ext) = file_ext.to_str() {
                    if let Some(lang) = self.lang.clone() {
                        if ext == lang {
                            sources.files.push(PathBuf::from(entry.path()));
                        }
                    }
                }
            }
        }
        Ok(sources)
    }
}

// Descibe how to install this project
#[derive(Debug,Default,RustcDecodable,RustcEncodable,Clone,PartialEq)]
pub struct InstallDesc {
    prefix: Option<String>,
}

#[derive(Debug,Default,RustcDecodable,RustcEncodable,Clone,PartialEq)]
pub struct DocDesc {
    doc: Option<String>,
}

// General trait for any descriptions
pub trait Desc<T> {
    fn new() -> T;
    fn from_file(file: &str, name: &str) -> Result<T, Vec<YabsError>>;
    fn from_toml_table(table: toml::Value) -> Result<T, YabsError>;
    fn print_json(&self);
}

impl<T: Decodable + Encodable + Default> Desc<T> for T {
    fn new() -> T {
        Default::default()
    }

    fn from_file(file: &str, name: &str) -> Result<T, Vec<YabsError>> {
        parse_toml_file(file).and_then(|toml| {
            toml.get(name)
                .ok_or(vec![YabsError::NoDesc(name.to_owned())])
                .and_then(|desc| {
                    Decodable::decode(&mut toml::Decoder::new(desc.clone()))
                        .map_err(|err| vec![YabsError::TomlDecode(err)])
                })
        })
    }

    fn from_toml_table(table: toml::Value) -> Result<T, YabsError> {
        Ok(try!(Decodable::decode(&mut toml::Decoder::new(table.clone()))))
    }

    fn print_json(&self) {
        println!("{}", json::as_pretty_json(&self));
    }
}
<commit_msg>build: rename function `gen_obj_list`<commit_after>extern crate toml;
extern crate rustc_serialize;
extern crate walkdir;
extern crate rpf;

use toml::decode;
use error::YabsError;
use ext::*;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, json};
use walkdir::WalkDir;

use std::ffi::OsStr;
use std::path::PathBuf;

#[derive(Debug,Default,RustcDecodable,RustcEncodable,Clone,PartialEq)]
pub struct Profile {
    name: String,
    proj_desc: Option<ProjDesc>,
    inst_desc: Option<InstallDesc>,
    doc_desc: Option<DocDesc>,
}

#[derive(Debug,Default,RustcDecodable,RustcEncodable)]
pub struct BuildFile {
    profiles: Vec<Profile>,
}

impl BuildFile {
    pub fn from_file(file: &str) -> Result<BuildFile, Vec<YabsError>> {
        let mut build_file: BuildFile = Default::default();
        parse_toml_file(file)
            .and_then(|toml| {
                for (key, table) in toml {
                    let mut profile: Profile = Default::default();
                    profile.name = key.clone();
                    match table {
                        toml::Value::Table(inner_table) => {
                            for (key, table) in inner_table {
                                match key.as_ref() {
                                    "project" => {
                                        profile.proj_desc = ProjDesc::from_toml_table(table).ok()
                                    }
                                    "install" => {
                                        profile.inst_desc = InstallDesc::from_toml_table(table).ok()
                                    }
                                    "doc" => {
                                        profile.doc_desc = DocDesc::from_toml_table(table).ok()
                                    }
                                    _ => (),
                                }
                            }
                        }
                        _ => (),
                    };
                    build_file.profiles.push(profile);
                }
                Ok(build_file)
            })
            .map_err(|err| err)
    }

    pub fn print_as_json(&self) {
        for profile in &self.profiles {
            profile.print_json();
        }
    }

    pub fn print_profile_as_json(&self, name: String) {
        for profile in &self.profiles {
            if profile.name == name {
                profile.print_json();
            }
        }
    }

    pub fn print_sources(&self) -> Result<(), YabsError> {
        for profile in &self.profiles {
            println!("{}", profile.name);
            if let Some(proj) = profile.proj_desc.as_ref() {
                let sources = try!(proj.gen_file_list());
                for file in sources.files {
                    println!("{}", file.display());
                }
            }
        }
        Ok(())
    }
}

#[derive(Debug,Default,RustcDecodable,RustcEncodable,Clone,PartialEq)]
pub struct ProjDesc {
    name: Option<String>,
    target: Option<String>,
    lang: Option<String>,
    os: Option<String>,
    version: Option<String>,
    compiler: Option<String>,
    src: Option<Vec<String>>,
    libs: Option<Vec<String>>,
    lib_dir: Option<Vec<String>>,
    inc: Option<Vec<String>>,
    inc_dir: Option<Vec<String>>,
    cflags: Option<String>,
    lflags: Option<String>,
    ignore: Option<Vec<String>>,
    before_script: Option<Vec<String>>,
    after_script: Option<Vec<String>>,
    lib: Option<bool>,
    ar: Option<String>,
}

#[derive(Default,RustcDecodable,RustcEncodable,PartialEq)]
struct Sources {
    files: Vec<PathBuf>,
    objects: Vec<PathBuf>,
}

impl ProjDesc {
    fn gen_file_list(&self) -> Result<Sources, YabsError> {
        let mut sources = Sources::new();
        for entry in WalkDir::new(".") {
            let entry = try!(entry);
            if entry.path().is_file() {
                let file_ext = entry.path().extension().unwrap_or(OsStr::new(""));
                if let Some(ext) = file_ext.to_str() {
                    if let Some(lang) = self.lang.clone() {
                        if ext == lang {
                            sources.files.push(PathBuf::from(entry.path()));
                        }
                    }
                }
            }
        }
        Ok(sources)
    }
}

// Descibe how to install this project
#[derive(Debug,Default,RustcDecodable,RustcEncodable,Clone,PartialEq)]
pub struct InstallDesc {
    prefix: Option<String>,
}

#[derive(Debug,Default,RustcDecodable,RustcEncodable,Clone,PartialEq)]
pub struct DocDesc {
    doc: Option<String>,
}

// General trait for any descriptions
pub trait Desc<T> {
    fn new() -> T;
    fn from_file(file: &str, name: &str) -> Result<T, Vec<YabsError>>;
    fn from_toml_table(table: toml::Value) -> Result<T, YabsError>;
    fn print_json(&self);
}

impl<T: Decodable + Encodable + Default> Desc<T> for T {
    fn new() -> T {
        Default::default()
    }

    fn from_file(file: &str, name: &str) -> Result<T, Vec<YabsError>> {
        parse_toml_file(file).and_then(|toml| {
            toml.get(name)
                .ok_or(vec![YabsError::NoDesc(name.to_owned())])
                .and_then(|desc| {
                    Decodable::decode(&mut toml::Decoder::new(desc.clone()))
                        .map_err(|err| vec![YabsError::TomlDecode(err)])
                })
        })
    }

    fn from_toml_table(table: toml::Value) -> Result<T, YabsError> {
        Ok(try!(Decodable::decode(&mut toml::Decoder::new(table.clone()))))
    }

    fn print_json(&self) {
        println!("{}", json::as_pretty_json(&self));
    }
}
<|endoftext|>


<commit_before>
use vertex::{RawVertex, Vertex};
use edge::{RawEdge, Edge};
use graph::TraversableToVertex;
use path::{Path, Element};
use std::iter::Extend;

// use std::iter::Iterator;

// define a traversal as a series of stages

pub struct GraphQuery {
    // many paths
    pub paths: Vec<Path>
}

impl GraphQuery {
    pub fn new(vertices: Vec<Vertex>) -> GraphQuery {
        // create a new path for each proxy, add the proxy
        let mut paths = Vec::new();
        for p in vertices {
            let mut path = Path::new(p);
            paths.push(path)
        }
        GraphQuery{paths:paths}
    }

    pub fn empty() -> GraphQuery {
        // return an empty graph query
        GraphQuery{paths:Vec::new()}
    }

    pub fn get_paths(&self) -> &Vec<Path> {
        &self.paths
    }
    pub fn push(&mut self, path:Path) {
        self.paths.push(path)
    }

    /*
    generic mapper for our queries
    future this may use worker threads to perform
    traversals

    TODO make sure that if nothing comes back we don't keep it in the path

     */
    fn map<F: Fn(&Path) -> Vec<Element>>(&self, closure: F) -> GraphQuery  {
        let mut result = GraphQuery::empty(); // result
        for path in self.paths.iter() {
            let mut tmp = closure(&path);
            // let mut tmp2 = tmp.as_slice();
            // currently gets back a Vec<Path> but what if it gets Elements?
            let new_elements = path.permute(&tmp);
            result.paths.extend(new_elements);
        }
        result
    }

    pub fn outV(&self, labels: &[&str]) -> GraphQuery {
        // map can figure out the rest
        let f = |path: &Path| {
            //take the final element in the path
            let element = path.last().unwrap();

            let result : Vec<Element> = match element {
                &Element::Vertex(v) =>
                    v.outV(&labels).iter().map(|v| Element::Vertex(*v)).collect(),
                    // Vec::new(),
                &Element::Edge(ref e) =>
                    Vec::new()
            };
            // apply outV
            result
        };
        self.map(f)
    }

    pub fn filter<F: Fn(&Path) -> bool>(&self, closure: F) -> GraphQuery {
        let gq = GraphQuery::empty();

        gq
    }

//    pub fn inV(&self) -> GraphQuery {
//        let g = GraphQuery::empty();
//        let f = |element: &Element| {
//            element.inV()
//        };
//        self.map(f)
//    }
}
<commit_msg>graph filtering<commit_after>
use vertex::{RawVertex, Vertex};
use edge::{RawEdge, Edge};
use graph::TraversableToVertex;
use path::{Path, Element};
use std::iter::Extend;
use std::iter::Filter;

// use std::iter::Iterator;

// define a traversal as a series of stages

pub struct GraphQuery {
    // many paths
    pub paths: Vec<Path>
}

impl GraphQuery {
    pub fn new(vertices: Vec<Vertex>) -> GraphQuery {
        // create a new path for each proxy, add the proxy
        let mut paths = Vec::new();
        for p in vertices {
            let mut path = Path::new(p);
            paths.push(path)
        }
        GraphQuery{paths:paths}
    }

    pub fn empty() -> GraphQuery {
        // return an empty graph query
        GraphQuery{paths:Vec::new()}
    }

    pub fn get_paths(&self) -> &Vec<Path> {
        &self.paths
    }
    pub fn push(&mut self, path:Path) {
        self.paths.push(path)
    }

    /*
    generic mapper for our queries
    future this may use worker threads to perform
    traversals

    TODO make sure that if nothing comes back we don't keep it in the path

     */
    fn map<F: Fn(&Path) -> Vec<Element>>(&self, closure: F) -> GraphQuery  {
        let mut result = GraphQuery::empty(); // result
        for path in self.paths.iter() {
            let mut tmp = closure(&path);
            // let mut tmp2 = tmp.as_slice();
            // currently gets back a Vec<Path> but what if it gets Elements?
            let new_elements = path.permute(&tmp);
            result.paths.extend(new_elements);
        }
        result
    }

    pub fn outV(&self, labels: &[&str]) -> GraphQuery {
        // map can figure out the rest
        let f = |path: &Path| {
            //take the final element in the path
            let element = path.last().unwrap();

            let result : Vec<Element> = match element {
                &Element::Vertex(v) =>
                    v.outV(&labels).iter().map(|v| Element::Vertex(*v)).collect(),
                    // Vec::new(),
                &Element::Edge(ref e) =>
                    Vec::new()
            };
            // apply outV
            result
        };
        self.map(f)
    }

    pub fn filter<F: Fn(&Path) -> bool>(&self, closure: F) -> GraphQuery {
        let result = GraphQuery::empty();
        // apply the filter to each path
        let tmp : Vec<Path> = self.paths.iter().filter(closure).collect();
        result.paths = tmp;
        return result
    }

//    pub fn inV(&self) -> GraphQuery {
//        let g = GraphQuery::empty();
//        let f = |element: &Element| {
//            element.inV()
//        };
//        self.map(f)
//    }
}
<|endoftext|>


<commit_before>use cgmath;
use mint;

use cgmath::Rotation3;
use input::{Input, Key, KeyAxis};
use object::Object;

#[derive(Clone, Debug)]
struct Axes {
    pub forward: Option<KeyAxis>,
    pub strafing: Option<KeyAxis>,
    pub vertical: Option<KeyAxis>,
}

impl Default for Axes {
    fn default() -> Self {
        Axes {
            forward: Some(KeyAxis {
                pos: Key::W,
                neg: Key::S,
            }),
            strafing: Some(KeyAxis {
                pos: Key::D,
                neg: Key::A,
            }),
            vertical: None,
        }
    }
}

/// Controls for first person camera.
pub struct FirstPerson {
    object: Object,
    position: mint::Point3<f32>,
    yaw: f32,
    pitch: f32,
    move_speed: f32,
    look_speed: f32,
    axes: Axes,
    vertical_move: bool,
    vertical_look: bool,
}

/// Constructs custom [`FirstPerson`](struct.FirstPerson.html) controls.
pub struct Builder {
    object: Object,
    position: mint::Point3<f32>,
    yaw: f32,
    pitch: f32,
    move_speed: f32,
    look_speed: f32,
    axes: Axes,
    vertical_move: bool,
    vertical_look: bool,
}

impl Builder {
    /// Create new `Builder` with default parameters.
    pub fn new(object: &Object) -> Self {
        Builder {
            object: object.clone(),
            position: [0.0, 0.0, 0.0].into(),
            yaw: 0.0,
            pitch: 0.0,
            move_speed: 1.0,
            look_speed: 0.5,
            axes: Axes::default(),
            vertical_move: true,
            vertical_look: true,
        }
    }

    /// Set the initial yaw angle in radians.
    ///
    /// Default is 0.0.
    pub fn yaw(
        &mut self,
        yaw: f32,
    ) -> &mut Self {
        self.yaw = yaw;
        self
    }

    /// Set the initial pitch angle in radians.
    ///
    /// Defaults to 0.0.
    pub fn pitch(
        &mut self,
        pitch: f32,
    ) -> &mut Self {
        self.pitch = pitch;
        self
    }

    /// Set the initial position.
    ///
    /// Defaults to the world origin.
    pub fn position<P>(
        &mut self,
        position: P,
    ) -> &mut Self
    where
        P: Into<mint::Point3<f32>>,
    {
        self.position = position.into();
        self
    }

    /// Setup the movement speed in world units per second.
    ///
    /// Defaults to 1.0 world units per second.
    pub fn move_speed(
        &mut self,
        speed: f32,
    ) -> &mut Self {
        self.move_speed = speed;
        self
    }

    /// Setup mouse sensitivity.
    ///
    /// Defaults to 0.5
    pub fn look_speed(
        &mut self,
        speed: f32,
    ) -> &mut Self {
        self.look_speed = speed;
        self
    }

    /// Setup whether controlled object should move along `y` axis when looking
    /// down or up.
    ///
    /// Defaults to true.
    pub fn vertical_movement(
        &mut self,
        value: bool,
    ) -> &mut Self {
        self.vertical_move = value;
        self
    }

    /// Setup whether controlled object can adjust pitch using mouse.
    ///
    /// Defaults to true.
    pub fn vertical_look(
        &mut self,
        value: bool,
    ) -> &mut Self {
        self.vertical_look = value;
        self
    }

    /// Setup key axis for moving forward/backward.
    ///
    /// Defaults to `W` and `S` keys.
    pub fn axis_forward(
        &mut self,
        axis: Option<KeyAxis>,
    ) -> &mut Self {
        self.axes.forward = axis;
        self
    }

    /// Setup button for "strafing" left/right.
    ///
    /// Defaults to `A` and `D` keys.
    pub fn axis_strafing(
        &mut self,
        axis: Option<KeyAxis>,
    ) -> &mut Self {
        self.axes.strafing = axis;
        self
    }

    /// Setup button for moving up/down.
    ///
    /// Defaults to `None`.
    pub fn axis_vertical(
        &mut self,
        axis: Option<KeyAxis>,
    ) -> &mut Self {
        self.axes.vertical = axis;
        self
    }

    /// Finalize builder and create new `FirstPerson` controls.
    pub fn build(&mut self) -> FirstPerson {
        FirstPerson {
            object: self.object.clone(),
            position: self.position,
            yaw: self.yaw,
            pitch: self.pitch,
            move_speed: self.move_speed,
            look_speed: self.look_speed,
            axes: self.axes.clone(),
            vertical_move: self.vertical_move,
            vertical_look: self.vertical_look,
        }
    }
}

impl FirstPerson {
    /// Create a `Builder`.
    pub fn builder(object: &Object) -> Builder {
        Builder::new(object)
    }

    /// Create `FirstPerson` controls with default parameters.
    pub fn default(object: &Object) -> Self {
        Self::builder(object).build()
    }

    /// Sets the yaw angle in radians.
    pub fn set_yaw(
        &mut self,
        yaw: f32,
    ) -> &mut Self {
        self.yaw = yaw;
        self
    }

    /// Sets the pitch angle in radians.
    pub fn set_pitch(
        &mut self,
        pitch: f32,
    ) -> &mut Self {
        self.pitch = pitch;
        self
    }

    /// Sets the object position.
    pub fn set_position<P>(
        &mut self,
        position: P,
    ) -> &mut Self
    where
        P: Into<mint::Point3<f32>>,
    {
        self.position = position.into();
        self
    }

    /// Sets the movement speed in world units per second.
    pub fn set_move_speed(
        &mut self,
        speed: f32,
    ) -> &mut Self {
        self.move_speed = speed;
        self
    }

    /// Sets the mouse sensitivity.
    pub fn set_look_speed(
        &mut self,
        speed: f32,
    ) -> &mut Self {
        self.look_speed = speed;
        self
    }

    /// Specifies whether controlled object should move along `y` axis when looking
    /// down or up.
    pub fn set_vertical_movement(
        &mut self,
        value: bool,
    ) -> &mut Self {
        self.vertical_move = value;
        self
    }

    /// Specifies whether controlled object can adjust pitch using mouse.
    pub fn set_vertical_look(
        &mut self,
        value: bool,
    ) -> &mut Self {
        self.vertical_look = value;
        self
    }

    /// Sets the key axis for moving forward/backward.
    pub fn set_axis_forward(
        &mut self,
        axis: Option<KeyAxis>,
    ) -> &mut Self {
        self.axes.forward = axis;
        self
    }

    /// Sets the button for "strafing" left/right.
    pub fn set_axis_strafing(
        &mut self,
        axis: Option<KeyAxis>,
    ) -> &mut Self {
        self.axes.strafing = axis;
        self
    }

    /// Setup button for moving up/down.
    ///
    /// Defaults to `None`.
    pub fn set_axis_vertical(
        &mut self,
        axis: Option<KeyAxis>,
    ) -> &mut Self {
        self.axes.vertical = axis;
        self
    }

    /// Updates the position, yaw, and pitch of the controlled object according to
    /// the last frame input.
    pub fn update(
        &mut self,
        input: &Input,
    ) {
        let dtime = input.delta_time();
        let dlook = dtime * self.look_speed;

        let mouse = input.mouse_delta_raw();

        self.yaw += dlook * mouse.x;
        if self.vertical_look {
            self.pitch += dlook * mouse.y;
        }

        self.axes
            .vertical
            .map(|a| if let Some(time) = a.timed(input) {
                self.position.y += self.move_speed * time;
            });

        self.axes
            .forward
            .map(|a| if let Some(time) = a.timed(input) {
                self.position.x += self.move_speed * time * self.yaw.sin();
                self.position.z -= self.move_speed * time * self.yaw.cos();
                if self.vertical_move {
                    self.position.y -= self.move_speed * time * self.pitch.sin();
                }
            });
        self.axes
            .strafing
            .map(|a| if let Some(time) = a.timed(input) {
                self.position.x += self.move_speed * time * self.yaw.cos();
                self.position.z += self.move_speed * time * self.yaw.sin();
            });

        let yrot = cgmath::Quaternion::from_angle_y(cgmath::Rad(-self.yaw));
        let xrot = cgmath::Quaternion::from_angle_x(cgmath::Rad(-self.pitch));
        self.object.set_transform(self.position, yrot * xrot, 1.0);
    }
}
<commit_msg>Add optional pitch range to FirstPersonControls<commit_after>use cgmath;
use mint;
use std::ops;

use cgmath::Rotation3;
use input::{Input, Key, KeyAxis};
use object::Object;
use std::f32::consts::PI;

#[derive(Clone, Debug)]
struct Axes {
    pub forward: Option<KeyAxis>,
    pub strafing: Option<KeyAxis>,
    pub vertical: Option<KeyAxis>,
}

impl Default for Axes {
    fn default() -> Self {
        Axes {
            forward: Some(KeyAxis {
                pos: Key::W,
                neg: Key::S,
            }),
            strafing: Some(KeyAxis {
                pos: Key::D,
                neg: Key::A,
            }),
            vertical: None,
        }
    }
}

/// Controls for first person camera.
pub struct FirstPerson {
    object: Object,
    position: mint::Point3<f32>,
    yaw: f32,
    pitch: f32,
    pitch_range: Option<ops::Range<f32>>,
    move_speed: f32,
    look_speed: f32,
    axes: Axes,
    vertical_move: bool,
    vertical_look: bool,
}

/// Constructs custom [`FirstPerson`](struct.FirstPerson.html) controls.
pub struct Builder {
    object: Object,
    position: mint::Point3<f32>,
    pitch_range: Option<ops::Range<f32>>,
    yaw: f32,
    pitch: f32,
    move_speed: f32,
    look_speed: f32,
    axes: Axes,
    vertical_move: bool,
    vertical_look: bool,
}

impl Builder {
    /// Create new `Builder` with default parameters.
    pub fn new(object: &Object) -> Self {
        Builder {
            object: object.clone(),
            position: [0.0, 0.0, 0.0].into(),
            yaw: 0.0,
            pitch: 0.0,
            pitch_range: Some(-PI / 2.0 .. PI / 2.0),
            move_speed: 1.0,
            look_speed: 0.5,
            axes: Axes::default(),
            vertical_move: true,
            vertical_look: true,
        }
    }

    /// Set the initial yaw angle in radians.
    ///
    /// Default is 0.0.
    pub fn yaw(
        &mut self,
        yaw: f32,
    ) -> &mut Self {
        self.yaw = yaw;
        self
    }

    /// Set the initial pitch angle in radians.
    ///
    /// Defaults to 0.0.
    pub fn pitch(
        &mut self,
        pitch: f32,
    ) -> &mut Self {
        self.pitch = pitch;
        self
    }

    /// Set the initial pitch range in radians.
    ///
    /// Defaults to `Some(-PI / 2.0 .. PI / 2.0)`.
    pub fn pitch_range(
        &mut self,
        range: Option<ops::Range<f32>>,
    ) -> &mut Self {
        self.pitch_range = range;
        self
    }

    /// Set the initial position.
    ///
    /// Defaults to the world origin.
    pub fn position<P>(
        &mut self,
        position: P,
    ) -> &mut Self
    where
        P: Into<mint::Point3<f32>>,
    {
        self.position = position.into();
        self
    }

    /// Setup the movement speed in world units per second.
    ///
    /// Defaults to 1.0 world units per second.
    pub fn move_speed(
        &mut self,
        speed: f32,
    ) -> &mut Self {
        self.move_speed = speed;
        self
    }

    /// Setup mouse sensitivity.
    ///
    /// Defaults to 0.5
    pub fn look_speed(
        &mut self,
        speed: f32,
    ) -> &mut Self {
        self.look_speed = speed;
        self
    }

    /// Setup whether controlled object should move along `y` axis when looking
    /// down or up.
    ///
    /// Defaults to true.
    pub fn vertical_movement(
        &mut self,
        value: bool,
    ) -> &mut Self {
        self.vertical_move = value;
        self
    }

    /// Setup whether controlled object can adjust pitch using mouse.
    ///
    /// Defaults to true.
    pub fn vertical_look(
        &mut self,
        value: bool,
    ) -> &mut Self {
        self.vertical_look = value;
        self
    }

    /// Setup key axis for moving forward/backward.
    ///
    /// Defaults to `W` and `S` keys.
    pub fn axis_forward(
        &mut self,
        axis: Option<KeyAxis>,
    ) -> &mut Self {
        self.axes.forward = axis;
        self
    }

    /// Setup button for "strafing" left/right.
    ///
    /// Defaults to `A` and `D` keys.
    pub fn axis_strafing(
        &mut self,
        axis: Option<KeyAxis>,
    ) -> &mut Self {
        self.axes.strafing = axis;
        self
    }

    /// Setup button for moving up/down.
    ///
    /// Defaults to `None`.
    pub fn axis_vertical(
        &mut self,
        axis: Option<KeyAxis>,
    ) -> &mut Self {
        self.axes.vertical = axis;
        self
    }

    /// Finalize builder and create new `FirstPerson` controls.
    pub fn build(&mut self) -> FirstPerson {
        FirstPerson {
            object: self.object.clone(),
            position: self.position,
            yaw: self.yaw,
            pitch: self.pitch,
            pitch_range: self.pitch_range.clone(),
            move_speed: self.move_speed,
            look_speed: self.look_speed,
            axes: self.axes.clone(),
            vertical_move: self.vertical_move,
            vertical_look: self.vertical_look,
        }
    }
}

impl FirstPerson {
    /// Create a `Builder`.
    pub fn builder(object: &Object) -> Builder {
        Builder::new(object)
    }

    /// Create `FirstPerson` controls with default parameters.
    pub fn default(object: &Object) -> Self {
        Self::builder(object).build()
    }

    /// Sets the yaw angle in radians.
    pub fn set_yaw(
        &mut self,
        yaw: f32,
    ) -> &mut Self {
        self.yaw = yaw;
        self
    }

    /// Sets the pitch angle in radians.
    pub fn set_pitch(
        &mut self,
        pitch: f32,
    ) -> &mut Self {
        self.pitch = pitch;
        self
    }

    /// Sets the pitch range in radians.
    pub fn pitch_range(
        &mut self,
        range: Option<ops::Range<f32>>,
    ) -> &mut Self {
        self.pitch_range = range;
        self
    }

    /// Sets the object position.
    pub fn set_position<P>(
        &mut self,
        position: P,
    ) -> &mut Self
    where
        P: Into<mint::Point3<f32>>,
    {
        self.position = position.into();
        self
    }

    /// Sets the movement speed in world units per second.
    pub fn set_move_speed(
        &mut self,
        speed: f32,
    ) -> &mut Self {
        self.move_speed = speed;
        self
    }

    /// Sets the mouse sensitivity.
    pub fn set_look_speed(
        &mut self,
        speed: f32,
    ) -> &mut Self {
        self.look_speed = speed;
        self
    }

    /// Specifies whether controlled object should move along `y` axis when looking
    /// down or up.
    pub fn set_vertical_movement(
        &mut self,
        value: bool,
    ) -> &mut Self {
        self.vertical_move = value;
        self
    }

    /// Specifies whether controlled object can adjust pitch using mouse.
    pub fn set_vertical_look(
        &mut self,
        value: bool,
    ) -> &mut Self {
        self.vertical_look = value;
        self
    }

    /// Sets the key axis for moving forward/backward.
    pub fn set_axis_forward(
        &mut self,
        axis: Option<KeyAxis>,
    ) -> &mut Self {
        self.axes.forward = axis;
        self
    }

    /// Sets the button for "strafing" left/right.
    pub fn set_axis_strafing(
        &mut self,
        axis: Option<KeyAxis>,
    ) -> &mut Self {
        self.axes.strafing = axis;
        self
    }

    /// Sets button for moving up/down.
    pub fn set_axis_vertical(
        &mut self,
        axis: Option<KeyAxis>,
    ) -> &mut Self {
        self.axes.vertical = axis;
        self
    }

    /// Updates the position, yaw, and pitch of the controlled object according to
    /// the last frame input.
    pub fn update(
        &mut self,
        input: &Input,
    ) {
        let dtime = input.delta_time();
        let dlook = dtime * self.look_speed;

        let mouse = input.mouse_delta_raw();

        self.yaw += dlook * mouse.x;
        if self.vertical_look {
            self.pitch += dlook * mouse.y;
            if let Some(range) = self.pitch_range.as_ref() {
                if self.pitch < range.start {
                    self.pitch = range.start;
                }
                if self.pitch > range.end {
                    self.pitch = range.end;
                }
            }
        }

        self.axes
            .vertical
            .map(|a| if let Some(time) = a.timed(input) {
                self.position.y += self.move_speed * time;
            });

        self.axes
            .forward
            .map(|a| if let Some(time) = a.timed(input) {
                self.position.x += self.move_speed * time * self.yaw.sin();
                self.position.z -= self.move_speed * time * self.yaw.cos();
                if self.vertical_move {
                    self.position.y -= self.move_speed * time * self.pitch.sin();
                }
            });
        self.axes
            .strafing
            .map(|a| if let Some(time) = a.timed(input) {
                self.position.x += self.move_speed * time * self.yaw.cos();
                self.position.z += self.move_speed * time * self.yaw.sin();
            });

        let yrot = cgmath::Quaternion::from_angle_y(cgmath::Rad(-self.yaw));
        let xrot = cgmath::Quaternion::from_angle_x(cgmath::Rad(-self.pitch));
        self.object.set_transform(self.position, yrot * xrot, 1.0);
    }
}
<|endoftext|>


<commit_before>#![feature(test)]
#![feature(i128_type)]

extern crate flat_map;
extern crate rand;
extern crate test;

use flat_map::FlatMap;
use rand::distributions::{IndependentSample, Range};
use rand::Rng;
use std::collections::BTreeMap;
use std::iter::FromIterator;
use test::Bencher;

type Key = u64;
type Value = u64;

const NUM_KEYS: usize = 2 << 12;
const NUM_VALUES: usize = 1 << 12;

fn flat_map_setup() -> (FlatMap<Key, Value>, Vec<Key>) {
    let num_items = 1 << 25;
    let mut keys = Vec::new();
    let mut key_vals = Vec::with_capacity(num_items);
    let mut rng = rand::IsaacRng::new_unseeded();
    for i in 0..NUM_KEYS * NUM_VALUES {
        keys.push(i as Key);
        let value = rng.gen::<Value>();
        key_vals.push((i as Key, value))
    }
    let map: FlatMap<_, _> = key_vals.into_iter().collect();
    (map, keys)
}

fn btree_map_setup() -> (BTreeMap<Key, Value>, Vec<Key>) {
    let num_items = 1 << 25;
    let mut keys = Vec::new();
    let mut key_vals = Vec::with_capacity(num_items);
    let mut rng = rand::IsaacRng::new_unseeded();
    for i in 0..NUM_KEYS * NUM_VALUES {
        keys.push(i as Key);
        let value = rng.gen::<Value>();
        key_vals.push((i as Value, value))
    }
    let map = BTreeMap::from_iter(key_vals);
    (map, keys)
}

#[bench]
fn bench_flat_map_from_iter(b: &mut Bencher) {
    let num_keys = 1 << 10;
    let num_values = 1 << 10;
    let mut keys = Vec::new();
    let mut key_vals = Vec::with_capacity(num_keys * num_values);
    let mut rng = rand::IsaacRng::new_unseeded();
    for i in 0..num_keys * num_values {
        keys.push(i as Key);
        let value = rng.gen::<Value>();
        key_vals.push((i as Key, value))
    }
    b.iter(|| {
        let map = FlatMap::from_iter(key_vals.clone());
        map
    })
}

#[bench]
fn bench_flat_map_insert(b: &mut Bencher) {
    let (mut map, keys) = flat_map_setup();
    let mut rng = rand::IsaacRng::new_unseeded();
    let between = Range::new(0, keys.len());
    b.iter(|| {
        let i = between.ind_sample(&mut rng);
        map.insert(keys[i], rng.gen::<Value>());
    })
}

#[bench]
fn bench_flat_map_get(b: &mut Bencher) {
    let (map, keys) = flat_map_setup();
    let mut rng = rand::IsaacRng::new_unseeded();
    let between = Range::new(0, keys.len());
    b.iter(|| {
        let i = between.ind_sample(&mut rng);
        map.get(&keys[i])
    })
}

#[bench]
fn bench_btree_map_from_iter(b: &mut Bencher) {
    let num_keys = 1 << 10;
    let num_values = 1 << 10;
    let mut keys = Vec::new();
    let mut key_vals = Vec::with_capacity(num_keys * num_values);
    let mut rng = rand::IsaacRng::new_unseeded();
    for i in 0..num_keys * num_values {
        keys.push(i as Key);
        let value = rng.gen::<Value>();
        key_vals.push((i as Key, value))
    }
    b.iter(|| {
        let map = BTreeMap::from_iter(key_vals.clone());
        map
    })
}

#[bench]
fn bench_btree_map_insert(b: &mut Bencher) {
    let (mut map, keys) = btree_map_setup();
    let mut rng = rand::IsaacRng::new_unseeded();
    let between = Range::new(0, keys.len());
    b.iter(|| {
        let i = between.ind_sample(&mut rng);
        map.insert(keys[i], rng.gen::<Value>());
    })
}

#[bench]
fn bench_btree_map_get(b: &mut Bencher) {
    let (map, keys) = btree_map_setup();
    let mut rng = rand::IsaacRng::new_unseeded();
    let between = Range::new(0, keys.len());
    b.iter(|| {
        let i = between.ind_sample(&mut rng);
        map.get(&keys[i])
    })
}
<commit_msg>remove i128_type feature, stable now<commit_after>#![feature(test)]

extern crate flat_map;
extern crate rand;
extern crate test;

use flat_map::FlatMap;
use rand::distributions::{IndependentSample, Range};
use rand::Rng;
use std::collections::BTreeMap;
use std::iter::FromIterator;
use test::Bencher;

type Key = u64;
type Value = u64;

const NUM_KEYS: usize = 2 << 12;
const NUM_VALUES: usize = 1 << 12;

fn flat_map_setup() -> (FlatMap<Key, Value>, Vec<Key>) {
    let num_items = 1 << 25;
    let mut keys = Vec::new();
    let mut key_vals = Vec::with_capacity(num_items);
    let mut rng = rand::IsaacRng::new_unseeded();
    for i in 0..NUM_KEYS * NUM_VALUES {
        keys.push(i as Key);
        let value = rng.gen::<Value>();
        key_vals.push((i as Key, value))
    }
    let map: FlatMap<_, _> = key_vals.into_iter().collect();
    (map, keys)
}

fn btree_map_setup() -> (BTreeMap<Key, Value>, Vec<Key>) {
    let num_items = 1 << 25;
    let mut keys = Vec::new();
    let mut key_vals = Vec::with_capacity(num_items);
    let mut rng = rand::IsaacRng::new_unseeded();
    for i in 0..NUM_KEYS * NUM_VALUES {
        keys.push(i as Key);
        let value = rng.gen::<Value>();
        key_vals.push((i as Value, value))
    }
    let map = BTreeMap::from_iter(key_vals);
    (map, keys)
}

#[bench]
fn bench_flat_map_from_iter(b: &mut Bencher) {
    let num_keys = 1 << 10;
    let num_values = 1 << 10;
    let mut keys = Vec::new();
    let mut key_vals = Vec::with_capacity(num_keys * num_values);
    let mut rng = rand::IsaacRng::new_unseeded();
    for i in 0..num_keys * num_values {
        keys.push(i as Key);
        let value = rng.gen::<Value>();
        key_vals.push((i as Key, value))
    }
    b.iter(|| {
        let map = FlatMap::from_iter(key_vals.clone());
        map
    })
}

#[bench]
fn bench_flat_map_insert(b: &mut Bencher) {
    let (mut map, keys) = flat_map_setup();
    let mut rng = rand::IsaacRng::new_unseeded();
    let between = Range::new(0, keys.len());
    b.iter(|| {
        let i = between.ind_sample(&mut rng);
        map.insert(keys[i], rng.gen::<Value>());
    })
}

#[bench]
fn bench_flat_map_get(b: &mut Bencher) {
    let (map, keys) = flat_map_setup();
    let mut rng = rand::IsaacRng::new_unseeded();
    let between = Range::new(0, keys.len());
    b.iter(|| {
        let i = between.ind_sample(&mut rng);
        map.get(&keys[i])
    })
}

#[bench]
fn bench_btree_map_from_iter(b: &mut Bencher) {
    let num_keys = 1 << 10;
    let num_values = 1 << 10;
    let mut keys = Vec::new();
    let mut key_vals = Vec::with_capacity(num_keys * num_values);
    let mut rng = rand::IsaacRng::new_unseeded();
    for i in 0..num_keys * num_values {
        keys.push(i as Key);
        let value = rng.gen::<Value>();
        key_vals.push((i as Key, value))
    }
    b.iter(|| {
        let map = BTreeMap::from_iter(key_vals.clone());
        map
    })
}

#[bench]
fn bench_btree_map_insert(b: &mut Bencher) {
    let (mut map, keys) = btree_map_setup();
    let mut rng = rand::IsaacRng::new_unseeded();
    let between = Range::new(0, keys.len());
    b.iter(|| {
        let i = between.ind_sample(&mut rng);
        map.insert(keys[i], rng.gen::<Value>());
    })
}

#[bench]
fn bench_btree_map_get(b: &mut Bencher) {
    let (map, keys) = btree_map_setup();
    let mut rng = rand::IsaacRng::new_unseeded();
    let between = Range::new(0, keys.len());
    b.iter(|| {
        let i = between.ind_sample(&mut rng);
        map.get(&keys[i])
    })
}
<|endoftext|>


<commit_before>use freetype::{Face};
use freetype::face::{RENDER};
use opengl_graphics::{Gl, Texture};
use graphics::{RelativeTransform, Image, color, default_draw_state};

pub fn render_text(face: &mut Face, gl: &mut Gl, xcoord: f64, ycoord: f64, text: &str) {
    gl.draw([0, 0, 1000, 1000], |c, gl| {
        let transform = c.transform.trans(xcoord, ycoord);
        let mut x = 0;
        let mut y = 0;
        for ch in text.chars() {
            face.load_char(ch as usize, RENDER).unwrap();
            let g = face.glyph();
            let bitmap = g.bitmap();
            let texture = Texture::from_memory_alpha(bitmap.buffer(),
                                                     bitmap.width() as u32,
                                                     bitmap.rows() as u32).unwrap();
            Image::colored(color::WHITE).draw(&texture,
                                              default_draw_state(),
                                              transform.trans((x + g.bitmap_left()) as f64, (y - g.bitmap_top()) as f64),
                                              gl);
            x += (g.advance().x >> 6) as i32;
            y += (g.advance().y >> 6) as i32;
        }
    });
}
<commit_msg>Minor fix for text.<commit_after>use freetype::{Face};
use freetype::face::{RENDER};
use opengl_graphics::{Gl, Texture};
use graphics::{RelativeTransform, Image, color, default_draw_state};

pub fn render_text(face: &mut Face, gl: &mut Gl, xcoord: f64, ycoord: f64, text: &str) {
    // TODO: account for window size correctly
    gl.draw([0, 0, 400, 416], |c, gl| {
        let transform = c.transform.trans(xcoord, ycoord);
        let mut x = 0;
        let mut y = 0;
        for ch in text.chars() {
            face.load_char(ch as usize, RENDER).unwrap();
            let g = face.glyph();
            let bitmap = g.bitmap();
            let texture = Texture::from_memory_alpha(bitmap.buffer(),
                                                     bitmap.width() as u32,
                                                     bitmap.rows() as u32).unwrap();
            Image::colored(color::WHITE).draw(&texture,
                                              default_draw_state(),
                                              transform.trans((x + g.bitmap_left()) as f64, (y - g.bitmap_top()) as f64),
                                              gl);
            x += (g.advance().x >> 6) as i32;
            y += (g.advance().y >> 6) as i32;
        }
    });
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 by SiegeLord
//
// All rights reserved. Distributed under ZLib. For full terms see the file LICENSE.

use libc::*;
use std::mem;
use std::c_str::CString;

use internal::bitmap::{Bitmap, new_bitmap_ref, clone_bitmap};
use internal::bitmap_like::BitmapLike;
use internal::color::PixelFormat;
use internal::core::{Core, dummy_target};
use internal::events::{EventSource, new_event_source_ref};
use rust_util::Flag;

use ffi::*;

pub use rust_util::c_bool;

flag_type!{
	DisplayFlags
	{
		WINDOWED                  = ALLEGRO_WINDOWED,
		FULLSCREEN                = ALLEGRO_FULLSCREEN,
		OPENGL                    = ALLEGRO_OPENGL,
		DIRECT3D                  = ALLEGRO_DIRECT3D_INTERNAL,
		RESIZABLE                 = ALLEGRO_RESIZABLE,
		FRAMELESS                 = ALLEGRO_FRAMELESS,
		GENERATE_EXPOSE_EVENTS    = ALLEGRO_GENERATE_EXPOSE_EVENTS,
		OPENGL_3_0                = ALLEGRO_OPENGL_3_0,
		OPENGL_FORWARD_COMPATIBLE = ALLEGRO_OPENGL_FORWARD_COMPATIBLE,
		FULLSCREEN_WINDOW         = ALLEGRO_FULLSCREEN_WINDOW,
		MINIMIZED                 = ALLEGRO_MINIMIZED
	}
}

#[repr(u32)]
#[deriving(Copy)]
pub enum DisplayOption
{
	RedSize = ALLEGRO_RED_SIZE,
	GreenSize = ALLEGRO_GREEN_SIZE,
	BlueSize = ALLEGRO_BLUE_SIZE,
	AlphaSize = ALLEGRO_ALPHA_SIZE,
	RedShift = ALLEGRO_RED_SHIFT,
	GreenShift = ALLEGRO_GREEN_SHIFT,
	BlueShift = ALLEGRO_BLUE_SHIFT,
	AlphaShift = ALLEGRO_ALPHA_SHIFT,
	AccRedSize = ALLEGRO_ACC_RED_SIZE,
	AccGreenSize = ALLEGRO_ACC_GREEN_SIZE,
	AccBlueSize = ALLEGRO_ACC_BLUE_SIZE,
	AccAlphaSize = ALLEGRO_ACC_ALPHA_SIZE,
	Stereo = ALLEGRO_STEREO,
	AuxBuffers = ALLEGRO_AUX_BUFFERS,
	ColorSize = ALLEGRO_COLOR_SIZE,
	DepthSize = ALLEGRO_DEPTH_SIZE,
	StencilSize = ALLEGRO_STENCIL_SIZE,
	SampleBuffers = ALLEGRO_SAMPLE_BUFFERS,
	Samples = ALLEGRO_SAMPLES,
	RenderMethod = ALLEGRO_RENDER_METHOD,
	FloatColor = ALLEGRO_FLOAT_COLOR,
	FloatDepth = ALLEGRO_FLOAT_DEPTH,
	SingleBuffer = ALLEGRO_SINGLE_BUFFER,
	SwapMethod = ALLEGRO_SWAP_METHOD,
	CompatibleDisplay = ALLEGRO_COMPATIBLE_DISPLAY,
	UpdateDisplayRegion = ALLEGRO_UPDATE_DISPLAY_REGION,
	Vsync = ALLEGRO_VSYNC,
	MaxBitmapSize = ALLEGRO_MAX_BITMAP_SIZE,
	SupportNpotBitmap = ALLEGRO_SUPPORT_NPOT_BITMAP,
	CanDrawIntoBitmap = ALLEGRO_CAN_DRAW_INTO_BITMAP,
	SupportSeparateAlpha = ALLEGRO_SUPPORT_SEPARATE_ALPHA,
}

#[repr(u32)]
#[deriving(Copy)]
pub enum DisplayOptionImportance
{
	DontCare = ALLEGRO_DONTCARE,
	Require = ALLEGRO_REQUIRE,
	Suggest = ALLEGRO_SUGGEST,
}

#[repr(u32)]
#[deriving(Copy)]
pub enum DisplayOrientation
{
	DisplayOrientation0Degrees = ALLEGRO_DISPLAY_ORIENTATION_0_DEGREES,
	DisplayOrientation90Degrees = ALLEGRO_DISPLAY_ORIENTATION_90_DEGREES,
	DisplayOrientation180Degrees = ALLEGRO_DISPLAY_ORIENTATION_180_DEGREES,
	DisplayOrientation270Degrees = ALLEGRO_DISPLAY_ORIENTATION_270_DEGREES,
	DisplayOrientationFaceUp = ALLEGRO_DISPLAY_ORIENTATION_FACE_UP,
	DisplayOrientationFaceDown = ALLEGRO_DISPLAY_ORIENTATION_FACE_DOWN,
}

pub struct Display
{
	allegro_display: *mut ALLEGRO_DISPLAY,
	backbuffer: Bitmap,
	event_source: EventSource,
}

impl Display
{
	pub fn new(_: &Core, w: i32, h: i32) -> Result<Display, String>
	{
		unsafe
		{
			if !al_get_current_display().is_null()
			{
				Err("Only one display is allowed per thread.".to_string())
			}
			else
			{
				let d = al_create_display(w as c_int, h as c_int);
				if d.is_null()
				{
					Err("Could not create the display".to_string())
				}
				else
				{
					Ok
					(
						Display
						{
							allegro_display: d,
							backbuffer: new_bitmap_ref(al_get_backbuffer(d)),
							event_source: new_event_source_ref(al_get_display_event_source(d)),
						}
					)
				}
			}
		}
	}

	pub fn get_width(&self) -> i32
	{
		unsafe
		{
			al_get_display_width(self.allegro_display) as i32
		}
	}

	pub fn get_height(&self) -> i32
	{
		unsafe
		{
			al_get_display_height(self.allegro_display) as i32
		}
	}

	pub fn get_format(&self) -> PixelFormat
	{
		unsafe
		{
			mem::transmute(al_get_display_format(self.allegro_display) as u32)
		}
	}

	pub fn get_refresh_rate(&self) -> i32
	{
		unsafe
		{
			al_get_display_refresh_rate(self.allegro_display) as i32
		}
	}

	pub fn get_flags(&self) -> DisplayFlags
	{
		unsafe
		{
			mem::transmute(al_get_display_flags(self.allegro_display))
		}
	}

	pub fn set_flag(&self, flag: DisplayFlags, onoff: bool) -> bool
	{
		unsafe
		{
			al_set_display_flag(self.allegro_display, flag.get(), onoff as u8) != 0
		}
	}

	pub fn get_backbuffer<'l>(&'l self) -> &'l Bitmap
	{
		&self.backbuffer
	}

	pub fn acknowledge_resize(&self) -> Result<(), ()>
	{
		unsafe
		{
			if al_acknowledge_resize(self.allegro_display) != 0
			{
				Ok(())
			}
			else
			{
				Err(())
			}
		}
	}

	pub fn resize(&self, w: i32, h: i32) -> Result<(), ()>
	{
		unsafe
		{
			if al_resize_display(self.allegro_display, w as c_int, h as c_int) != 0
			{
				Ok(())
			}
			else
			{
				Err(())
			}
		}
	}

	pub fn set_icon<T: BitmapLike>(&self, icon: &T)
	{
		unsafe
		{
			al_set_display_icon(self.allegro_display, icon.get_allegro_bitmap());
		}
	}

	pub fn set_icons<'l, U: Iterator<&'l(BitmapLike + 'l)>>(&self, icons: U)
	{
		let mut c_icons: Vec<_> = icons.map(|b| b.get_allegro_bitmap()).collect();
		unsafe
		{
			al_set_display_icons(self.allegro_display, c_icons.len() as c_int, c_icons.as_mut_ptr());
		}
	}

	pub fn set_window_position(&self, x: i32, y: i32)
	{
		unsafe
		{
			al_set_window_position(self.allegro_display, x as c_int, y as c_int);
		}
	}

	pub fn get_window_position(&self) -> (i32, i32)
	{
		unsafe
		{
			let mut x = 0 as c_int;
			let mut y = 0 as c_int;
			al_get_window_position(self.allegro_display, &mut x, &mut y);
			(x as i32, y as i32)
		}
	}

	pub fn set_window_title(&self, title: &CString)
	{
		unsafe
		{
			al_set_window_title(self.allegro_display, title.as_ptr());
		}
	}

	pub fn get_option(&self, option: DisplayOption) -> i32
	{
		unsafe
		{
			al_get_display_option(self.allegro_display, option as c_int) as i32
		}
	}

	pub fn convert_bitmap<T: BitmapLike>(&self, bmp: &T) -> Result<Bitmap, ()>
	{
		clone_bitmap(bmp.get_allegro_bitmap())
	}

	pub fn get_event_source<'l>(&'l self) -> &'l EventSource
	{
		&self.event_source
	}

	pub fn get_allegro_display(&self) -> *mut ALLEGRO_DISPLAY
	{
		self.allegro_display
	}

	pub fn flip(&self)
	{
		unsafe
		{
			al_flip_display();
		}
	}

	pub fn update_region(&self, x: i32, y: i32, width: i32, height: i32)
	{
		unsafe
		{
			al_update_display_region(x as c_int, y as c_int, width as c_int, height as c_int);
		}
	}

	pub fn is_compatible_bitmap<T: BitmapLike>(&self, bitmap: &T) -> bool
	{
		unsafe
		{
			al_is_compatible_bitmap(bitmap.get_allegro_bitmap()) != 0
		}
	}

	pub fn wait_for_vsync(&self) -> Result<(), ()>
	{
		unsafe
		{
			if al_wait_for_vsync() != 0
			{
				Ok(())
			}
			else
			{
				Err(())
			}
		}
	}

	pub fn hold_bitmap_drawing(&self, hold: bool)
	{
		unsafe
		{
			al_hold_bitmap_drawing(hold as c_bool);
		}
	}

	pub fn is_bitmap_drawing_held(&self) -> bool
	{
		unsafe
		{
			al_is_bitmap_drawing_held() != 0
		}
	}
}

// Not Send just because of the marker in the event source
#[unsafe_destructor]
impl Drop for Display
{
	fn drop(&mut self)
	{
		unsafe
		{
			/* If it's a video bitmap, it's about to be reset, so we fall back to the dummy target */
			if al_get_bitmap_flags(al_get_target_bitmap()) & (ALLEGRO_VIDEO_BITMAP as i32) != 0
			{
				al_set_target_bitmap(dummy_target);
			}
			al_destroy_display(self.allegro_display);
		}
	}
}
<commit_msg>Stray 'pub'.<commit_after>// Copyright (c) 2014 by SiegeLord
//
// All rights reserved. Distributed under ZLib. For full terms see the file LICENSE.

use libc::*;
use std::mem;
use std::c_str::CString;

use internal::bitmap::{Bitmap, new_bitmap_ref, clone_bitmap};
use internal::bitmap_like::BitmapLike;
use internal::color::PixelFormat;
use internal::core::{Core, dummy_target};
use internal::events::{EventSource, new_event_source_ref};
use rust_util::Flag;

use ffi::*;

use rust_util::c_bool;

flag_type!{
	DisplayFlags
	{
		WINDOWED                  = ALLEGRO_WINDOWED,
		FULLSCREEN                = ALLEGRO_FULLSCREEN,
		OPENGL                    = ALLEGRO_OPENGL,
		DIRECT3D                  = ALLEGRO_DIRECT3D_INTERNAL,
		RESIZABLE                 = ALLEGRO_RESIZABLE,
		FRAMELESS                 = ALLEGRO_FRAMELESS,
		GENERATE_EXPOSE_EVENTS    = ALLEGRO_GENERATE_EXPOSE_EVENTS,
		OPENGL_3_0                = ALLEGRO_OPENGL_3_0,
		OPENGL_FORWARD_COMPATIBLE = ALLEGRO_OPENGL_FORWARD_COMPATIBLE,
		FULLSCREEN_WINDOW         = ALLEGRO_FULLSCREEN_WINDOW,
		MINIMIZED                 = ALLEGRO_MINIMIZED
	}
}

#[repr(u32)]
#[deriving(Copy)]
pub enum DisplayOption
{
	RedSize = ALLEGRO_RED_SIZE,
	GreenSize = ALLEGRO_GREEN_SIZE,
	BlueSize = ALLEGRO_BLUE_SIZE,
	AlphaSize = ALLEGRO_ALPHA_SIZE,
	RedShift = ALLEGRO_RED_SHIFT,
	GreenShift = ALLEGRO_GREEN_SHIFT,
	BlueShift = ALLEGRO_BLUE_SHIFT,
	AlphaShift = ALLEGRO_ALPHA_SHIFT,
	AccRedSize = ALLEGRO_ACC_RED_SIZE,
	AccGreenSize = ALLEGRO_ACC_GREEN_SIZE,
	AccBlueSize = ALLEGRO_ACC_BLUE_SIZE,
	AccAlphaSize = ALLEGRO_ACC_ALPHA_SIZE,
	Stereo = ALLEGRO_STEREO,
	AuxBuffers = ALLEGRO_AUX_BUFFERS,
	ColorSize = ALLEGRO_COLOR_SIZE,
	DepthSize = ALLEGRO_DEPTH_SIZE,
	StencilSize = ALLEGRO_STENCIL_SIZE,
	SampleBuffers = ALLEGRO_SAMPLE_BUFFERS,
	Samples = ALLEGRO_SAMPLES,
	RenderMethod = ALLEGRO_RENDER_METHOD,
	FloatColor = ALLEGRO_FLOAT_COLOR,
	FloatDepth = ALLEGRO_FLOAT_DEPTH,
	SingleBuffer = ALLEGRO_SINGLE_BUFFER,
	SwapMethod = ALLEGRO_SWAP_METHOD,
	CompatibleDisplay = ALLEGRO_COMPATIBLE_DISPLAY,
	UpdateDisplayRegion = ALLEGRO_UPDATE_DISPLAY_REGION,
	Vsync = ALLEGRO_VSYNC,
	MaxBitmapSize = ALLEGRO_MAX_BITMAP_SIZE,
	SupportNpotBitmap = ALLEGRO_SUPPORT_NPOT_BITMAP,
	CanDrawIntoBitmap = ALLEGRO_CAN_DRAW_INTO_BITMAP,
	SupportSeparateAlpha = ALLEGRO_SUPPORT_SEPARATE_ALPHA,
}

#[repr(u32)]
#[deriving(Copy)]
pub enum DisplayOptionImportance
{
	DontCare = ALLEGRO_DONTCARE,
	Require = ALLEGRO_REQUIRE,
	Suggest = ALLEGRO_SUGGEST,
}

#[repr(u32)]
#[deriving(Copy)]
pub enum DisplayOrientation
{
	DisplayOrientation0Degrees = ALLEGRO_DISPLAY_ORIENTATION_0_DEGREES,
	DisplayOrientation90Degrees = ALLEGRO_DISPLAY_ORIENTATION_90_DEGREES,
	DisplayOrientation180Degrees = ALLEGRO_DISPLAY_ORIENTATION_180_DEGREES,
	DisplayOrientation270Degrees = ALLEGRO_DISPLAY_ORIENTATION_270_DEGREES,
	DisplayOrientationFaceUp = ALLEGRO_DISPLAY_ORIENTATION_FACE_UP,
	DisplayOrientationFaceDown = ALLEGRO_DISPLAY_ORIENTATION_FACE_DOWN,
}

pub struct Display
{
	allegro_display: *mut ALLEGRO_DISPLAY,
	backbuffer: Bitmap,
	event_source: EventSource,
}

impl Display
{
	pub fn new(_: &Core, w: i32, h: i32) -> Result<Display, String>
	{
		unsafe
		{
			if !al_get_current_display().is_null()
			{
				Err("Only one display is allowed per thread.".to_string())
			}
			else
			{
				let d = al_create_display(w as c_int, h as c_int);
				if d.is_null()
				{
					Err("Could not create the display".to_string())
				}
				else
				{
					Ok
					(
						Display
						{
							allegro_display: d,
							backbuffer: new_bitmap_ref(al_get_backbuffer(d)),
							event_source: new_event_source_ref(al_get_display_event_source(d)),
						}
					)
				}
			}
		}
	}

	pub fn get_width(&self) -> i32
	{
		unsafe
		{
			al_get_display_width(self.allegro_display) as i32
		}
	}

	pub fn get_height(&self) -> i32
	{
		unsafe
		{
			al_get_display_height(self.allegro_display) as i32
		}
	}

	pub fn get_format(&self) -> PixelFormat
	{
		unsafe
		{
			mem::transmute(al_get_display_format(self.allegro_display) as u32)
		}
	}

	pub fn get_refresh_rate(&self) -> i32
	{
		unsafe
		{
			al_get_display_refresh_rate(self.allegro_display) as i32
		}
	}

	pub fn get_flags(&self) -> DisplayFlags
	{
		unsafe
		{
			mem::transmute(al_get_display_flags(self.allegro_display))
		}
	}

	pub fn set_flag(&self, flag: DisplayFlags, onoff: bool) -> bool
	{
		unsafe
		{
			al_set_display_flag(self.allegro_display, flag.get(), onoff as u8) != 0
		}
	}

	pub fn get_backbuffer<'l>(&'l self) -> &'l Bitmap
	{
		&self.backbuffer
	}

	pub fn acknowledge_resize(&self) -> Result<(), ()>
	{
		unsafe
		{
			if al_acknowledge_resize(self.allegro_display) != 0
			{
				Ok(())
			}
			else
			{
				Err(())
			}
		}
	}

	pub fn resize(&self, w: i32, h: i32) -> Result<(), ()>
	{
		unsafe
		{
			if al_resize_display(self.allegro_display, w as c_int, h as c_int) != 0
			{
				Ok(())
			}
			else
			{
				Err(())
			}
		}
	}

	pub fn set_icon<T: BitmapLike>(&self, icon: &T)
	{
		unsafe
		{
			al_set_display_icon(self.allegro_display, icon.get_allegro_bitmap());
		}
	}

	pub fn set_icons<'l, U: Iterator<&'l(BitmapLike + 'l)>>(&self, icons: U)
	{
		let mut c_icons: Vec<_> = icons.map(|b| b.get_allegro_bitmap()).collect();
		unsafe
		{
			al_set_display_icons(self.allegro_display, c_icons.len() as c_int, c_icons.as_mut_ptr());
		}
	}

	pub fn set_window_position(&self, x: i32, y: i32)
	{
		unsafe
		{
			al_set_window_position(self.allegro_display, x as c_int, y as c_int);
		}
	}

	pub fn get_window_position(&self) -> (i32, i32)
	{
		unsafe
		{
			let mut x = 0 as c_int;
			let mut y = 0 as c_int;
			al_get_window_position(self.allegro_display, &mut x, &mut y);
			(x as i32, y as i32)
		}
	}

	pub fn set_window_title(&self, title: &CString)
	{
		unsafe
		{
			al_set_window_title(self.allegro_display, title.as_ptr());
		}
	}

	pub fn get_option(&self, option: DisplayOption) -> i32
	{
		unsafe
		{
			al_get_display_option(self.allegro_display, option as c_int) as i32
		}
	}

	pub fn convert_bitmap<T: BitmapLike>(&self, bmp: &T) -> Result<Bitmap, ()>
	{
		clone_bitmap(bmp.get_allegro_bitmap())
	}

	pub fn get_event_source<'l>(&'l self) -> &'l EventSource
	{
		&self.event_source
	}

	pub fn get_allegro_display(&self) -> *mut ALLEGRO_DISPLAY
	{
		self.allegro_display
	}

	pub fn flip(&self)
	{
		unsafe
		{
			al_flip_display();
		}
	}

	pub fn update_region(&self, x: i32, y: i32, width: i32, height: i32)
	{
		unsafe
		{
			al_update_display_region(x as c_int, y as c_int, width as c_int, height as c_int);
		}
	}

	pub fn is_compatible_bitmap<T: BitmapLike>(&self, bitmap: &T) -> bool
	{
		unsafe
		{
			al_is_compatible_bitmap(bitmap.get_allegro_bitmap()) != 0
		}
	}

	pub fn wait_for_vsync(&self) -> Result<(), ()>
	{
		unsafe
		{
			if al_wait_for_vsync() != 0
			{
				Ok(())
			}
			else
			{
				Err(())
			}
		}
	}

	pub fn hold_bitmap_drawing(&self, hold: bool)
	{
		unsafe
		{
			al_hold_bitmap_drawing(hold as c_bool);
		}
	}

	pub fn is_bitmap_drawing_held(&self) -> bool
	{
		unsafe
		{
			al_is_bitmap_drawing_held() != 0
		}
	}
}

// Not Send just because of the marker in the event source
#[unsafe_destructor]
impl Drop for Display
{
	fn drop(&mut self)
	{
		unsafe
		{
			/* If it's a video bitmap, it's about to be reset, so we fall back to the dummy target */
			if al_get_bitmap_flags(al_get_target_bitmap()) & (ALLEGRO_VIDEO_BITMAP as i32) != 0
			{
				al_set_target_bitmap(dummy_target);
			}
			al_destroy_display(self.allegro_display);
		}
	}
}
<|endoftext|>


<commit_before>pub use super::super::compiler::*;

use super::super::cache::Cache;
use super::postprocess;
use super::super::wincmd;
use super::super::utils::filter;
use super::super::utils::hash_text;
use super::super::io::tempfile::TempFile;

use std::fs::File;
use std::io::{Error, BufReader, Cursor, Read, Write};
use std::hash::{SipHasher, Hasher};
use std::path::{Path, PathBuf};
use std::process::Output;

pub struct VsCompiler {
	cache: Cache,
	temp_dir: PathBuf
}

impl VsCompiler {
	pub fn new(cache: &Cache, temp_dir: &Path) -> Self {
		VsCompiler {
			cache: cache.clone(),
			temp_dir: temp_dir.to_path_buf()
		}
	}
}

impl Compiler for VsCompiler {
	fn create_task(&self, command: CommandInfo, args: &[String]) -> Result<CompilationTask, String> {
		super::prepare::create_task(command, args)
	}

	fn preprocess_step(&self, task: &CompilationTask) -> Result<PreprocessResult, Error> {
		// Make parameters list for preprocessing.
		let mut args = filter(&task.args, |arg:&Arg|->Option<String> {
			match arg {
				&Arg::Flag{ref scope, ref flag} => {
					match scope {
						&Scope::Preprocessor | &Scope::Shared => Some("/".to_string() + &flag),
						&Scope::Ignore | &Scope::Compiler => None
					}
				}
				&Arg::Param{ref scope, ref  flag, ref value} => {
					match scope {
						&Scope::Preprocessor | &Scope::Shared => Some("/".to_string() + &flag + &value),
						&Scope::Ignore | &Scope::Compiler => None
					}
				}
				&Arg::Input{..} => None,
				&Arg::Output{..} => None,
			}
		});

		// Add preprocessor paramters.
		let temp_file = TempFile::new_in(&self.temp_dir, ".i");
		args.push("/nologo".to_string());
		args.push("/T".to_string() + &task.language);
		args.push("/P".to_string());
		args.push(task.input_source.display().to_string());

		// Hash data.
		let mut sip_hash = SipHasher::new();
		let hash: &mut Hasher = &mut sip_hash;
		hash.write_u8(0);
		hash.write(wincmd::join(&args).as_bytes());

		let mut command = task.command.to_command();
		command
			.args(&args)
			.arg(&join_flag("/Fi", &temp_file.path()))
			.arg(&join_flag("/Fo", &task.output_object)); // /Fo option also set output path for #import directive
		let output = try! (command.output());
		if output.status.success() {
			match File::open(temp_file.path()) {
				Ok(stream) => {
					let (mut output, sources): (Box<Read>, Vec<PathBuf>) = if task.input_precompiled.is_some() || task.output_precompiled.is_some() {
						let mut buffer: Vec<u8> = Vec::new();
						let sources = try! (postprocess::filter_preprocessed(&task.command.current_dir, &mut BufReader::new(stream), &mut buffer, &task.marker_precompiled, task.output_precompiled.is_some()));
						(Box::new(Cursor::new(buffer)), sources)
					} else {
						(Box::new(stream), Vec::new())
					};
					let mut content = Vec::new();
					try! (output.read_to_end(&mut content));
					hash.write(&content);
					Ok(PreprocessResult::Success(PreprocessedSource {
						hash: format!("{:016x}", hash.finish()),
						sources: sources,
						content: content,
					}))
				}
				Err(e) => Err(e)
			}
		} else {
			Ok(PreprocessResult::Failed(OutputInfo::new(output)))
		}
	}

	// Compile preprocessed file.
	fn compile_step(&self, task: &CompilationTask, preprocessed: PreprocessedSource) -> Result<OutputInfo, Error> {
		let mut args = filter(&task.args, |arg:&Arg|->Option<String> {
			match arg {
				&Arg::Flag{ref scope, ref flag} => {
					match scope {
						&Scope::Compiler | &Scope::Shared => Some("/".to_string() + &flag),
						&Scope::Ignore | &Scope::Preprocessor => None
					}
				}
				&Arg::Param{ref scope, ref  flag, ref value} => {
					match scope {
						&Scope::Compiler | &Scope::Shared => Some("/".to_string() + &flag + &value),
						&Scope::Ignore | &Scope::Preprocessor => None
					}
				}
				&Arg::Input{..} => None,
				&Arg::Output{..} => None
			}
		});
		args.push("/T".to_string() + &task.language);
		match &task.input_precompiled {
			&Some(ref path) => {
				args.push("/Yu".to_string());
				args.push("/Fp".to_string() + &path.display().to_string());
			}
			&None => {}
		}
		if task.output_precompiled.is_some() {
			args.push("/Yc".to_string());
		}
		// Input data, stored in files.
		let mut inputs: Vec<PathBuf> = Vec::new();
		match &task.input_precompiled {
				&Some(ref path) => {inputs.push(path.clone());}
				&None => {}
			}
		// Output files.
		let mut outputs: Vec<PathBuf> = Vec::new();
		outputs.push(task.output_object.clone());
		match &task.output_precompiled {
			&Some(ref path) => {outputs.push(path.clone());}
			&None => {}
		}

		let hash_params = hash_text(&preprocessed.content) + &wincmd::join(&args);
		self.cache.run_cached(&hash_params, &inputs, &outputs, || -> Result<OutputInfo, Error> {
			// Input file path.
			let input_temp = TempFile::new_in(&self.temp_dir, ".i");
			try! (try! (File::create(input_temp.path())).write_all(&preprocessed.content));
			// Run compiler.
			let mut command = task.command.to_command();
			command
				.args(&args)
				.arg(input_temp.path().to_str().unwrap())
				.arg("/c")
				.arg(&join_flag("/Fo", &task.output_object));
			match &task.input_precompiled {
				&Some(ref path) => {command.arg(&join_flag("/Fp", path));}
				&None => {}
			}
			match &task.output_precompiled {
				&Some(ref path) => {command.arg(&join_flag("/Fp", path));}
				&None => {}
			}
			command.output().map(|o| OutputInfo::new(o))
		})
	}
}

pub fn join_flag(flag: &str, path: &Path) -> String {
	flag.to_string() + &path.to_str().unwrap()
}<commit_msg>Create precompiled header by compiling original (not preprocessed) source file<commit_after>pub use super::super::compiler::*;

use super::super::cache::Cache;
use super::postprocess;
use super::super::wincmd;
use super::super::utils::filter;
use super::super::utils::hash_text;
use super::super::io::tempfile::TempFile;

use std::fs::File;
use std::io::{Error, BufReader, Cursor, Read, Write};
use std::hash::{SipHasher, Hasher};
use std::path::{Path, PathBuf};
use std::process::Output;

pub struct VsCompiler {
	cache: Cache,
	temp_dir: PathBuf
}

impl VsCompiler {
	pub fn new(cache: &Cache, temp_dir: &Path) -> Self {
		VsCompiler {
			cache: cache.clone(),
			temp_dir: temp_dir.to_path_buf()
		}
	}

	fn run_compiler(&self, task: &CompilationTask, source: &Path, args: &Vec<String>) -> Result<OutputInfo, Error> {
		let mut command = task.command.to_command();
		command
			.args(&args)
			.arg(source.to_str().unwrap())
			.arg("/c")
			.arg(&join_flag("/Fo", &task.output_object));
		match &task.input_precompiled {
			&Some(ref path) => {command.arg(&join_flag("/Fp", path));}
			&None => {}
		}
		match &task.output_precompiled {
			&Some(ref path) => {command.arg(&join_flag("/Fp", path));}
			&None => {}
		}
		command.output().map(|o| OutputInfo::new(o))
	}
}

impl Compiler for VsCompiler {
	fn create_task(&self, command: CommandInfo, args: &[String]) -> Result<CompilationTask, String> {
		super::prepare::create_task(command, args)
	}

	fn preprocess_step(&self, task: &CompilationTask) -> Result<PreprocessResult, Error> {
		// Make parameters list for preprocessing.
		let mut args = filter(&task.args, |arg:&Arg|->Option<String> {
			match arg {
				&Arg::Flag{ref scope, ref flag} => {
					match scope {
						&Scope::Preprocessor | &Scope::Shared => Some("/".to_string() + &flag),
						&Scope::Ignore | &Scope::Compiler => None
					}
				}
				&Arg::Param{ref scope, ref  flag, ref value} => {
					match scope {
						&Scope::Preprocessor | &Scope::Shared => Some("/".to_string() + &flag + &value),
						&Scope::Ignore | &Scope::Compiler => None
					}
				}
				&Arg::Input{..} => None,
				&Arg::Output{..} => None,
			}
		});

		// Add preprocessor paramters.
		let temp_file = TempFile::new_in(&self.temp_dir, ".i");
		args.push("/nologo".to_string());
		args.push("/T".to_string() + &task.language);
		args.push("/P".to_string());
		args.push(task.input_source.display().to_string());

		// Hash data.
		let mut sip_hash = SipHasher::new();
		let hash: &mut Hasher = &mut sip_hash;
		hash.write_u8(0);
		hash.write(wincmd::join(&args).as_bytes());

		let mut command = task.command.to_command();
		command
			.args(&args)
			.arg(&join_flag("/Fi", &temp_file.path()))
			.arg(&join_flag("/Fo", &task.output_object)); // /Fo option also set output path for #import directive
		let output = try! (command.output());
		if output.status.success() {
			match File::open(temp_file.path()) {
				Ok(stream) => {
					let (mut output, sources): (Box<Read>, Vec<PathBuf>) = if task.input_precompiled.is_some() || task.output_precompiled.is_some() {
						let mut buffer: Vec<u8> = Vec::new();
						let sources = try! (postprocess::filter_preprocessed(&task.command.current_dir, &mut BufReader::new(stream), &mut buffer, &task.marker_precompiled, task.output_precompiled.is_some()));
						(Box::new(Cursor::new(buffer)), sources)
					} else {
						(Box::new(stream), Vec::new())
					};
					let mut content = Vec::new();
					try! (output.read_to_end(&mut content));
					hash.write(&content);
					Ok(PreprocessResult::Success(PreprocessedSource {
						hash: format!("{:016x}", hash.finish()),
						sources: sources,
						content: content,
					}))
				}
				Err(e) => Err(e)
			}
		} else {
			Ok(PreprocessResult::Failed(OutputInfo::new(output)))
		}
	}

	// Compile preprocessed file.
	fn compile_step(&self, task: &CompilationTask, preprocessed: PreprocessedSource) -> Result<OutputInfo, Error> {
		let mut args = filter(&task.args, |arg:&Arg|->Option<String> {
			match arg {
				&Arg::Flag{ref scope, ref flag} => {
					match scope {
						&Scope::Compiler | &Scope::Shared => Some("/".to_string() + &flag),
						&Scope::Ignore | &Scope::Preprocessor => None
					}
				}
				&Arg::Param{ref scope, ref  flag, ref value} => {
					match scope {
						&Scope::Compiler | &Scope::Shared => Some("/".to_string() + &flag + &value),
						&Scope::Ignore | &Scope::Preprocessor => None
					}
				}
				&Arg::Input{..} => None,
				&Arg::Output{..} => None
			}
		});
		args.push("/T".to_string() + &task.language);
		match &task.input_precompiled {
			&Some(ref path) => {
				args.push("/Yu".to_string());
				args.push("/Fp".to_string() + &path.display().to_string());
			}
			&None => {}
		}
		if task.output_precompiled.is_some() {
			args.push("/Yc".to_string());
		}
		// Input data, stored in files.
		let mut inputs: Vec<PathBuf> = Vec::new();
		match &task.input_precompiled {
				&Some(ref path) => {inputs.push(path.clone());}
				&None => {}
			}
		// Output files.
		let mut outputs: Vec<PathBuf> = Vec::new();
		outputs.push(task.output_object.clone());
		match &task.output_precompiled {
			&Some(ref path) => {
				outputs.push(path.clone());
				match &task.marker_precompiled {
					&Some(ref path) => {
						args.push("/Yc".to_string() + &path);
					}
					&None => {}
				}
			}
			&None => {}
		}

		let hash_params = hash_text(&preprocessed.content) + &wincmd::join(&args);
		self.cache.run_cached(&hash_params, &inputs, &outputs, || -> Result<OutputInfo, Error> {
			match &task.output_precompiled {
				&Some(_) => {
					// Input file path.
					self.run_compiler(task, &task.input_source, &args)
				}
				&None => {
					// Input file path.
					let input_temp = TempFile::new_in(&self.temp_dir, ".i");
					try! (try! (File::create(input_temp.path())).write_all(&preprocessed.content));
					self.run_compiler(task, input_temp.path(), &args)
				}
			}
		})
	}
}

pub fn join_flag(flag: &str, path: &Path) -> String {
	flag.to_string() + &path.to_str().unwrap()
}<|endoftext|>