<commit_before>extern crate csv;
extern crate serde_json;
extern crate serde;
#[macro_use]
extern crate serde_derive;

use std::ascii::AsciiExt;
use std::io::{Write, BufReader, BufWriter};
use std::collections::HashMap;
use std::fs::File;
use std::path::Path;
use std::rc::Rc;
use std::env;

const DATA_PATH: &'static str = "misc/data.json";
const SUPPORTED_LANG_PATH: &'static str = "misc/supported_laguages.csv";

const TRIGRAPH_COUNT: usize = 300;

#[derive(Debug, Clone, PartialEq, Deserialize)]
struct SupportedLang {
    code: String,
    eng_name: String,
    name: String,
    native_speakers: Option<f64>,
}

#[derive(Debug, Clone, PartialEq)]
struct Lang<'a> {
    info: &'a SupportedLang,
    script: String,
    trigraphs: Vec<String>,
}

fn main() {
    println!("cargo:rerun-if-changed={}", DATA_PATH);
    println!("cargo:rerun-if-changed={}", SUPPORTED_LANG_PATH);
    let out_dir = env::var("OUT_DIR").unwrap();
    let dest_path = Path::new(&out_dir).join("lang.rs");
    let mut lang_def = BufWriter::new(File::create(&dest_path).unwrap());

    let data_file = BufReader::new(File::open(DATA_PATH).unwrap());
    let mut lang_reader = csv::ReaderBuilder::new().flexible(true).from_path(SUPPORTED_LANG_PATH).unwrap();

    let mut supported_langs: Vec<SupportedLang> = lang_reader.deserialize().map(Result::unwrap).collect();
    supported_langs.sort_by(|left, right| left.code.cmp(&right.code));

    let supported_lang_codes: HashMap<&str, &SupportedLang> = supported_langs.iter().map(|lang| (&*lang.code, lang)).collect();

    let capitalized_codes: HashMap<&str, String> = supported_langs.iter().map(|lang| (&*lang.code, capitalize_name(&lang.code))).collect();

    let lang_data: HashMap<String, HashMap<String, String>> = serde_json::from_reader(data_file).unwrap();

    let mut scripts: HashMap<String, Vec<Rc<Lang>>> = HashMap::with_capacity(lang_data.len());
    let mut all_langs: Vec<Rc<Lang>> = Vec::new();
    for (script, langs) in &lang_data {
        for (code, trigraphs) in langs {
            let info = match supported_lang_codes.get(&**code) {
                Some(info) => info,
                None => continue,
            };
            let lang = Rc::new(Lang {
                info: info,
                script: script.clone(),
                trigraphs: trigraphs.split('|').map(Into::into).collect()
            });
            if lang.trigraphs.len() != TRIGRAPH_COUNT {
                panic!("Languate {} has {} trigraphs, instead of {}", code, lang.trigraphs.len(), TRIGRAPH_COUNT);
            }

            all_langs.push(lang.clone());
            scripts.entry(script.clone()).or_insert_with(Vec::new).push(lang);
        }
    }

    writeln!(lang_def, "/// Represents a language following [ISO 639-3](https://en.wikipedia.org/wiki/ISO_639-3) standard.").unwrap();
    writeln!(lang_def, "#[derive(PartialEq, Eq, Debug, Hash, Clone, Copy)]").unwrap();
    writeln!(lang_def, "pub enum Lang {{").unwrap();
    for (i, supported_lang) in supported_langs.iter().enumerate() {
        writeln!(lang_def, "  /// {} ({})", supported_lang.name, supported_lang.eng_name).unwrap();
        // Number starting at 1, to allow enum optimizations to occur (e.g. Option<Lang> will be smaller)
        writeln!(lang_def, "  {} = {},", capitalize_name(&supported_lang.code), i + 1).unwrap();
    }
    writeln!(lang_def, "}}").unwrap();
    lang_def.flush().unwrap();

    writeln!(lang_def, "#[inline] fn lang_from_code<S: Into<String>>(code: S) -> Option<Lang> {{").unwrap();
    writeln!(lang_def, "  match code.into().to_lowercase().as_ref() {{").unwrap();
    for supported_lang in &supported_langs {
        writeln!(lang_def, "    \"{}\" => Some(Lang::{}),", supported_lang.code, capitalized_codes[&*supported_lang.code]).unwrap();
    }
    writeln!(lang_def, "    _ => None,").unwrap();
    writeln!(lang_def, "  }}").unwrap();
    writeln!(lang_def, "}}").unwrap();

    writeln!(lang_def, "#[inline] fn lang_to_code(lang: Lang) -> &'static str {{").unwrap();
    writeln!(lang_def, "  match lang {{").unwrap();
    for supported_lang in &supported_langs {
        writeln!(lang_def, "    Lang::{} => \"{}\",", capitalized_codes[&*supported_lang.code], supported_lang.code).unwrap();
    }
    writeln!(lang_def, "  }}").unwrap();
    writeln!(lang_def, "}}").unwrap();

    writeln!(lang_def, "#[inline] fn lang_to_name(lang: Lang) -> &'static str {{").unwrap();
    writeln!(lang_def, "  match lang {{").unwrap();
    for supported_lang in &supported_langs {
        writeln!(lang_def, "    Lang::{} => \"{}\",", capitalized_codes[&*supported_lang.code], supported_lang.name).unwrap();
    }
    writeln!(lang_def, "  }}").unwrap();
    writeln!(lang_def, "}}").unwrap();

    writeln!(lang_def, "#[inline] fn lang_to_eng_name(lang: Lang) -> &'static str {{").unwrap();
    writeln!(lang_def, "  match lang {{").unwrap();
    for supported_lang in &supported_langs {
        writeln!(lang_def, "    Lang::{} => \"{}\",", capitalized_codes[&*supported_lang.code], supported_lang.eng_name).unwrap();
    }
    writeln!(lang_def, "  }}").unwrap();
    writeln!(lang_def, "}}").unwrap();

    for (script, script_langs) in &scripts {
        writeln!(lang_def, "/// Languages for script '{}'", script).unwrap();
        writeln!(lang_def, "pub static {}_LANGS: LangProfileList = &[", script.to_ascii_uppercase()).unwrap();
        for lang in script_langs {
            writeln!(lang_def, "  (Lang::{}, &{:?}),", capitalized_codes[&*lang.info.code], lang.trigraphs).unwrap();
        }
        writeln!(lang_def, "];").unwrap();
    }
}

fn capitalize_name(name: &str) -> String {
    let mut name = String::from(name);
    name[0..1].make_ascii_uppercase();
    name
}
<commit_msg>Remove unused AsciiExt from build.rs<commit_after>extern crate csv;
extern crate serde_json;
extern crate serde;
#[macro_use]
extern crate serde_derive;

use std::io::{Write, BufReader, BufWriter};
use std::collections::HashMap;
use std::fs::File;
use std::path::Path;
use std::rc::Rc;
use std::env;

const DATA_PATH: &'static str = "misc/data.json";
const SUPPORTED_LANG_PATH: &'static str = "misc/supported_laguages.csv";

const TRIGRAPH_COUNT: usize = 300;

#[derive(Debug, Clone, PartialEq, Deserialize)]
struct SupportedLang {
    code: String,
    eng_name: String,
    name: String,
    native_speakers: Option<f64>,
}

#[derive(Debug, Clone, PartialEq)]
struct Lang<'a> {
    info: &'a SupportedLang,
    script: String,
    trigraphs: Vec<String>,
}

fn main() {
    println!("cargo:rerun-if-changed={}", DATA_PATH);
    println!("cargo:rerun-if-changed={}", SUPPORTED_LANG_PATH);
    let out_dir = env::var("OUT_DIR").unwrap();
    let dest_path = Path::new(&out_dir).join("lang.rs");
    let mut lang_def = BufWriter::new(File::create(&dest_path).unwrap());

    let data_file = BufReader::new(File::open(DATA_PATH).unwrap());
    let mut lang_reader = csv::ReaderBuilder::new().flexible(true).from_path(SUPPORTED_LANG_PATH).unwrap();

    let mut supported_langs: Vec<SupportedLang> = lang_reader.deserialize().map(Result::unwrap).collect();
    supported_langs.sort_by(|left, right| left.code.cmp(&right.code));

    let supported_lang_codes: HashMap<&str, &SupportedLang> = supported_langs.iter().map(|lang| (&*lang.code, lang)).collect();

    let capitalized_codes: HashMap<&str, String> = supported_langs.iter().map(|lang| (&*lang.code, capitalize_name(&lang.code))).collect();

    let lang_data: HashMap<String, HashMap<String, String>> = serde_json::from_reader(data_file).unwrap();

    let mut scripts: HashMap<String, Vec<Rc<Lang>>> = HashMap::with_capacity(lang_data.len());
    let mut all_langs: Vec<Rc<Lang>> = Vec::new();
    for (script, langs) in &lang_data {
        for (code, trigraphs) in langs {
            let info = match supported_lang_codes.get(&**code) {
                Some(info) => info,
                None => continue,
            };
            let lang = Rc::new(Lang {
                info: info,
                script: script.clone(),
                trigraphs: trigraphs.split('|').map(Into::into).collect()
            });
            if lang.trigraphs.len() != TRIGRAPH_COUNT {
                panic!("Languate {} has {} trigraphs, instead of {}", code, lang.trigraphs.len(), TRIGRAPH_COUNT);
            }

            all_langs.push(lang.clone());
            scripts.entry(script.clone()).or_insert_with(Vec::new).push(lang);
        }
    }

    writeln!(lang_def, "/// Represents a language following [ISO 639-3](https://en.wikipedia.org/wiki/ISO_639-3) standard.").unwrap();
    writeln!(lang_def, "#[derive(PartialEq, Eq, Debug, Hash, Clone, Copy)]").unwrap();
    writeln!(lang_def, "pub enum Lang {{").unwrap();
    for (i, supported_lang) in supported_langs.iter().enumerate() {
        writeln!(lang_def, "  /// {} ({})", supported_lang.name, supported_lang.eng_name).unwrap();
        // Number starting at 1, to allow enum optimizations to occur (e.g. Option<Lang> will be smaller)
        writeln!(lang_def, "  {} = {},", capitalize_name(&supported_lang.code), i + 1).unwrap();
    }
    writeln!(lang_def, "}}").unwrap();
    lang_def.flush().unwrap();

    writeln!(lang_def, "#[inline] fn lang_from_code<S: Into<String>>(code: S) -> Option<Lang> {{").unwrap();
    writeln!(lang_def, "  match code.into().to_lowercase().as_ref() {{").unwrap();
    for supported_lang in &supported_langs {
        writeln!(lang_def, "    \"{}\" => Some(Lang::{}),", supported_lang.code, capitalized_codes[&*supported_lang.code]).unwrap();
    }
    writeln!(lang_def, "    _ => None,").unwrap();
    writeln!(lang_def, "  }}").unwrap();
    writeln!(lang_def, "}}").unwrap();

    writeln!(lang_def, "#[inline] fn lang_to_code(lang: Lang) -> &'static str {{").unwrap();
    writeln!(lang_def, "  match lang {{").unwrap();
    for supported_lang in &supported_langs {
        writeln!(lang_def, "    Lang::{} => \"{}\",", capitalized_codes[&*supported_lang.code], supported_lang.code).unwrap();
    }
    writeln!(lang_def, "  }}").unwrap();
    writeln!(lang_def, "}}").unwrap();

    writeln!(lang_def, "#[inline] fn lang_to_name(lang: Lang) -> &'static str {{").unwrap();
    writeln!(lang_def, "  match lang {{").unwrap();
    for supported_lang in &supported_langs {
        writeln!(lang_def, "    Lang::{} => \"{}\",", capitalized_codes[&*supported_lang.code], supported_lang.name).unwrap();
    }
    writeln!(lang_def, "  }}").unwrap();
    writeln!(lang_def, "}}").unwrap();

    writeln!(lang_def, "#[inline] fn lang_to_eng_name(lang: Lang) -> &'static str {{").unwrap();
    writeln!(lang_def, "  match lang {{").unwrap();
    for supported_lang in &supported_langs {
        writeln!(lang_def, "    Lang::{} => \"{}\",", capitalized_codes[&*supported_lang.code], supported_lang.eng_name).unwrap();
    }
    writeln!(lang_def, "  }}").unwrap();
    writeln!(lang_def, "}}").unwrap();

    for (script, script_langs) in &scripts {
        writeln!(lang_def, "/// Languages for script '{}'", script).unwrap();
        writeln!(lang_def, "pub static {}_LANGS: LangProfileList = &[", script.to_ascii_uppercase()).unwrap();
        for lang in script_langs {
            writeln!(lang_def, "  (Lang::{}, &{:?}),", capitalized_codes[&*lang.info.code], lang.trigraphs).unwrap();
        }
        writeln!(lang_def, "];").unwrap();
    }
}

fn capitalize_name(name: &str) -> String {
    let mut name = String::from(name);
    name[0..1].make_ascii_uppercase();
    name
}
<|endoftext|>


<commit_before>use std::env;
use std::path::{Path, PathBuf};
use std::process;
use std::process::{Command, Stdio};
use std::fs;

fn main() {
    let target = env::var("TARGET").unwrap();
    if target.contains("android") {
        android_main()
    } else {
        println!("Android target supported only");
    }
}

fn android_main() {
    let ndk_path = env::var("ANDROID_NDK").ok().expect("Please set the ANDROID_NDK environment variable");
    let ndk_path = Path::new(&ndk_path);
    let sdk_path = env::var("ANDROID_SDK").ok().expect("Please set the ANDROID_SDK environment variable");
    let sdk_path = Path::new(&sdk_path);

    let target = env::var("TARGET").unwrap();
    let abi = if target.contains("armv7") {
        "armeabi-v7a"
    } else if target.contains("aarch64") {
        "arm64-v8a"
    } else if target.contains("arm") {
        "armeabi"
    } else if target.contains("x86") {
        "x86"
    } else {
        panic!("Invalid target architecture {}", target);
    };

    if Command::new(ndk_path.join("ndk-build"))
        .arg(format!("APP_ABI={}", abi))
        .arg("-C")
        .arg("src/jni/")
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .status().unwrap().code().unwrap() != 0
    {
        println!("Error while executing ndk-build");
        process::exit(1)
    }

    let out_dir = env::var("OUT_DIR").ok().expect("Cargo should have set the OUT_DIR environment variable");

    if Command::new("cp")
        .arg(format!("src/obj/local/{}/libblurdroid.a", abi))
        .arg(&format!("{}", out_dir))
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .status().unwrap().code().unwrap() != 0
    {
        println!("Error while executing cp");
        process::exit(1)
    }

    if Command::new("mkdir")
        .arg("-p")
        .arg("target/java/classes/")
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .status().unwrap().code().unwrap() != 0
    {
        println!("Error while executing cp");
        process::exit(1)
    }

    let java_files = fs::read_dir("src/java/hu/uszeged/bluetooth").unwrap().map(|p| p.unwrap().path()).collect::<Vec<_>>();
    let java_files = java_files.iter().map(|p| p.as_os_str().to_str().unwrap()).collect::<Vec<_>>();

    if Command::new("javac")
        .arg("-d")
        .arg("target/java/classes/")
        .arg("-cp")
        .arg(find_android_platform(sdk_path))
        .args(java_files.as_slice())
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .status().unwrap().code().unwrap() != 0
    {
        println!("Error while executing javac");
        process::exit(1)
    }

    if Command::new("jar")
        .arg("cvf")
        .arg(&format!("{}/blurdroid.jar", out_dir))
        .arg("-C")
        .arg("target/java/classes/")
        .arg("hu")
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .status().unwrap().code().unwrap() != 0
    {
        println!("Error while executing jar");
        process::exit(1)
    }

    println!("cargo:rustc-link-lib=static=blurdroid");
    println!("cargo:rustc-link-search=native={}", out_dir);
}

fn find_android_platform(sdk_path: &Path) -> PathBuf {
    // Sorted android platforms by priority
    let mut platforms = Vec::new();
    // Allow configuration using env variable
    if let Ok(platform) =  env::var("ANDROID_SDK_PLATFORM") {
        platforms.push(platform);
    }
    // Fallback to other platforms
    for v in (18..27).rev() {
        platforms.push(v.to_string());
    }

    for platfom in platforms {
        let path = sdk_path.join("platforms").join(format!("android-{}", platfom)).join("android.jar");
        if path.exists() {
            return path;
        }
    }

    panic!("Couldn't find a correct android SDK platform. Please set ANDROID_SDK_PLATFORM env variable");
}
<commit_msg>Support i686-linux-android target.<commit_after>use std::env;
use std::path::{Path, PathBuf};
use std::process;
use std::process::{Command, Stdio};
use std::fs;

fn main() {
    let target = env::var("TARGET").unwrap();
    if target.contains("android") {
        android_main()
    } else {
        println!("Android target supported only");
    }
}

fn android_main() {
    let ndk_path = env::var("ANDROID_NDK").ok().expect("Please set the ANDROID_NDK environment variable");
    let ndk_path = Path::new(&ndk_path);
    let sdk_path = env::var("ANDROID_SDK").ok().expect("Please set the ANDROID_SDK environment variable");
    let sdk_path = Path::new(&sdk_path);

    let target = env::var("TARGET").unwrap();
    let abi = if target.contains("armv7") {
        "armeabi-v7a"
    } else if target.contains("aarch64") {
        "arm64-v8a"
    } else if target.contains("arm") {
        "armeabi"
    } else if target.contains("x86") || target.contains("i686") {
        "x86"
    } else {
        panic!("Invalid target architecture {}", target);
    };

    if Command::new(ndk_path.join("ndk-build"))
        .arg(format!("APP_ABI={}", abi))
        .arg("-C")
        .arg("src/jni/")
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .status().unwrap().code().unwrap() != 0
    {
        println!("Error while executing ndk-build");
        process::exit(1)
    }

    let out_dir = env::var("OUT_DIR").ok().expect("Cargo should have set the OUT_DIR environment variable");

    if Command::new("cp")
        .arg(format!("src/obj/local/{}/libblurdroid.a", abi))
        .arg(&format!("{}", out_dir))
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .status().unwrap().code().unwrap() != 0
    {
        println!("Error while executing cp");
        process::exit(1)
    }

    if Command::new("mkdir")
        .arg("-p")
        .arg("target/java/classes/")
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .status().unwrap().code().unwrap() != 0
    {
        println!("Error while executing cp");
        process::exit(1)
    }

    let java_files = fs::read_dir("src/java/hu/uszeged/bluetooth").unwrap().map(|p| p.unwrap().path()).collect::<Vec<_>>();
    let java_files = java_files.iter().map(|p| p.as_os_str().to_str().unwrap()).collect::<Vec<_>>();

    if Command::new("javac")
        .arg("-d")
        .arg("target/java/classes/")
        .arg("-cp")
        .arg(find_android_platform(sdk_path))
        .args(java_files.as_slice())
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .status().unwrap().code().unwrap() != 0
    {
        println!("Error while executing javac");
        process::exit(1)
    }

    if Command::new("jar")
        .arg("cvf")
        .arg(&format!("{}/blurdroid.jar", out_dir))
        .arg("-C")
        .arg("target/java/classes/")
        .arg("hu")
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .status().unwrap().code().unwrap() != 0
    {
        println!("Error while executing jar");
        process::exit(1)
    }

    println!("cargo:rustc-link-lib=static=blurdroid");
    println!("cargo:rustc-link-search=native={}", out_dir);
}

fn find_android_platform(sdk_path: &Path) -> PathBuf {
    // Sorted android platforms by priority
    let mut platforms = Vec::new();
    // Allow configuration using env variable
    if let Ok(platform) =  env::var("ANDROID_SDK_PLATFORM") {
        platforms.push(platform);
    }
    // Fallback to other platforms
    for v in (18..27).rev() {
        platforms.push(v.to_string());
    }

    for platfom in platforms {
        let path = sdk_path.join("platforms").join(format!("android-{}", platfom)).join("android.jar");
        if path.exists() {
            return path;
        }
    }

    panic!("Couldn't find a correct android SDK platform. Please set ANDROID_SDK_PLATFORM env variable");
}
<|endoftext|>


<commit_before>use std::process::Command;
use std::env;

fn main() {
    let mut path = match env::var("WELD_HOME") {
        Ok(val) => val,
        Err(_) => ".".to_string(),
    };

    if path.chars().last().unwrap() != '/' {
        path = path + &"/";
    }

    Command::new("make")
        .arg("clean")
        .arg("-C")
        .arg("python/grizzly/")
        .status()
        .unwrap();

    Command::new("make")
        .arg("convertor")
        .arg("-C")
        .arg("python/grizzly/")
        .status()
        .unwrap();

    // NOTE this is pretty hacky...better way?
    let weldrt_path = path + &"weld_rt/Cargo.toml";
    Command::new("cargo")
        .arg("build")
        .arg("--manifest-path")
        .arg(weldrt_path.clone())
        .arg("--release")
        .status()
        .unwrap();
}
<commit_msg>More build.rs fixes<commit_after>use std::process::Command;
use std::env;

fn main() {
    let mut path = match env::var("WELD_HOME") {
        Ok(val) => val,
        Err(_) => ".".to_string(),
    };

    if path.chars().last().unwrap() != '/' {
        path = path + &"/";
    }

    Command::new("make")
        .arg("clean")
        .arg("-C")
        .arg("python/grizzly/")
        .status()
        .unwrap();

    Command::new("make")
        .arg("convertor")
        .arg("-C")
        .arg("python/grizzly/")
        .status()
        .unwrap();

    Command::new("make")
        .arg("-C")
        .arg("weld_rt/cpp/")
        .status()
        .unwrap();

    // NOTE this is pretty hacky...better way?
    let weldrt_path = path + &"weld_rt/Cargo.toml";
    Command::new("cargo")
        .arg("build")
        .arg("--manifest-path")
        .arg(weldrt_path.clone())
        .arg("--release")
        .status()
        .unwrap();
}
<|endoftext|>


<commit_before>use fake_tty::FakeIO;
use tty::IO;

pub struct Ansi<'a> {
    pub io: Box<(IO + 'a)>,
}

impl <'a> Ansi<'a> {
    pub fn escape(&mut self, message: &str) {
        let out = Ansi::esc(message);
        self.io.write(out.as_slice());
    }

    fn esc(input: &str) -> String {
        format!("\x1b[{}", input)
    }

    pub fn clear(&mut self) {
        self.escape("2J");
    }

    fn hide_cursor(&mut self) {
        self.escape("?251");
    }

    fn show_cursor(&mut self) {
        self.escape("?25h");
    }

    fn set_position(&mut self, line: isize, column: isize) {
        let message = format!("{};{}H", line+1, column+1);
        self.escape(message.as_slice());
    }

    fn invert(&mut self) {
        self.escape("7m");
    }

    fn reset(&mut self) {
        self.escape("0m");
    }

    pub fn inverted(&mut self, line: &str) {
        let compound = format!("{}{}{}", Ansi::esc("7m"), line, Ansi::esc("0m"));
        self.io.write(compound.as_slice());
    }

    pub fn print(&mut self, line: &str) {
        self.io.write(line);
    }
}

#[cfg(test)]

#[test]
fn it_escapes_a_str() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.escape("something");
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[something");
}

#[test]
fn it_clears_the_screen() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.clear();
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[2J");
}

#[test]
fn it_hides_the_cursos() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.hide_cursor();
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[?251");
}

#[test]
fn it_shows_the_cursor() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.show_cursor();
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[?25h");
}

#[test]
fn it_sets_the_position() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.set_position(8,12);
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[9;13H");
}

#[test]
fn it_inverts() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.invert();
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[7m");
}

fn it_prints_inverted() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.inverted("test");
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[7mtest\x1b[0m");
}

#[test]
fn it_resets() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.reset();
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[0m");
}

<commit_msg>Make ansi API public<commit_after>use fake_tty::FakeIO;
use tty::IO;

pub struct Ansi<'a> {
    pub io: Box<(IO + 'a)>,
}

impl <'a> Ansi<'a> {
    pub fn escape(&mut self, message: &str) {
        let out = Ansi::esc(message);
        self.io.write(out.as_slice());
    }

    fn esc(input: &str) -> String {
        format!("\x1b[{}", input)
    }

    pub fn clear(&mut self) {
        self.escape("2J");
    }

    pub fn hide_cursor(&mut self) {
        self.escape("?251");
    }

    pub fn show_cursor(&mut self) {
        self.escape("?25h");
    }

    pub fn set_position(&mut self, line: usize, column: usize) {
        let message = format!("{};{}H", line+1, column+1);
        self.escape(message.as_slice());
    }

    fn invert(&mut self) {
        self.escape("7m");
    }

    fn reset(&mut self) {
        self.escape("0m");
    }

    pub fn inverted(&mut self, line: &str) {
        let compound = format!("{}{}{}", Ansi::esc("7m"), line, Ansi::esc("0m"));
        self.io.write(compound.as_slice());
    }

    pub fn print(&mut self, line: &str) {
        self.io.write(line);
    }

    pub fn blank_line(&mut self, line: usize) {
        self.set_position(line, 0);
        self.escape("2K");
    }
}

#[cfg(test)]

#[test]
fn it_escapes_a_str() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.escape("something");
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[something");
}

#[test]
fn it_clears_the_screen() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.clear();
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[2J");
}

#[test]
fn it_hides_the_cursos() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.hide_cursor();
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[?251");
}

#[test]
fn it_shows_the_cursor() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.show_cursor();
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[?25h");
}

#[test]
fn it_sets_the_position() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.set_position(8,12);
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[9;13H");
}

#[test]
fn it_inverts() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.invert();
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[7m");
}

fn it_prints_inverted() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.inverted("test");
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[7mtest\x1b[0m");
}

#[test]
fn it_resets() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.reset();
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[0m");
}
<|endoftext|>


<commit_before>mod structs;

pub use self::generation::gen_frame;
pub use self::parsing::parse_frame;
pub use self::structs::*;

/// Serialization utils
pub mod generation;
/// Parsing utils
pub mod parsing;
<commit_msg>protocol: more reexports<commit_after>mod structs;

pub use self::generation::gen_frame;
pub use self::parsing::parse_frame;
pub use self::structs::*;

pub use cookie_factory::GenError;
pub use nom::Offset;

/// Serialization utils
pub mod generation;
/// Parsing utils
pub mod parsing;
<|endoftext|>


<commit_before>//! The `conf` module contains functions for loading and saving game
//! configurations.
//!
//! A `Conf` struct is used to specify hardware setup stuff used to create
//! the window and other context information.
//!
//! By default a ggez game will search its resource paths for a `/conf.toml`
//! file and load values from it when the `Context` is created.  This file
//! must be complete (ie you cannot just fill in some fields and have the
//! rest be default) and provides a nice way to specify settings that
//! can be tweaked such as window resolution, multisampling options, etc.

use std::io;
use toml;

use GameResult;

/// Possible fullscreen modes.
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum FullscreenType {
    /// Windowed mode
    Off,
    /// Real fullscreen
    True,
    /// Windowed fullscreen, generally preferred over real fullscreen
    /// these days 'cause it plays nicer with multiple monitors.
    Desktop,
}

use sdl2::video::FullscreenType as SdlFullscreenType;
impl From<SdlFullscreenType> for FullscreenType {
    fn from(other: SdlFullscreenType) -> Self {
        match other {
            SdlFullscreenType::Off => FullscreenType::Off,
            SdlFullscreenType::True => FullscreenType::True,
            SdlFullscreenType::Desktop => FullscreenType::Desktop,
        }
    }
}

impl From<FullscreenType> for SdlFullscreenType {
    fn from(other: FullscreenType) -> Self {
        match other {
            FullscreenType::Off => SdlFullscreenType::Off,
            FullscreenType::True => SdlFullscreenType::True,
            FullscreenType::Desktop => SdlFullscreenType::Desktop,
        }
    }
}

/// A builder structure containing window settings
/// that can be set at runtime and changed with `graphics::set_mode()`
///
/// Defaults:
///
/// ```rust,ignore
/// WindowMode {
///     width: 800,
///     height: 600,
///     borderless: false,
///     fullscreen_type: FullscreenType::Off,
///     vsync: true,
///     min width: 0,
///     max_width: 0,
///     min_height: 0,
///     max_height: 0,
/// }
/// ```
#[derive(Debug, Copy, Clone, SmartDefault, Serialize, Deserialize, PartialEq, Eq)]
pub struct WindowMode {
    /// Window width
    #[default = r#"800"#]
    pub width: u32,
    /// Window height
    #[default = r#"600"#]
    pub height: u32,
    /// Whether or not to show window decorations
    #[default = r#"false"#]
    pub borderless: bool,
    /// Fullscreen type
    #[default = r#"FullscreenType::Off"#]
    pub fullscreen_type: FullscreenType,
    /// Whether or not to enable vsync
    #[default = r#"true"#]
    pub vsync: bool,
    /// Minimum width for resizable windows; 0 means no limit
    #[default = r#"0"#]
    pub min_width: u32,
    /// Minimum height for resizable windows; 0 means no limit
    #[default = r#"0"#]
    pub min_height: u32,
    /// Maximum width for resizable windows; 0 means no limit
    #[default = r#"0"#]
    pub max_width: u32,
    /// Maximum height for resizable windows; 0 means no limit
    #[default = r#"0"#]
    pub max_height: u32,
}

impl WindowMode {
    /// Set borderless
    pub fn borderless(mut self, borderless: bool) -> Self {
        self.borderless = borderless;
        self
    }

    /// Set the fullscreen type
    pub fn fullscreen_type(mut self, fullscreen_type: FullscreenType) -> Self {
        self.fullscreen_type = fullscreen_type;
        self
    }

    /// Set vsync
    pub fn vsync(mut self, vsync: bool) -> Self {
        self.vsync = vsync;
        self
    }

    /// Set default window size, or screen resolution in fullscreen mode
    pub fn dimensions(mut self, width: u32, height: u32) -> Self {
        self.width = width;
        self.height = height;
        self
    }

    /// Set minimum window dimensions for windowed mode
    pub fn min_dimensions(mut self, width: u32, height: u32) -> Self {
        self.min_width = width;
        self.min_height = height;
        self
    }

    /// Set maximum window dimensions for windowed mode
    pub fn max_dimensions(mut self, width: u32, height: u32) -> Self {
        self.max_width = width;
        self.max_height = height;
        self
    }
}

/// A builder structure containing window settings
/// that must be set at init time and cannot be changed afterwards.
///
/// Defaults:
///
/// ```rust,ignore
/// WindowSetup {
///     window_title: "An easy, good game",
///     window_icon: "",
///     resizable: false,
///     allow_highdpi: true,
///     samples: NumSamples::One,
/// }
/// ```
#[derive(Debug, Clone, SmartDefault, Serialize, Deserialize, PartialEq, Eq)]
pub struct WindowSetup {
    /// The window title.
    #[default = r#""An easy, good game".to_owned()"#]
    pub title: String,
    /// A file path to the window's icon.
    /// It is rooted in the `resources` directory (see the `filesystem` module for details),
    /// and an empty string results in a blank/default icon.
    #[default = r#""".to_owned()"#]
    pub icon: String,
    /// Whether or not the window is resizable
    #[default = r#"false"#]
    pub resizable: bool,
    /// Whether or not to allow high DPI mode when creating the window
    #[default = r#"true"#]
    pub allow_highdpi: bool,
    /// Number of samples for multisample anti-aliasing
    #[default = r#"NumSamples::One"#]
    pub samples: NumSamples,
}

impl WindowSetup {
    /// Set window title
    pub fn title(mut self, title: &str) -> Self {
        self.title = title.to_owned();
        self
    }

    /// Set the window's icon.
    pub fn icon(mut self, icon: &str) -> Self {
        self.icon = icon.to_owned();
        self
    }

    /// Set resizable
    pub fn resizable(mut self, resizable: bool) -> Self {
        self.resizable = resizable;
        self
    }

    /// Set allow_highdpi
    pub fn allow_highdpi(mut self, allow: bool) -> Self {
        self.allow_highdpi = allow;
        self
    }

    /// Set number of samples
    ///
    /// Returns None if given an invalid value
    /// (valid values are powers of 2 from 1 to 16)
    pub fn samples(mut self, samples: u32) -> Option<Self> {
        match NumSamples::from_u32(samples) {
            Some(s) => {
                self.samples = s;
                Some(self)
            }
            None => None,
        }
    }
}

/// Possible backends.
/// Currently, only OpenGL Core spec is supported,
/// but this lets you specify the version numbers.
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, SmartDefault)]
#[serde(tag = "type")]
pub enum Backend {
    /// Defaults to OpenGL 3.2, which is supported by basically
    /// every machine since 2009 or so (apart from the ones that don't)
    #[default]
    OpenGL {
        /// OpenGL major version
        #[default = r#"3"#]
        major: u8,
        /// OpenGL minor version
        #[default = r#"2"#]
        minor: u8,
    },
}

/// The possible number of samples for multisample anti-aliasing
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum NumSamples {
    /// One sample
    One = 1,
    /// Two samples
    Two = 2,
    /// Four samples
    Four = 4,
    /// Eight samples
    Eight = 8,
    /// Sixteen samples
    Sixteen = 16,
}

impl NumSamples {
    /// Create a NumSamples from a number.
    /// Returns None if i is invalid.
    pub fn from_u32(i: u32) -> Option<NumSamples> {
        match i {
            1 => Some(NumSamples::One),
            2 => Some(NumSamples::Two),
            4 => Some(NumSamples::Four),
            8 => Some(NumSamples::Eight),
            16 => Some(NumSamples::Sixteen),
            _ => None,
        }
    }
}

/// A structure containing configuration data
/// for the game engine.
///
/// Defaults:
///
/// ```rust,ignore
/// Conf {
///     window_mode: WindowMode::default(),
///     window_setup: WindowSetup::default(),
///     backend: Backend::OpenGL(3, 2),
/// }
/// ```
#[derive(Serialize, Deserialize, Debug, PartialEq, SmartDefault)]
pub struct Conf {
    /// Window setting information that can be set at runtime
    pub window_mode: WindowMode,
    /// Window setting information that must be set at init-time
    pub window_setup: WindowSetup,
    /// Backend configuration
    pub backend: Backend,
}

impl Conf {
    /// Same as Conf::default()
    pub fn new() -> Self {
        Self::default()
    }

    /// Load a TOML file from the given `Read` and attempts to parse
    /// a `Conf` from it.
    pub fn from_toml_file<R: io::Read>(file: &mut R) -> GameResult<Conf> {
        let mut s = String::new();
        file.read_to_string(&mut s)?;
        let decoded = toml::from_str(&s)?;
        Ok(decoded)
    }

    /// Saves the `Conf` to the given `Write` object,
    /// formatted as TOML.
    pub fn to_toml_file<W: io::Write>(&self, file: &mut W) -> GameResult<()> {
        let s = toml::to_vec(self)?;
        file.write_all(&s)?;
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use conf;

    /// Tries to encode and decode a `Conf` object
    /// and makes sure it gets the same result it had.
    #[test]
    fn encode_round_trip() {
        let c1 = conf::Conf::new();
        let mut writer = Vec::new();
        let _c = c1.to_toml_file(&mut writer).unwrap();
        let mut reader = writer.as_slice();
        let c2 = conf::Conf::from_toml_file(&mut reader).unwrap();
        assert_eq!(c1, c2);
    }
}
<commit_msg>Fix WindowSetup documentation<commit_after>//! The `conf` module contains functions for loading and saving game
//! configurations.
//!
//! A `Conf` struct is used to specify hardware setup stuff used to create
//! the window and other context information.
//!
//! By default a ggez game will search its resource paths for a `/conf.toml`
//! file and load values from it when the `Context` is created.  This file
//! must be complete (ie you cannot just fill in some fields and have the
//! rest be default) and provides a nice way to specify settings that
//! can be tweaked such as window resolution, multisampling options, etc.

use std::io;
use toml;

use GameResult;

/// Possible fullscreen modes.
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum FullscreenType {
    /// Windowed mode
    Off,
    /// Real fullscreen
    True,
    /// Windowed fullscreen, generally preferred over real fullscreen
    /// these days 'cause it plays nicer with multiple monitors.
    Desktop,
}

use sdl2::video::FullscreenType as SdlFullscreenType;
impl From<SdlFullscreenType> for FullscreenType {
    fn from(other: SdlFullscreenType) -> Self {
        match other {
            SdlFullscreenType::Off => FullscreenType::Off,
            SdlFullscreenType::True => FullscreenType::True,
            SdlFullscreenType::Desktop => FullscreenType::Desktop,
        }
    }
}

impl From<FullscreenType> for SdlFullscreenType {
    fn from(other: FullscreenType) -> Self {
        match other {
            FullscreenType::Off => SdlFullscreenType::Off,
            FullscreenType::True => SdlFullscreenType::True,
            FullscreenType::Desktop => SdlFullscreenType::Desktop,
        }
    }
}

/// A builder structure containing window settings
/// that can be set at runtime and changed with `graphics::set_mode()`
///
/// Defaults:
///
/// ```rust,ignore
/// WindowMode {
///     width: 800,
///     height: 600,
///     borderless: false,
///     fullscreen_type: FullscreenType::Off,
///     vsync: true,
///     min width: 0,
///     max_width: 0,
///     min_height: 0,
///     max_height: 0,
/// }
/// ```
#[derive(Debug, Copy, Clone, SmartDefault, Serialize, Deserialize, PartialEq, Eq)]
pub struct WindowMode {
    /// Window width
    #[default = r#"800"#]
    pub width: u32,
    /// Window height
    #[default = r#"600"#]
    pub height: u32,
    /// Whether or not to show window decorations
    #[default = r#"false"#]
    pub borderless: bool,
    /// Fullscreen type
    #[default = r#"FullscreenType::Off"#]
    pub fullscreen_type: FullscreenType,
    /// Whether or not to enable vsync
    #[default = r#"true"#]
    pub vsync: bool,
    /// Minimum width for resizable windows; 0 means no limit
    #[default = r#"0"#]
    pub min_width: u32,
    /// Minimum height for resizable windows; 0 means no limit
    #[default = r#"0"#]
    pub min_height: u32,
    /// Maximum width for resizable windows; 0 means no limit
    #[default = r#"0"#]
    pub max_width: u32,
    /// Maximum height for resizable windows; 0 means no limit
    #[default = r#"0"#]
    pub max_height: u32,
}

impl WindowMode {
    /// Set borderless
    pub fn borderless(mut self, borderless: bool) -> Self {
        self.borderless = borderless;
        self
    }

    /// Set the fullscreen type
    pub fn fullscreen_type(mut self, fullscreen_type: FullscreenType) -> Self {
        self.fullscreen_type = fullscreen_type;
        self
    }

    /// Set vsync
    pub fn vsync(mut self, vsync: bool) -> Self {
        self.vsync = vsync;
        self
    }

    /// Set default window size, or screen resolution in fullscreen mode
    pub fn dimensions(mut self, width: u32, height: u32) -> Self {
        self.width = width;
        self.height = height;
        self
    }

    /// Set minimum window dimensions for windowed mode
    pub fn min_dimensions(mut self, width: u32, height: u32) -> Self {
        self.min_width = width;
        self.min_height = height;
        self
    }

    /// Set maximum window dimensions for windowed mode
    pub fn max_dimensions(mut self, width: u32, height: u32) -> Self {
        self.max_width = width;
        self.max_height = height;
        self
    }
}

/// A builder structure containing window settings
/// that must be set at init time and cannot be changed afterwards.
///
/// Defaults:
///
/// ```rust,ignore
/// WindowSetup {
///     title: "An easy, good game".to_owned(),
///     icon: "".to_owned(),
///     resizable: false,
///     allow_highdpi: true,
///     samples: NumSamples::One,
/// }
/// ```
#[derive(Debug, Clone, SmartDefault, Serialize, Deserialize, PartialEq, Eq)]
pub struct WindowSetup {
    /// The window title.
    #[default = r#""An easy, good game".to_owned()"#]
    pub title: String,
    /// A file path to the window's icon.
    /// It is rooted in the `resources` directory (see the `filesystem` module for details),
    /// and an empty string results in a blank/default icon.
    #[default = r#""".to_owned()"#]
    pub icon: String,
    /// Whether or not the window is resizable
    #[default = r#"false"#]
    pub resizable: bool,
    /// Whether or not to allow high DPI mode when creating the window
    #[default = r#"true"#]
    pub allow_highdpi: bool,
    /// Number of samples for multisample anti-aliasing
    #[default = r#"NumSamples::One"#]
    pub samples: NumSamples,
}

impl WindowSetup {
    /// Set window title
    pub fn title(mut self, title: &str) -> Self {
        self.title = title.to_owned();
        self
    }

    /// Set the window's icon.
    pub fn icon(mut self, icon: &str) -> Self {
        self.icon = icon.to_owned();
        self
    }

    /// Set resizable
    pub fn resizable(mut self, resizable: bool) -> Self {
        self.resizable = resizable;
        self
    }

    /// Set allow_highdpi
    pub fn allow_highdpi(mut self, allow: bool) -> Self {
        self.allow_highdpi = allow;
        self
    }

    /// Set number of samples
    ///
    /// Returns None if given an invalid value
    /// (valid values are powers of 2 from 1 to 16)
    pub fn samples(mut self, samples: u32) -> Option<Self> {
        match NumSamples::from_u32(samples) {
            Some(s) => {
                self.samples = s;
                Some(self)
            }
            None => None,
        }
    }
}

/// Possible backends.
/// Currently, only OpenGL Core spec is supported,
/// but this lets you specify the version numbers.
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, SmartDefault)]
#[serde(tag = "type")]
pub enum Backend {
    /// Defaults to OpenGL 3.2, which is supported by basically
    /// every machine since 2009 or so (apart from the ones that don't)
    #[default]
    OpenGL {
        /// OpenGL major version
        #[default = r#"3"#]
        major: u8,
        /// OpenGL minor version
        #[default = r#"2"#]
        minor: u8,
    },
}

/// The possible number of samples for multisample anti-aliasing
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum NumSamples {
    /// One sample
    One = 1,
    /// Two samples
    Two = 2,
    /// Four samples
    Four = 4,
    /// Eight samples
    Eight = 8,
    /// Sixteen samples
    Sixteen = 16,
}

impl NumSamples {
    /// Create a NumSamples from a number.
    /// Returns None if i is invalid.
    pub fn from_u32(i: u32) -> Option<NumSamples> {
        match i {
            1 => Some(NumSamples::One),
            2 => Some(NumSamples::Two),
            4 => Some(NumSamples::Four),
            8 => Some(NumSamples::Eight),
            16 => Some(NumSamples::Sixteen),
            _ => None,
        }
    }
}

/// A structure containing configuration data
/// for the game engine.
///
/// Defaults:
///
/// ```rust,ignore
/// Conf {
///     window_mode: WindowMode::default(),
///     window_setup: WindowSetup::default(),
///     backend: Backend::OpenGL(3, 2),
/// }
/// ```
#[derive(Serialize, Deserialize, Debug, PartialEq, SmartDefault)]
pub struct Conf {
    /// Window setting information that can be set at runtime
    pub window_mode: WindowMode,
    /// Window setting information that must be set at init-time
    pub window_setup: WindowSetup,
    /// Backend configuration
    pub backend: Backend,
}

impl Conf {
    /// Same as Conf::default()
    pub fn new() -> Self {
        Self::default()
    }

    /// Load a TOML file from the given `Read` and attempts to parse
    /// a `Conf` from it.
    pub fn from_toml_file<R: io::Read>(file: &mut R) -> GameResult<Conf> {
        let mut s = String::new();
        file.read_to_string(&mut s)?;
        let decoded = toml::from_str(&s)?;
        Ok(decoded)
    }

    /// Saves the `Conf` to the given `Write` object,
    /// formatted as TOML.
    pub fn to_toml_file<W: io::Write>(&self, file: &mut W) -> GameResult<()> {
        let s = toml::to_vec(self)?;
        file.write_all(&s)?;
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use conf;

    /// Tries to encode and decode a `Conf` object
    /// and makes sure it gets the same result it had.
    #[test]
    fn encode_round_trip() {
        let c1 = conf::Conf::new();
        let mut writer = Vec::new();
        let _c = c1.to_toml_file(&mut writer).unwrap();
        let mut reader = writer.as_slice();
        let c2 = conf::Conf::from_toml_file(&mut reader).unwrap();
        assert_eq!(c1, c2);
    }
}
<|endoftext|>


<commit_before>//! Solver configuration, contains backend solver specific info.

use std::fmt ;

use self::SolverStyle::* ;

/// A configuration item is either a keyword or unsupported.
pub type ConfItem = Option<& 'static str> ;

/// Value of an unsupported configuration item.
#[inline(always)]
fn unsupported() -> ConfItem { None }
/// Keyword for a configuration item.
#[inline(always)]
fn supported(keyword: & 'static str) -> ConfItem { Some(keyword) }

/// Solver styles.
#[derive(Debug, Clone)]
pub enum SolverStyle {
  /// Z3-style smt solver.
  Z3,
  /// CVC4-style smt solver.
  CVC4,
}

impl SolverStyle {
  /// Default configuration for a solver style.
  pub fn default(self) -> SolverConf {
    let cmd = self.cmd() ;
    match self {
      Z3 => SolverConf {
        style: self,
        cmd: cmd,
        options: vec![
          "-in", "-smt2"
        ],
        parse_success: false,
        unsat_cores: false,
        check_sat_assuming: supported("check-sat"),
      },
      CVC4 => SolverConf {
        style: self,
        cmd: cmd,
        options: vec![
          "--smtlib-strict", "-qqqqq", "--interactive"
        ],
        parse_success: false,
        unsat_cores: false,
        check_sat_assuming: unsupported(),
      },
    }
  }
  /// A solver style from a string.
  pub fn of_str(s: & str) -> Option<SolverStyle> {
    match s {
      "z3" | "Z3" => Some(Z3),
      "cvc4" | "CVC4" => Some(CVC4),
      _ => None,
    }
  }
  /// Legal string representations of solver styles.
  pub fn str_keys() -> Vec<& 'static str> {
    vec![ "z3", "Z3", "cvc4", "CVC4" ]
  }
  /// Default command for a solver style.
  #[cfg( not(windows) )]
  pub fn cmd(& self) -> String {
    match * self {
      Z3 => "z3".to_string(), CVC4 => "cvc4".to_string(),
    }
  }
  /// Default command for a solver style.
  #[cfg( windows )]
  pub fn cmd(& self) -> String {
    match * self {
      Z3 => "z3.exe".to_string(), CVC4 => "cvc4.exe".to_string(),
    }
  }
}

impl fmt::Display for SolverStyle {
  fn fmt(& self, fmt: & mut fmt::Formatter) -> fmt::Result {
    match * self {
      Z3 => write!(fmt, "z3"),
      CVC4 => write!(fmt, "cvc4"),
    }
  }
}

/// Configuration and solver specific info.
#[derive(Debug, Clone)]
pub struct SolverConf {
  /// Solver style.
  style: SolverStyle,
  /// Solver command.
  cmd: String,
  /// Options to call the solver with.
  options: Vec<& 'static str>,
  /// Parse success.
  parse_success: bool,
  /// Triggers unsat-core production.
  unsat_cores: bool,
  /// Keyword for check-sat with assumptions.
  check_sat_assuming: ConfItem,
}

impl SolverConf {
  /// Creates a new z3-like solver configuration.
  #[inline(always)]
  pub fn z3() -> Self { Z3.default() }

  /// Creates a new CVC4-like solver configuration.
  #[inline(always)]
  pub fn cvc4() -> Self { CVC4.default() }

  /// Solver style.
  #[inline(always)]
  pub fn style(& self) -> & SolverStyle { & self.style }

  /// Solver command.
  #[inline(always)]
  pub fn get_cmd(& self) -> & str { & self.cmd }

  /// Options of the configuration.
  #[inline(always)]
  pub fn get_options(& self) -> & [& 'static str] { & self.options }

  /// Indicates if parse success is active.
  #[inline(always)]
  pub fn get_parse_success(& self) -> bool { self.parse_success }

  /// Keyword for check-sat with assumptions.
  #[inline(always)]
  pub fn get_check_sat_assuming(& self) -> & ConfItem {
    & self.check_sat_assuming
  }

  /// Adds an option to the configuration.
  #[inline(always)]
  pub fn option(mut self, o: & 'static str) -> Self {
    self.options.push(o) ;
    self
  }

  /// Sets the command for the solver.
  #[inline(always)]
  pub fn cmd(mut self, cmd: String) -> Self {
    self.cmd = cmd ;
    self
  }

  /// Activates parse sucess.
  #[inline(always)]
  #[cfg(not(no_parse_success))]
  pub fn print_success(mut self) -> Self {
    self.parse_success = true ;
    self
  }

  /// Activates unsat-core production.
  #[inline(always)]
  pub fn unsat_cores(mut self) -> Self {
    self.unsat_cores = true ;
    self
  }

  // /// Creates a solver instance.
  // #[inline(always)]
  // pub fn mk<Parser>(
  //   self, cmd: Command, parser: Parser
  // ) -> io::Result<Solver<Parser>> {
  //   Solver::mk(cmd, self, parser)
  // }
}<commit_msg>helper conf functions for cvc4 and z3<commit_after>//! Solver configuration, contains backend solver specific info.

use std::fmt ;

use self::SolverStyle::* ;

/// A configuration item is either a keyword or unsupported.
pub type ConfItem = Option<& 'static str> ;

/// Value of an unsupported configuration item.
#[inline(always)]
fn unsupported() -> ConfItem { None }
/// Keyword for a configuration item.
#[inline(always)]
fn supported(keyword: & 'static str) -> ConfItem { Some(keyword) }

/// Solver styles.
#[derive(Debug, Clone)]
pub enum SolverStyle {
  /// Z3-style smt solver.
  Z3,
  /// CVC4-style smt solver.
  CVC4,
}

impl SolverStyle {
  /// Default configuration for a solver style.
  pub fn default(self) -> SolverConf {
    let cmd = self.cmd() ;
    match self {
      Z3 => SolverConf {
        style: self,
        cmd: cmd,
        options: vec![
          "-in", "-smt2"
        ],
        parse_success: false,
        unsat_cores: false,
        check_sat_assuming: supported("check-sat"),
      },
      CVC4 => SolverConf {
        style: self,
        cmd: cmd,
        options: vec![
          "--smtlib-strict", "-qqqqq", "--interactive"
        ],
        parse_success: false,
        unsat_cores: false,
        check_sat_assuming: unsupported(),
      },
    }
  }
  /// A solver style from a string.
  pub fn of_str(s: & str) -> Option<SolverStyle> {
    match s {
      "z3" | "Z3" => Some(Z3),
      "cvc4" | "CVC4" => Some(CVC4),
      _ => None,
    }
  }
  /// Legal string representations of solver styles.
  pub fn str_keys() -> Vec<& 'static str> {
    vec![ "z3", "Z3", "cvc4", "CVC4" ]
  }
  /// Default command for a solver style.
  #[cfg( not(windows) )]
  pub fn cmd(& self) -> String {
    match * self {
      Z3 => "z3".to_string(), CVC4 => "cvc4".to_string(),
    }
  }
  /// Default command for a solver style.
  #[cfg( windows )]
  pub fn cmd(& self) -> String {
    match * self {
      Z3 => "z3.exe".to_string(), CVC4 => "cvc4.exe".to_string(),
    }
  }
}

impl fmt::Display for SolverStyle {
  fn fmt(& self, fmt: & mut fmt::Formatter) -> fmt::Result {
    match * self {
      Z3 => write!(fmt, "z3"),
      CVC4 => write!(fmt, "cvc4"),
    }
  }
}

/// Creates a default z3 solver configuration.
#[inline]
pub fn z3() -> SolverConf {
  SolverConf::z3()
}

/// Creates a default cvc4 solver configuration.
#[inline]
pub fn cvc4() -> SolverConf {
  SolverConf::cvc4()
}

/// Configuration and solver specific info.
#[derive(Debug, Clone)]
pub struct SolverConf {
  /// Solver style.
  style: SolverStyle,
  /// Solver command.
  cmd: String,
  /// Options to call the solver with.
  options: Vec<& 'static str>,
  /// Parse success.
  parse_success: bool,
  /// Triggers unsat-core production.
  unsat_cores: bool,
  /// Keyword for check-sat with assumptions.
  check_sat_assuming: ConfItem,
}

impl SolverConf {
  /// Creates a new z3-like solver configuration.
  #[inline(always)]
  pub fn z3() -> Self { Z3.default() }

  /// Creates a new CVC4-like solver configuration.
  #[inline(always)]
  pub fn cvc4() -> Self { CVC4.default() }

  /// Solver style.
  #[inline(always)]
  pub fn style(& self) -> & SolverStyle { & self.style }

  /// Solver command.
  #[inline(always)]
  pub fn get_cmd(& self) -> & str { & self.cmd }

  /// Options of the configuration.
  #[inline(always)]
  pub fn get_options(& self) -> & [& 'static str] { & self.options }

  /// Indicates if parse success is active.
  #[inline(always)]
  pub fn get_parse_success(& self) -> bool { self.parse_success }

  /// Keyword for check-sat with assumptions.
  #[inline(always)]
  pub fn get_check_sat_assuming(& self) -> & ConfItem {
    & self.check_sat_assuming
  }

  /// Adds an option to the configuration.
  #[inline(always)]
  pub fn option(mut self, o: & 'static str) -> Self {
    self.options.push(o) ;
    self
  }

  /// Sets the command for the solver.
  #[inline(always)]
  pub fn cmd(mut self, cmd: String) -> Self {
    self.cmd = cmd ;
    self
  }

  /// Activates parse sucess.
  #[inline(always)]
  #[cfg(not(no_parse_success))]
  pub fn print_success(mut self) -> Self {
    self.parse_success = true ;
    self
  }

  /// Activates unsat-core production.
  #[inline(always)]
  pub fn unsat_cores(mut self) -> Self {
    self.unsat_cores = true ;
    self
  }

  // /// Creates a solver instance.
  // #[inline(always)]
  // pub fn mk<Parser>(
  //   self, cmd: Command, parser: Parser
  // ) -> io::Result<Solver<Parser>> {
  //   Solver::mk(cmd, self, parser)
  // }
}<|endoftext|>


<commit_before>fn main() {
    // Re-export the TARGET environment variable so it can
    // be accessed by miri.
    let target = std::env::var("TARGET").unwrap();
    println!("cargo:rustc-env=TARGET={}", target);
}
<commit_msg>Auto merge of #2515 - RalfJung:build, r=RalfJung<commit_after>fn main() {
    // Don't rebuild miri when nothing changed.
    println!("cargo:rerun-if-changed=build.rs");
    // Re-export the TARGET environment variable so it can
    // be accessed by miri.
    let target = std::env::var("TARGET").unwrap();
    println!("cargo:rustc-env=TARGET={}", target);
}
<|endoftext|>


<commit_before>extern crate cmake;

fn main() {
    // Builds the project in the directory located in `chipmunk`, installing it
    // into $OUT_DIR
    let dst = cmake::Config::new("chipmunk")
            .define("BUILD_DEMOS", "OFF")
            .define("INSTALL_DEMOS", "OFF")
            .define("BUILD_SHARED", "OFF")
            .build();

    println!("cargo:rustc-link-search=native={}", dst.join("lib").display());
    println!("cargo:rustc-link-lib=static=chipmunk");
}
<commit_msg>Support release build.<commit_after>extern crate cmake;

use std::env::var;
use std::str::FromStr;

const DEBUG_DEFAULT: bool = false;

fn main() {
    // Builds the project in the directory located in `chipmunk`, installing it
    // into $OUT_DIR
    let debug: bool = var("DEBUG")
        .map(|s| bool::from_str(&s).unwrap_or(DEBUG_DEFAULT))
        .unwrap_or(DEBUG_DEFAULT);

    let dst = cmake::Config::new("chipmunk")
        .define("BUILD_DEMOS", "OFF")
        .define("INSTALL_DEMOS", "OFF")
        .define("BUILD_SHARED", "OFF")
        .define("CMAKE_BUILD_TYPE", if debug { "Debug" } else { "Release" })
        .build();

    println!("cargo:rustc-link-search=native={}",
             dst.join("lib").display());
    println!("cargo:rustc-link-lib=static=chipmunk");
}
<|endoftext|>


<commit_before>#![cfg_attr(feature = "performance-counter", feature(convert))]

#[cfg(not(feature = "performance-counter"))]
fn main() {}

#[cfg(feature = "performance-counter")]
fn main() {
    performance_counter::main();
}

#[cfg(feature = "performance-counter")]
mod performance_counter {

extern crate phf_codegen;
extern crate serde_json;
extern crate csv;

use std::ascii::AsciiExt;
use std::env;
use std::fs::File;
use std::io::{BufWriter, BufReader, Write};
use std::path::Path;
use std::collections::HashMap;
use std::mem;

use self::serde_json::Value;

include!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/perfcnt/intel/description.rs"));

/// HACK: We need to convert parsed strings to static because we're reusing
/// the struct definition which declare strings as static in the generated code.
fn string_to_static_str<'a>(s: &'a str) -> &'static str {
    unsafe {
        let ret = mem::transmute(&s as &str);
        mem::forget(s);
        ret
    }
}

fn parse_bool(input: &str) -> bool {
    match input.trim() {
        "0" => false,
        "1" => true,
        _ => panic!("Unknown boolean value {}", input),
    }
}

fn parse_hex_numbers(split_str_parts: Vec<&str>) -> Vec<u64> {
    split_str_parts.iter()
        .map(|x| {
            assert!(x.starts_with("0x"));
            match u64::from_str_radix(&x[2..], 16) {
                Ok(u) => u,
                Err(e) => panic!("{}: Can not parse {}", e, x)
            }
        }).collect()
}

fn parse_number(value_str: &str) -> u64 {
    if value_str.len() > 2 && value_str[..2].starts_with("0x") {
        match u64::from_str_radix(&value_str[2..], 16) {
            Ok(u) => u,
            Err(e) => panic!("{}: Can not parse {}", e, value_str)
        }
    }
    else {
        match u64::from_str_radix(&value_str, 10) {
            Ok(u) => u,
            Err(e) => panic!("{}: Can not parse {}", e, value_str)
        }
    }
}

fn parse_counter_values(value_str: &str) -> u64 {
    value_str.split(",").map(|x| x.trim())
        .filter(|x| x.len() > 0)
        .map(|x| {
            match u64::from_str_radix(&x, 10) {
                Ok(u) => u,
                Err(e) => panic!("{}: Can not parse {} in {}", e, x, value_str)
            }
        }).fold(0, |acc, c| { assert!(c < 8); acc | 1 << c })
}

fn parse_null_string(value_str: &str) -> Option<&str> {
    if value_str != "null" {
        Some(value_str)
    }
    else {
        None
    }
}

fn parse_counters(value_str: &str) -> Counter {
    if value_str.to_lowercase().starts_with("fixed counter") {
        let mask: u64 = parse_counter_values(&value_str["fixed counter".len()..]);
        Counter::Fixed(mask as u8)
    }
    else if value_str.to_lowercase().starts_with("fixed") {
        let mask: u64 = parse_counter_values(&value_str["fixed".len()..]);
        Counter::Fixed(mask as u8)
    }
    else {
        let mask: u64 = parse_counter_values(value_str);
        Counter::Programmable(mask as u8)
    }
}

fn parse_pebs(value_str: &str) -> PebsType {
    match value_str.trim() {
        "0" => PebsType::Regular,
        "1" => PebsType::PebsOrRegular,
        "2" => PebsType::PebsOnly,
        _ => panic!("Unknown PEBS type: {}", value_str),
    }
}

fn parse_performance_counters(input: &str, variable: &str, file: &mut BufWriter<File>) {
    let mut builder = phf_codegen::Map::new();
    let f = File::open(input).unwrap();
    let reader = BufReader::new(f);
    let data: Value = serde_json::from_reader(reader).unwrap();
    let mut all_events = HashMap::new();

    if data.is_array() {
        let entries = data.as_array().unwrap();
        for entry in entries.iter() {

            if !entry.is_object() {
                panic!("Expected JSON object.");
            }
            let pcn = entry.as_object().unwrap();

            let mut event_code = Tuple::One(0);
            let mut umask = Tuple::One(0);
            let mut event_name = "";
            let mut brief_description = "";
            let mut public_description = None;
            let mut counter = Counter::Fixed(0);
            let mut counter_ht_off = Counter::Fixed(0);
            let mut pebs_counters = None;
            let mut sample_after_value = 0;
            let mut msr_index = MSRIndex::None;
            let mut msr_value = 0;
            let mut taken_alone = false;
            let mut counter_mask = 0;
            let mut invert = false;
            let mut any_thread = false;
            let mut edge_detect = false;
            let mut pebs = PebsType::Regular;
            let mut precise_store = false;
            let mut data_la = false;
            let mut l1_hit_indication = false;
            let mut errata = None;
            let mut offcore = false;
            let mut unit = None;
            let mut filter = None;
            let mut extsel = false;

            let mut do_insert: bool = false;

            for (key, value) in pcn.iter() {
                if !value.is_string() {
                    panic!("Not a string");
                }

                println!("key = {} value = {}", key, value.as_string().unwrap());
                let value_string = value.as_string().unwrap();
                let value_str = string_to_static_str(value_string).trim();
                let split_str_parts: Vec<&str> = value_string.split(",").map(|x| x.trim()).collect();

                match key.as_str() {
                    "EventName" => {
                        if !all_events.contains_key(value_str.clone()) {
                            all_events.insert(value_str, 0);
                            assert!(all_events.contains_key(value_str));
                            do_insert = true;
                        }
                        else {
                            do_insert = false;
                            println!("WARN: Key {} already exists.", value_str);
                        }
                        event_name = value_str;
                    }
                    "EventCode" => {
                        let split_parts: Vec<u64> = parse_hex_numbers(split_str_parts);
                        match split_parts.len() {
                            1 => event_code = Tuple::One(split_parts[0] as u8),
                            2 => event_code = Tuple::Two(split_parts[0] as u8, split_parts[1] as u8),
                            _ => panic!("More than two event codes?")
                        }
                    },
                    "UMask" => {
                        let split_parts: Vec<u64> = parse_hex_numbers(split_str_parts);
                        match split_parts.len() {
                            1 => umask = Tuple::One(split_parts[0] as u8),
                            2 => umask = Tuple::Two(split_parts[0] as u8, split_parts[1] as u8),
                            _ => panic!("More than two event codes?")
                        }
                    },
                    "BriefDescription" => brief_description = value_str,
                    "PublicDescription" => {
                        if brief_description != value_str && value_str != "tbd" {
                            public_description = Some(value_str);
                        }
                        else {
                            public_description = None;
                        }
                    },
                    "Counter" => counter = parse_counters(value_str),
                    "CounterHTOff" => counter_ht_off = parse_counters(value_str),
                    "PEBScounters" => pebs_counters = Some(parse_counters(value_str)),
                    "SampleAfterValue" => sample_after_value = parse_number(value_str),
                    "MSRIndex" => {
                        let split_parts: Vec<u64> = value_str
                            .split(",")
                            .map(|x| x.trim())
                            .map(|x| parse_number(x))
                            .collect();

                            msr_index = match split_parts.len() {
                                1 => {
                                    if split_parts[0] != 0 {
                                        MSRIndex::One(split_parts[0] as u8)
                                    }
                                    else {
                                        MSRIndex::None
                                    }
                                },
                                2 => MSRIndex::Two(split_parts[0] as u8, split_parts[1] as u8),
                                _ => panic!("More than two MSR indexes?")
                            }
                    },
                    "MSRValue" => msr_value = parse_number(value_str),
                    "TakenAlone" => taken_alone = parse_bool(value_str),
                    "CounterMask" => counter_mask = parse_number(value_str) as u8,
                    "Invert" => invert = parse_bool(value_str),
                    "AnyThread" => any_thread = parse_bool(value_str),
                    "EdgeDetect" => edge_detect = parse_bool(value_str),
                    "PEBS" => pebs = parse_pebs(value_str),
                    "PRECISE_STORE" => precise_store = parse_bool(value_str),
                    "Data_LA" => data_la = parse_bool(value_str),
                    "L1_Hit_Indication" => l1_hit_indication = parse_bool(value_str),
                    "Errata" => errata = parse_null_string(value_str),
                    "Offcore" => offcore = parse_bool(value_str),
                    "Unit" => unit = parse_null_string(value_str),
                    "Filter" => filter = parse_null_string(value_str),
                    "ExtSel" => extsel = parse_bool(value_str),
                    "ELLC" => {/* Ignored due to missing documentation. */ },
                    _ => panic!("Unknown member: {} in file {}", key, input),
                };
            }

            let ipcd = IntelPerformanceCounterDescription::new(
                event_code,
                umask,
                event_name,
                brief_description,
                public_description,
                counter,
                counter_ht_off,
                pebs_counters,
                sample_after_value,
                msr_index,
                msr_value,
                taken_alone,
                counter_mask,
                invert,
                any_thread,
                edge_detect,
                pebs,
                precise_store,
                data_la,
                l1_hit_indication,
                errata,
                offcore,
                unit,
                filter,
                extsel
            );

            //println!("{:?}", ipcd.event_name);
            if do_insert == true {
                builder.entry(ipcd.event_name, format!("{:?}", ipcd).as_str());
            }
        }
    }
    else {
        panic!("JSON data is not an array.");
    }

    write!(file, "pub const {}: phf::Map<&'static str, IntelPerformanceCounterDescription> = ", variable).unwrap();
    builder.build(file).unwrap();
    write!(file, ";\n").unwrap();
}

fn make_file_name<'a>(path: &'a Path) -> (String, String) {
    let stem = path.file_stem().unwrap().to_str().unwrap();

    // File name without _core*.json
    println!("{:?}", path);
    let mut core_start = stem.find("_core");
    if core_start.is_none() {
        core_start = stem.find("_uncore");
    }
    assert!(!core_start.is_none());
    let (output_file, _) = stem.split_at(core_start.unwrap());

    // File name without _V*.json at the end:
    let version_start = stem.find("_V").unwrap();
    let (variable, _) = stem.split_at(version_start);
    let uppercase = variable.to_ascii_uppercase();
    let variable_clean = uppercase.replace("-", "_");
    let variable_upper = variable_clean.as_str();

    (output_file.to_string(), variable_upper.to_string())
}

pub fn get_file_suffix(file_name: String) -> &'static str {
    if file_name.contains("_core_") {
        "core"
    }
    else if file_name.contains("_uncore_") {
        "uncore"
    }
    else if file_name.contains("_matrix_") {
        "matrix"
    }
    else if file_name.contains("_FP_ARITH_INST_") {
        "fparith"
    }
    else {
        panic!("Unknown suffix {}", file_name);
    }
}

pub fn main() {
    println!("cargo:rerun-if-changed=build.rs");
    println!("cargo:rerun-if-changed=x86data/perfmon_data");

    let mut rdr = csv::Reader::from_file("./x86data/perfmon_data/mapfile.csv").unwrap();
    let mut data_files = HashMap::new();

    // Parse CSV
    for record in rdr.decode() {
        let (family_model, version, file_name, event_type): (String, String, String, String) = record.unwrap();
        // TODO: Parse offcore counter descriptions.
        if !data_files.contains_key(&file_name) {
            let suffix = get_file_suffix(file_name.clone());
            if suffix == "core" || suffix == "uncore" {
                data_files.insert(file_name.clone(), (family_model + "-" + suffix, version, event_type));
            }
        }
    }

    // Build hash-table to select performance counter for each architecture
    let path = Path::new(&env::var("OUT_DIR").unwrap()).join("counters.rs");
    let mut filewriter = BufWriter::new(File::create(&path).unwrap());

    let mut builder = phf_codegen::Map::new();
    for (file, data) in &data_files {
        let (ref family_model, _, _): (String, String, String) = *data;
        let path = Path::new(file.as_str());
        let (_, ref variable_upper) = make_file_name(&path);
        builder.entry(family_model.as_str(), format!("{}", variable_upper.as_str()).as_str());
    }

    write!(&mut filewriter, "pub static {}: phf::Map<&'static str, phf::Map<&'static str, IntelPerformanceCounterDescription>> = ", "COUNTER_MAP").unwrap();
    builder.build(&mut filewriter).unwrap();
    write!(&mut filewriter, ";\n").unwrap();

    // Parse all JSON files and write the hash-tables
    for (file, data) in &data_files {
        let suffix = get_file_suffix(file.clone());
        if suffix == "core" || suffix == "uncore" {
            let (ref family_model, ref version, ref event_type): (String, String, String) = *data;
            println!("Processing {:?} {} {} {}", file, family_model, version, event_type);

            let path = Path::new(file.as_str());
            let (_, ref variable_upper) = make_file_name(&path);
            parse_performance_counters(format!("x86data/perfmon_data{}", file).as_str(),
                                       variable_upper, &mut filewriter);
        }
    }

}
}
<commit_msg>Fix indentation<commit_after>#![cfg_attr(feature = "performance-counter", feature(convert))]

#[cfg(not(feature = "performance-counter"))]
fn main() {}

#[cfg(feature = "performance-counter")]
fn main() {
    performance_counter::main();
}

#[cfg(feature = "performance-counter")]
mod performance_counter {

    extern crate phf_codegen;
    extern crate serde_json;
    extern crate csv;

    use std::ascii::AsciiExt;
    use std::env;
    use std::fs::File;
    use std::io::{BufWriter, BufReader, Write};
    use std::path::Path;
    use std::collections::HashMap;
    use std::mem;

    use self::serde_json::Value;

    include!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/perfcnt/intel/description.rs"));

    /// HACK: We need to convert parsed strings to static because we're reusing
    /// the struct definition which declare strings as static in the generated code.
    fn string_to_static_str<'a>(s: &'a str) -> &'static str {
        unsafe {
            let ret = mem::transmute(&s as &str);
            mem::forget(s);
            ret
        }
    }

    fn parse_bool(input: &str) -> bool {
        match input.trim() {
            "0" => false,
            "1" => true,
            _ => panic!("Unknown boolean value {}", input),
        }
    }

    fn parse_hex_numbers(split_str_parts: Vec<&str>) -> Vec<u64> {
        split_str_parts.iter()
            .map(|x| {
                assert!(x.starts_with("0x"));
                match u64::from_str_radix(&x[2..], 16) {
                    Ok(u) => u,
                    Err(e) => panic!("{}: Can not parse {}", e, x)
                }
            }).collect()
    }

    fn parse_number(value_str: &str) -> u64 {
        if value_str.len() > 2 && value_str[..2].starts_with("0x") {
            match u64::from_str_radix(&value_str[2..], 16) {
                Ok(u) => u,
                Err(e) => panic!("{}: Can not parse {}", e, value_str)
            }
        }
        else {
            match u64::from_str_radix(&value_str, 10) {
                Ok(u) => u,
                Err(e) => panic!("{}: Can not parse {}", e, value_str)
            }
        }
    }

    fn parse_counter_values(value_str: &str) -> u64 {
        value_str.split(",").map(|x| x.trim())
            .filter(|x| x.len() > 0)
            .map(|x| {
                match u64::from_str_radix(&x, 10) {
                    Ok(u) => u,
                    Err(e) => panic!("{}: Can not parse {} in {}", e, x, value_str)
                }
            }).fold(0, |acc, c| { assert!(c < 8); acc | 1 << c })
    }

    fn parse_null_string(value_str: &str) -> Option<&str> {
        if value_str != "null" {
            Some(value_str)
        }
        else {
            None
        }
    }

    fn parse_counters(value_str: &str) -> Counter {
        if value_str.to_lowercase().starts_with("fixed counter") {
            let mask: u64 = parse_counter_values(&value_str["fixed counter".len()..]);
            Counter::Fixed(mask as u8)
        }
        else if value_str.to_lowercase().starts_with("fixed") {
            let mask: u64 = parse_counter_values(&value_str["fixed".len()..]);
            Counter::Fixed(mask as u8)
        }
        else {
            let mask: u64 = parse_counter_values(value_str);
            Counter::Programmable(mask as u8)
        }
    }

    fn parse_pebs(value_str: &str) -> PebsType {
        match value_str.trim() {
            "0" => PebsType::Regular,
            "1" => PebsType::PebsOrRegular,
            "2" => PebsType::PebsOnly,
            _ => panic!("Unknown PEBS type: {}", value_str),
        }
    }

    fn parse_performance_counters(input: &str, variable: &str, file: &mut BufWriter<File>) {
        let mut builder = phf_codegen::Map::new();
        let f = File::open(input).unwrap();
        let reader = BufReader::new(f);
        let data: Value = serde_json::from_reader(reader).unwrap();
        let mut all_events = HashMap::new();

        if data.is_array() {
            let entries = data.as_array().unwrap();
            for entry in entries.iter() {

                if !entry.is_object() {
                    panic!("Expected JSON object.");
                }
                let pcn = entry.as_object().unwrap();

                let mut event_code = Tuple::One(0);
                let mut umask = Tuple::One(0);
                let mut event_name = "";
                let mut brief_description = "";
                let mut public_description = None;
                let mut counter = Counter::Fixed(0);
                let mut counter_ht_off = Counter::Fixed(0);
                let mut pebs_counters = None;
                let mut sample_after_value = 0;
                let mut msr_index = MSRIndex::None;
                let mut msr_value = 0;
                let mut taken_alone = false;
                let mut counter_mask = 0;
                let mut invert = false;
                let mut any_thread = false;
                let mut edge_detect = false;
                let mut pebs = PebsType::Regular;
                let mut precise_store = false;
                let mut data_la = false;
                let mut l1_hit_indication = false;
                let mut errata = None;
                let mut offcore = false;
                let mut unit = None;
                let mut filter = None;
                let mut extsel = false;

                let mut do_insert: bool = false;

                for (key, value) in pcn.iter() {
                    if !value.is_string() {
                        panic!("Not a string");
                    }

                    println!("key = {} value = {}", key, value.as_string().unwrap());
                    let value_string = value.as_string().unwrap();
                    let value_str = string_to_static_str(value_string).trim();
                    let split_str_parts: Vec<&str> = value_string.split(",").map(|x| x.trim()).collect();

                    match key.as_str() {
                        "EventName" => {
                            if !all_events.contains_key(value_str.clone()) {
                                all_events.insert(value_str, 0);
                                assert!(all_events.contains_key(value_str));
                                do_insert = true;
                            }
                            else {
                                do_insert = false;
                                println!("WARN: Key {} already exists.", value_str);
                            }
                            event_name = value_str;
                        }
                        "EventCode" => {
                            let split_parts: Vec<u64> = parse_hex_numbers(split_str_parts);
                            match split_parts.len() {
                                1 => event_code = Tuple::One(split_parts[0] as u8),
                                2 => event_code = Tuple::Two(split_parts[0] as u8, split_parts[1] as u8),
                                _ => panic!("More than two event codes?")
                            }
                        },
                        "UMask" => {
                            let split_parts: Vec<u64> = parse_hex_numbers(split_str_parts);
                            match split_parts.len() {
                                1 => umask = Tuple::One(split_parts[0] as u8),
                                2 => umask = Tuple::Two(split_parts[0] as u8, split_parts[1] as u8),
                                _ => panic!("More than two event codes?")
                            }
                        },
                        "BriefDescription" => brief_description = value_str,
                        "PublicDescription" => {
                            if brief_description != value_str && value_str != "tbd" {
                                public_description = Some(value_str);
                            }
                            else {
                                public_description = None;
                            }
                        },
                        "Counter" => counter = parse_counters(value_str),
                        "CounterHTOff" => counter_ht_off = parse_counters(value_str),
                        "PEBScounters" => pebs_counters = Some(parse_counters(value_str)),
                        "SampleAfterValue" => sample_after_value = parse_number(value_str),
                        "MSRIndex" => {
                            let split_parts: Vec<u64> = value_str
                                .split(",")
                                .map(|x| x.trim())
                                .map(|x| parse_number(x))
                                .collect();

                                msr_index = match split_parts.len() {
                                    1 => {
                                        if split_parts[0] != 0 {
                                            MSRIndex::One(split_parts[0] as u8)
                                        }
                                        else {
                                            MSRIndex::None
                                        }
                                    },
                                    2 => MSRIndex::Two(split_parts[0] as u8, split_parts[1] as u8),
                                    _ => panic!("More than two MSR indexes?")
                                }
                        },
                        "MSRValue" => msr_value = parse_number(value_str),
                        "TakenAlone" => taken_alone = parse_bool(value_str),
                        "CounterMask" => counter_mask = parse_number(value_str) as u8,
                        "Invert" => invert = parse_bool(value_str),
                        "AnyThread" => any_thread = parse_bool(value_str),
                        "EdgeDetect" => edge_detect = parse_bool(value_str),
                        "PEBS" => pebs = parse_pebs(value_str),
                        "PRECISE_STORE" => precise_store = parse_bool(value_str),
                        "Data_LA" => data_la = parse_bool(value_str),
                        "L1_Hit_Indication" => l1_hit_indication = parse_bool(value_str),
                        "Errata" => errata = parse_null_string(value_str),
                        "Offcore" => offcore = parse_bool(value_str),
                        "Unit" => unit = parse_null_string(value_str),
                        "Filter" => filter = parse_null_string(value_str),
                        "ExtSel" => extsel = parse_bool(value_str),
                        "ELLC" => {/* Ignored due to missing documentation. */ },
                        _ => panic!("Unknown member: {} in file {}", key, input),
                    };
                }

                let ipcd = IntelPerformanceCounterDescription::new(
                    event_code,
                    umask,
                    event_name,
                    brief_description,
                    public_description,
                    counter,
                    counter_ht_off,
                    pebs_counters,
                    sample_after_value,
                    msr_index,
                    msr_value,
                    taken_alone,
                    counter_mask,
                    invert,
                    any_thread,
                    edge_detect,
                    pebs,
                    precise_store,
                    data_la,
                    l1_hit_indication,
                    errata,
                    offcore,
                    unit,
                    filter,
                    extsel
                );

                //println!("{:?}", ipcd.event_name);
                if do_insert == true {
                    builder.entry(ipcd.event_name, format!("{:?}", ipcd).as_str());
                }
            }
        }
        else {
            panic!("JSON data is not an array.");
        }

        write!(file, "pub const {}: phf::Map<&'static str, IntelPerformanceCounterDescription> = ", variable).unwrap();
        builder.build(file).unwrap();
        write!(file, ";\n").unwrap();
    }

    fn make_file_name<'a>(path: &'a Path) -> (String, String) {
        let stem = path.file_stem().unwrap().to_str().unwrap();

        // File name without _core*.json
        println!("{:?}", path);
        let mut core_start = stem.find("_core");
        if core_start.is_none() {
            core_start = stem.find("_uncore");
        }
        assert!(!core_start.is_none());
        let (output_file, _) = stem.split_at(core_start.unwrap());

        // File name without _V*.json at the end:
        let version_start = stem.find("_V").unwrap();
        let (variable, _) = stem.split_at(version_start);
        let uppercase = variable.to_ascii_uppercase();
        let variable_clean = uppercase.replace("-", "_");
        let variable_upper = variable_clean.as_str();

        (output_file.to_string(), variable_upper.to_string())
    }

    pub fn get_file_suffix(file_name: String) -> &'static str {
        if file_name.contains("_core_") {
            "core"
        }
        else if file_name.contains("_uncore_") {
            "uncore"
        }
        else if file_name.contains("_matrix_") {
            "matrix"
        }
        else if file_name.contains("_FP_ARITH_INST_") {
            "fparith"
        }
        else {
            panic!("Unknown suffix {}", file_name);
        }
    }

    pub fn main() {
        println!("cargo:rerun-if-changed=build.rs");
        println!("cargo:rerun-if-changed=x86data/perfmon_data");

        let mut rdr = csv::Reader::from_file("./x86data/perfmon_data/mapfile.csv").unwrap();
        let mut data_files = HashMap::new();

        // Parse CSV
        for record in rdr.decode() {
            let (family_model, version, file_name, event_type): (String, String, String, String) = record.unwrap();
            // TODO: Parse offcore counter descriptions.
            if !data_files.contains_key(&file_name) {
                let suffix = get_file_suffix(file_name.clone());
                if suffix == "core" || suffix == "uncore" {
                    data_files.insert(file_name.clone(), (family_model + "-" + suffix, version, event_type));
                }
            }
        }

        // Build hash-table to select performance counter for each architecture
        let path = Path::new(&env::var("OUT_DIR").unwrap()).join("counters.rs");
        let mut filewriter = BufWriter::new(File::create(&path).unwrap());

        let mut builder = phf_codegen::Map::new();
        for (file, data) in &data_files {
            let (ref family_model, _, _): (String, String, String) = *data;
            let path = Path::new(file.as_str());
            let (_, ref variable_upper) = make_file_name(&path);
            builder.entry(family_model.as_str(), format!("{}", variable_upper.as_str()).as_str());
        }

        write!(&mut filewriter, "pub static {}: phf::Map<&'static str, phf::Map<&'static str, IntelPerformanceCounterDescription>> = ", "COUNTER_MAP").unwrap();
        builder.build(&mut filewriter).unwrap();
        write!(&mut filewriter, ";\n").unwrap();

        // Parse all JSON files and write the hash-tables
        for (file, data) in &data_files {
            let suffix = get_file_suffix(file.clone());
            if suffix == "core" || suffix == "uncore" {
                let (ref family_model, ref version, ref event_type): (String, String, String) = *data;
                println!("Processing {:?} {} {} {}", file, family_model, version, event_type);

                let path = Path::new(file.as_str());
                let (_, ref variable_upper) = make_file_name(&path);
                parse_performance_counters(format!("x86data/perfmon_data{}", file).as_str(),
                                           variable_upper, &mut filewriter);
            }
        }

    }
}
<|endoftext|>


<commit_before>// build.rs

extern crate cmake;
#[cfg(unix)]
extern crate pkg_config;
#[cfg(unix)]
#[cfg(feature = "decode_test")]
extern crate bindgen;
#[cfg(target_arch = "x86_64")]
extern crate nasm_rs;

use std::env;
use std::fs;
use std::fs::File;
use std::io::Write;
use std::path::Path;

fn main() {
    if cfg!(target_arch = "x86_64") {
        let out_dir = env::var("OUT_DIR").unwrap();
        {
            let dest_path = Path::new(&out_dir).join("config.asm");
            let mut config_file = File::create(dest_path).unwrap();
            config_file.write(b"	%define ARCH_X86_32 0\n").unwrap();
            config_file.write(b" %define ARCH_X86_64 1\n").unwrap();
            config_file.write(b"	%define PIC 1\n").unwrap();
            config_file.write(b" %define STACK_ALIGNMENT 32\n").unwrap();
        }
        let mut config_include_arg = String::from("-I");
        config_include_arg.push_str(&out_dir);
        config_include_arg.push('/');
        nasm_rs::compile_library_args("rav1easm", &["src/x86/mc.asm"], &[&config_include_arg, "-Isrc/"]);
    }

    if cfg!(windows) && cfg!(feature = "decode_test") {
        panic!("Unsupported feature on this platform!");
    }

    let cargo_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let build_path = Path::new(&cargo_dir).join("aom_build/aom");
    let debug = if let Some(v) = env::var("PROFILE").ok() {
        match v.as_str() {
            "bench" | "release" => false,
            _ => true,
        }
    } else {
        false
    };

    let dst = cmake::Config::new(build_path)
        .define("CONFIG_DEBUG", (debug as u8).to_string())
        .define("CONFIG_ANALYZER", "0")
        .define("ENABLE_DOCS", "0")
        .define("ENABLE_NASM", "1")
        .define("ENABLE_TESTS", "0")
        .no_build_target(cfg!(windows))
        .build();

    // Dirty hack to force a rebuild whenever the defaults are changed upstream
    let _ = fs::remove_file(dst.join("build/CMakeCache.txt"));

    #[cfg(windows)] {
        println!("cargo:rustc-link-search=native={}", dst.join("build").to_str().unwrap());
        println!("cargo:rustc-link-search=native={}", dst.join("build/Debug").to_str().unwrap());
        println!("cargo:rustc-link-search=native={}", dst.join("build/Release").to_str().unwrap());
        println!("cargo:rustc-link-lib=static=aom");
    }

    #[cfg(unix)] {
        env::set_var("PKG_CONFIG_PATH", dst.join("lib/pkgconfig"));
        let _libs = pkg_config::Config::new().statik(true).probe("aom").unwrap();

        #[cfg(feature = "decode_test")] {
            use std::io::Write;

            let out_dir = env::var("OUT_DIR").unwrap();

            let headers = _libs.include_paths.clone();

            let mut builder = bindgen::builder()
                .blacklist_type("max_align_t")
                .rustfmt_bindings(false)
                .header("data/aom.h");

            for header in headers {
                builder = builder.clang_arg("-I").clang_arg(header.to_str().unwrap());
            }

            // Manually fix the comment so rustdoc won't try to pick them
            let s = builder
                .generate()
                .unwrap()
                .to_string()
                .replace("/**", "/*")
                .replace("/*!", "/*");

            let dest_path = Path::new(&out_dir).join("aom.rs");

            let mut file = fs::File::create(dest_path).unwrap();

            let _ = file.write(s.as_bytes());
        }
    }

    fn rerun_dir<P: AsRef<Path>>(dir: P) {
        for entry in fs::read_dir(dir).unwrap() {
            let entry = entry.unwrap();
            let path = entry.path();
            println!("cargo:rerun-if-changed={}", path.to_string_lossy());

            if path.is_dir() {
                rerun_dir(path);
            }
        }
    }

    rerun_dir("aom_build");
}
<commit_msg>Unbreak non-x86_64<commit_after>// build.rs

extern crate cmake;
#[cfg(unix)]
extern crate pkg_config;
#[cfg(unix)]
#[cfg(feature = "decode_test")]
extern crate bindgen;
#[cfg(target_arch = "x86_64")]
extern crate nasm_rs;

use std::env;
use std::fs;
use std::path::Path;

fn main() {
    #[cfg(target_arch = "x86_64")] {
        use std::fs::File;
        use std::io::Write;
        let out_dir = env::var("OUT_DIR").unwrap();
        {
            let dest_path = Path::new(&out_dir).join("config.asm");
            let mut config_file = File::create(dest_path).unwrap();
            config_file.write(b"	%define ARCH_X86_32 0\n").unwrap();
            config_file.write(b" %define ARCH_X86_64 1\n").unwrap();
            config_file.write(b"	%define PIC 1\n").unwrap();
            config_file.write(b" %define STACK_ALIGNMENT 32\n").unwrap();
        }
        let mut config_include_arg = String::from("-I");
        config_include_arg.push_str(&out_dir);
        config_include_arg.push('/');
        nasm_rs::compile_library_args("rav1easm", &["src/x86/mc.asm"], &[&config_include_arg, "-Isrc/"]);
    }

    if cfg!(windows) && cfg!(feature = "decode_test") {
        panic!("Unsupported feature on this platform!");
    }

    let cargo_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let build_path = Path::new(&cargo_dir).join("aom_build/aom");
    let debug = if let Some(v) = env::var("PROFILE").ok() {
        match v.as_str() {
            "bench" | "release" => false,
            _ => true,
        }
    } else {
        false
    };

    let dst = cmake::Config::new(build_path)
        .define("CONFIG_DEBUG", (debug as u8).to_string())
        .define("CONFIG_ANALYZER", "0")
        .define("ENABLE_DOCS", "0")
        .define("ENABLE_NASM", "1")
        .define("ENABLE_TESTS", "0")
        .no_build_target(cfg!(windows))
        .build();

    // Dirty hack to force a rebuild whenever the defaults are changed upstream
    let _ = fs::remove_file(dst.join("build/CMakeCache.txt"));

    #[cfg(windows)] {
        println!("cargo:rustc-link-search=native={}", dst.join("build").to_str().unwrap());
        println!("cargo:rustc-link-search=native={}", dst.join("build/Debug").to_str().unwrap());
        println!("cargo:rustc-link-search=native={}", dst.join("build/Release").to_str().unwrap());
        println!("cargo:rustc-link-lib=static=aom");
    }

    #[cfg(unix)] {
        env::set_var("PKG_CONFIG_PATH", dst.join("lib/pkgconfig"));
        let _libs = pkg_config::Config::new().statik(true).probe("aom").unwrap();

        #[cfg(feature = "decode_test")] {
            use std::io::Write;

            let out_dir = env::var("OUT_DIR").unwrap();

            let headers = _libs.include_paths.clone();

            let mut builder = bindgen::builder()
                .blacklist_type("max_align_t")
                .rustfmt_bindings(false)
                .header("data/aom.h");

            for header in headers {
                builder = builder.clang_arg("-I").clang_arg(header.to_str().unwrap());
            }

            // Manually fix the comment so rustdoc won't try to pick them
            let s = builder
                .generate()
                .unwrap()
                .to_string()
                .replace("/**", "/*")
                .replace("/*!", "/*");

            let dest_path = Path::new(&out_dir).join("aom.rs");

            let mut file = fs::File::create(dest_path).unwrap();

            let _ = file.write(s.as_bytes());
        }
    }

    fn rerun_dir<P: AsRef<Path>>(dir: P) {
        for entry in fs::read_dir(dir).unwrap() {
            let entry = entry.unwrap();
            let path = entry.path();
            println!("cargo:rerun-if-changed={}", path.to_string_lossy());

            if path.is_dir() {
                rerun_dir(path);
            }
        }
    }

    rerun_dir("aom_build");
}
<|endoftext|>