<commit_before>#![feature(convert)]

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 serde_json::Value;

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

/// We need to convert parsed strings to static because we're reusing
/// the struct definition which declare strings (rightfully) 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, "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);
    }
}

fn main() {
    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>Update comment.<commit_after>#![feature(convert)]

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 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, "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);
    }
}

fn main() {
    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>// Copyright 2016 Kyle Mayes
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Finds and links to the required `libclang` libraries.

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(feature="clippy", warn(clippy))]

extern crate glob;

use std::env;
use std::path::{Path};
use std::process::{Command};

use glob::{MatchOptions};

// Environment variables:
//
// * LLVM_CONFIG_PATH - provides a path to an `llvm-config` executable
// * LIBCLANG_PATH - provides a path to a directory containing a `libclang` shared library
// * LIBCLANG_STATIC_PATH - provides a path to a directory containing LLVM and Clang static libraries

/// Returns whether the supplied directory contains the supplied file.
fn contains<D: AsRef<Path>>(directory: D, file: &str) -> bool {
    directory.as_ref().join(file).exists()
}

/// Panics with a user friendly error message.
fn error(file: &str, env: &str) -> ! {
    panic!("could not find {0}, set the {1} environment variable to a path where {0} can be found", file, env);
}

/// Runs a console command, returning the output if the command was successfully executed.
fn run(command: &str, arguments: &[&str]) -> Option<String> {
    Command::new(command).args(arguments).output().map(|o| {
        String::from_utf8_lossy(&o.stdout).into_owned()
    }).ok()
}

/// Runs `llvm-config`, returning the output if the command was successfully executed.
fn run_llvm_config(arguments: &[&str]) -> Option<String> {
    run(&env::var("LLVM_CONFIG_PATH").unwrap_or("llvm-config".into()), arguments)
}

/// Backup search directory globs for FreeBSD and Linux.
const SEARCH_LINUX: &'static [&'static str] = &[
    "/usr/lib*",
    "/usr/lib*/*",
    "/usr/lib*/*/*",
    "/usr/local/lib*",
    "/usr/local/lib*/*",
    "/usr/local/lib*/*/*",
    "/usr/local/llvm*/lib",
];

/// Backup search directory globs for OS X.
const SEARCH_OSX: &'static [&'static str] = &[
    "/usr/local/opt/llvm*/lib",
    "/Library/Developer/CommandLineTools/usr/lib",
    "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib",
    "/usr/local/opt/llvm*/lib/llvm*/lib",
];

/// Backup search directory globs for Windows.
const SEARCH_WINDOWS: &'static [&'static str] = &[
    "C:\\LLVM\\bin",
    "C:\\LLVM\\lib",
    "C:\\Program Files*\\LLVM\\bin",
    "C:\\Program Files*\\LLVM\\lib",
];

/// Searches for a library, returning the directory it can be found in if the search was successful.
fn find(file: &str, env: &str) -> Option<String> {
    // Search the directory provided by the relevant environment variable, if set.
    if let Some(directory) = env::var(env).ok() {
        if contains(&directory, file) {
            return Some(directory);
        }
        // On Windows, libclang.dll is usually put in bin directory while
        // libclang.lib is placed under lib directory. So we try to search
        // both directories here.
        if cfg!(target_os="windows") {
            let dir_path = Path::new(&directory);
            let alternative_dir = if dir_path.ends_with("lib") {
                Some("bin")
            } else if dir_path.ends_with("bin") {
                Some("lib")
            } else {
                None
            };
            if let Some(dir) = alternative_dir {
                let alternative_path = dir_path.parent().unwrap().join(dir);
                if contains(&alternative_path, file) {
                    return Some(alternative_path.into_os_string().into_string().unwrap());
                }
            }
        }
    }

    // Search the `bin` and `lib` subdirectories in the directory returned by
    // `llvm-config --prefix`, if `llvm-config` is available.
    if let Some(output) = run_llvm_config(&["--prefix"]) {
        let directory = output.lines().map(|s| s.to_string()).next().unwrap();
        let bin = format!("{}/bin", directory);
        if contains(&bin, file) {
            return Some(bin);
        }
        let lib = format!("{}/lib", directory);
        if contains(&lib, file) {
            return Some(lib);
        }
    }

    // Search the backup directories.
    let search = if cfg!(any(target_os="freebsd", target_os="linux")) {
        SEARCH_LINUX
    } else if cfg!(target_os="macos") {
        SEARCH_OSX
    } else if cfg!(target_os="windows") {
        SEARCH_WINDOWS
    } else {
        return None;
    };
    for pattern in search {
        let mut options = MatchOptions::new();
        options.case_sensitive = false;
        options.require_literal_separator = true;
        if let Ok(paths) = glob::glob_with(pattern, &options) {
            for path in paths.filter_map(Result::ok).filter(|p| p.is_dir()) {
                if contains(&path, file) {
                    return Some(path.to_string_lossy().into_owned());
                }
            }
        }
    }
    None
}

/// Returns the name of an LLVM or Clang library from a path.
fn get_library_name(path: &Path) -> Option<String> {
    path.file_stem().map(|l| l.to_string_lossy()[3..].into())
}

/// Returns the LLVM libraries required to link to `libclang` statically.
fn get_llvm_libraries() -> Vec<String> {
    run_llvm_config(&["--libs"]).expect(
        "could not execute `llvm-config --libs`, set the LLVM_CONFIG_PATH environment variable to \
         a path to an `llvm-config` executable"
    ).split_whitespace().filter_map(|p| {
        // Depending on the version of `llvm-config` in use, listed libraries may be in one of two
        // forms, a full path to the library or simply prefixed with `-l`.
        if p.starts_with("-l") {
            Some(p[2..].into())
        } else {
            get_library_name(Path::new(p))
        }
    }).collect()
}

/// Clang libraries required to link to `libclang` 3.5 and later statically.
const CLANG_LIBRARIES: &'static [&'static str] = &[
    "clang",
    "clangAST",
    "clangAnalysis",
    "clangBasic",
    "clangDriver",
    "clangEdit",
    "clangFrontend",
    "clangIndex",
    "clangLex",
    "clangParse",
    "clangRewrite",
    "clangSema",
    "clangSerialization",
];

/// Returns the Clang libraries required to link to `libclang` statically.
fn get_clang_libraries(directory: &str) -> Vec<String> {
    let pattern = Path::new(directory).join("libclang*.a").to_string_lossy().to_string();
    if let Ok(libraries) = glob::glob(&pattern) {
        libraries.filter_map(|l| l.ok().and_then(|l| get_library_name(&l))).collect()
    } else {
        CLANG_LIBRARIES.iter().map(|l| l.to_string()).collect()
    }
}

fn main() {
    if cfg!(feature="static") {
        // Find LLVM and Clang static libraries.
        let directory = match find("libclang.a", "LIBCLANG_STATIC_PATH") {
            Some(directory) => directory,
            _ => error("libclang.a", "LIBCLANG_STATIC_PATH"),
        };

        print!("cargo:rustc-flags=");

        // Specify required LLVM and Clang static libraries.
        print!("-L {} ", directory);
        for library in get_llvm_libraries() {
            print!("-l static={} ", library);
        }
        for library in get_clang_libraries(&directory) {
            print!("-l static={} ", library);
        }

        // Specify required system libraries.
        if cfg!(any(target_os="freebsd", target_os="linux")) {
            println!("-l ffi -l ncursesw -l stdc++ -l z");
        } else if cfg!(target_os="macos") {
            println!("-l ffi -l ncurses -l stdc++ -l z");
        } else {
            panic!("unsupported operating system for static linking");
        }
    } else {
        let file = if cfg!(target_os="windows") {
            // The filename of the `libclang` shared library on Windows is `libclang.dll` instead of
            // the expected `clang.dll`.
            "libclang.dll".into()
        } else {
            format!("{}clang{}", env::consts::DLL_PREFIX, env::consts::DLL_SUFFIX)
        };

        // Find the `libclang` shared library.
        let directory = match find(&file, "LIBCLANG_PATH") {
            Some(directory) => directory,
            _ => error(&file, "LIBCLANG_PATH")
        };

        println!("cargo:rustc-link-search={}", directory);
        if cfg!(all(target_os="windows", target_env="msvc")) {
            // Find the `libclang` stub static library required for the MSVC toolchain.
            let directory = match find("libclang.lib", "LIBCLANG_PATH") {
                Some(directory) => directory,
                _ => error("libclang.lib", "LIBCLANG_PATH"),
            };

            println!("cargo:rustc-link-search={}", directory);
            println!("cargo:rustc-link-lib=dylib=libclang");
        } else {
            println!("cargo:rustc-link-lib=dylib=clang");
        }
    }
}
<commit_msg>Refactor build.rs to use PathBuf<commit_after>// Copyright 2016 Kyle Mayes
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Finds and links to the required `libclang` libraries.

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(feature="clippy", warn(clippy))]

extern crate glob;

use std::env;
use std::path::{Path, PathBuf};
use std::process::{Command};

use glob::{MatchOptions};

// Environment variables:
//
// * LLVM_CONFIG_PATH - provides a path to an `llvm-config` executable
// * LIBCLANG_PATH - provides a path to a directory containing a `libclang` shared library
// * LIBCLANG_STATIC_PATH - provides a path to a directory containing LLVM and Clang static libraries

/// Returns whether the supplied directory contains the supplied file.
fn contains<D: AsRef<Path>>(directory: D, file: &str) -> bool {
    directory.as_ref().join(file).exists()
}

/// Panics with a user friendly error message.
fn error(file: &str, env: &str) -> ! {
    panic!("could not find {0}, set the {1} environment variable to a path where {0} can be found", file, env);
}

/// Runs a console command, returning the output if the command was successfully executed.
fn run(command: &str, arguments: &[&str]) -> Option<String> {
    Command::new(command).args(arguments).output().map(|o| {
        String::from_utf8_lossy(&o.stdout).into_owned()
    }).ok()
}

/// Runs `llvm-config`, returning the output if the command was successfully executed.
fn run_llvm_config(arguments: &[&str]) -> Option<String> {
    run(&env::var("LLVM_CONFIG_PATH").unwrap_or("llvm-config".into()), arguments)
}

/// Backup search directory globs for FreeBSD and Linux.
const SEARCH_LINUX: &'static [&'static str] = &[
    "/usr/lib*",
    "/usr/lib*/*",
    "/usr/lib*/*/*",
    "/usr/local/lib*",
    "/usr/local/lib*/*",
    "/usr/local/lib*/*/*",
    "/usr/local/llvm*/lib",
];

/// Backup search directory globs for OS X.
const SEARCH_OSX: &'static [&'static str] = &[
    "/usr/local/opt/llvm*/lib",
    "/Library/Developer/CommandLineTools/usr/lib",
    "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib",
    "/usr/local/opt/llvm*/lib/llvm*/lib",
];

/// Backup search directory globs for Windows.
const SEARCH_WINDOWS: &'static [&'static str] = &[
    "C:\\LLVM\\bin",
    "C:\\LLVM\\lib",
    "C:\\Program Files*\\LLVM\\bin",
    "C:\\Program Files*\\LLVM\\lib",
];

/// Searches for a library, returning the directory it can be found in if the search was successful.
fn find(file: &str, env: &str) -> Option<PathBuf> {
    // Search the directory provided by the relevant environment variable, if set.
    if let Some(directory) = env::var(env).map(|d| Path::new(&d).to_path_buf()).ok() {
        if contains(&directory, file) {
            return Some(directory);
        }

        // On Windows, `libclang.dll` is usually found in the LLVM `bin` directory while
        // `libclang.lib` is usually found in the LLVM `lib` directory. Search the other if one is
        // specified with `LIBCLANG_PATH`.
        if cfg!(target_os="windows") {
            let suffix = if directory.ends_with("lib") {
                Some("bin")
            } else if directory.ends_with("bin") {
                Some("lib")
            } else {
                None
            };
            if let Some(suffix) = suffix {
                let alternative = directory.parent().unwrap().join(suffix);
                if contains(&alternative, file) {
                    return Some(alternative);
                }
            }
        }
    }

    // Search the `bin` and `lib` subdirectories in the directory returned by
    // `llvm-config --prefix`, if `llvm-config` is available.
    if let Some(output) = run_llvm_config(&["--prefix"]) {
        let directory = Path::new(output.lines().next().unwrap()).to_path_buf();
        let bin = directory.join("bin");
        if contains(&bin, file) {
            return Some(bin);
        }
        let lib = directory.join("lib");
        if contains(&lib, file) {
            return Some(lib);
        }
    }

    // Search the backup directories.
    let search = if cfg!(any(target_os="freebsd", target_os="linux")) {
        SEARCH_LINUX
    } else if cfg!(target_os="macos") {
        SEARCH_OSX
    } else if cfg!(target_os="windows") {
        SEARCH_WINDOWS
    } else {
        return None;
    };
    for pattern in search {
        let mut options = MatchOptions::new();
        options.case_sensitive = false;
        options.require_literal_separator = true;
        if let Ok(paths) = glob::glob_with(pattern, &options) {
            for path in paths.filter_map(Result::ok).filter(|p| p.is_dir()) {
                if contains(&path, file) {
                    return Some(path);
                }
            }
        }
    }
    None
}

/// Returns the name of an LLVM or Clang library from a path.
fn get_library_name(path: &Path) -> Option<String> {
    path.file_stem().map(|l| l.to_string_lossy()[3..].into())
}

/// Returns the LLVM libraries required to link to `libclang` statically.
fn get_llvm_libraries() -> Vec<String> {
    run_llvm_config(&["--libs"]).expect(
        "could not execute `llvm-config --libs`, set the LLVM_CONFIG_PATH environment variable to \
         a path to an `llvm-config` executable"
    ).split_whitespace().filter_map(|p| {
        // Depending on the version of `llvm-config` in use, listed libraries may be in one of two
        // forms, a full path to the library or simply prefixed with `-l`.
        if p.starts_with("-l") {
            Some(p[2..].into())
        } else {
            get_library_name(Path::new(p))
        }
    }).collect()
}

/// Clang libraries required to link to `libclang` 3.5 and later statically.
const CLANG_LIBRARIES: &'static [&'static str] = &[
    "clang",
    "clangAST",
    "clangAnalysis",
    "clangBasic",
    "clangDriver",
    "clangEdit",
    "clangFrontend",
    "clangIndex",
    "clangLex",
    "clangParse",
    "clangRewrite",
    "clangSema",
    "clangSerialization",
];

/// Returns the Clang libraries required to link to `libclang` statically.
fn get_clang_libraries<P: AsRef<Path>>(directory: P) -> Vec<String> {
    let pattern = directory.as_ref().join("libclang*.a").to_string_lossy().to_string();
    if let Ok(libraries) = glob::glob(&pattern) {
        libraries.filter_map(|l| l.ok().and_then(|l| get_library_name(&l))).collect()
    } else {
        CLANG_LIBRARIES.iter().map(|l| l.to_string()).collect()
    }
}

fn main() {
    if cfg!(feature="static") {
        // Find LLVM and Clang static libraries.
        let directory = match find("libclang.a", "LIBCLANG_STATIC_PATH") {
            Some(directory) => directory,
            _ => error("libclang.a", "LIBCLANG_STATIC_PATH"),
        };

        print!("cargo:rustc-flags=");

        // Specify required LLVM and Clang static libraries.
        print!("-L {} ", directory.display());
        for library in get_llvm_libraries() {
            print!("-l static={} ", library);
        }
        for library in get_clang_libraries(&directory) {
            print!("-l static={} ", library);
        }

        // Specify required system libraries.
        if cfg!(any(target_os="freebsd", target_os="linux")) {
            println!("-l ffi -l ncursesw -l stdc++ -l z");
        } else if cfg!(target_os="macos") {
            println!("-l ffi -l ncurses -l stdc++ -l z");
        } else {
            panic!("unsupported operating system for static linking");
        }
    } else {
        let file = if cfg!(target_os="windows") {
            // The filename of the `libclang` shared library on Windows is `libclang.dll` instead of
            // the expected `clang.dll`.
            "libclang.dll".into()
        } else {
            format!("{}clang{}", env::consts::DLL_PREFIX, env::consts::DLL_SUFFIX)
        };

        // Find the `libclang` shared library.
        let directory = match find(&file, "LIBCLANG_PATH") {
            Some(directory) => directory,
            _ => error(&file, "LIBCLANG_PATH")
        };

        println!("cargo:rustc-link-search={}", directory.display());
        if cfg!(all(target_os="windows", target_env="msvc")) {
            // Find the `libclang` stub static library required for the MSVC toolchain.
            let directory = match find("libclang.lib", "LIBCLANG_PATH") {
                Some(directory) => directory,
                _ => error("libclang.lib", "LIBCLANG_PATH"),
            };

            println!("cargo:rustc-link-search={}", directory.display());
            println!("cargo:rustc-link-lib=dylib=libclang");
        } else {
            println!("cargo:rustc-link-lib=dylib=clang");
        }
    }
}
<|endoftext|>


<commit_before>// build.rs

use std::process::Command;
use std::env;
use std::path::Path;
#[macro_use]
extern crate error_chain;

#[cfg(windows)]
mod execs {
    pub const NPM: &str = "npm.cmd";
    pub const STYLUS: &str = "stylus.cmd";
}
#[cfg(not(windows))]
mod execs {
    pub const NPM: &str = "npm";
    pub const STYLUS: &str = "stylus";
}

error_chain!{
 foreign_links {
        Io(std::io::Error);
    }
}

fn program_exists(program: &str) -> Result<()> {
    Command::new(program)
        .arg("-v")
        .output()
        .chain_err(|| format!("Please install '{}'!", program))?;
    Ok(())
}

fn npm_package_exists(package: &str) -> Result<()> {
    let status = Command::new(execs::NPM)
        .args(&["list", "-g"])
        .arg(package)
        .output();

    match status {
        Ok(ref out) if out.status.success() => Ok(()),
        _ => {
            bail!("Missing npm package '{0}' \
                  install with: 'npm -g install {0}'",
                  package)
        },
    }
}

pub enum Resource<'a> {
    Program(&'a str),
    Package(&'a str),
}
use Resource::{Program, Package};

impl<'a> Resource<'a> {
    pub fn exists(&self) -> Result<()> {
        match *self {
            Program(name) => program_exists(name),
            Package(name) => npm_package_exists(name),
        }
    }
}

fn run() -> Result<()> {

    if let Ok(_) = env::var("CARGO_FEATURE_REGENERATE_CSS") {
        // Check dependencies
        Program(execs::NPM).exists()?;
        Program("node").exists()?;
        Package("nib").exists()?;
        Package("stylus").exists()?;

        // Compile stylus stylesheet to css
        let manifest_dir = env::var("CARGO_MANIFEST_DIR")
            .chain_err(|| "Please run the script with: 'cargo build'!")?;
        let theme_dir = Path::new(&manifest_dir).join("src/theme/");
        let stylus_dir = theme_dir.join("stylus/book.styl");

        if !Command::new(execs::STYLUS)
                .arg(stylus_dir)
                .arg("--out")
                .arg(theme_dir)
                .arg("--use")
                .arg("nib")
                .status()?
                .success() {
            bail!("Stylus encoutered an error");
        }
    }
    Ok(())
}

quick_main!(run);
<commit_msg>Fix for different naming of nodejs on ubuntu<commit_after>// build.rs

use std::process::Command;
use std::env;
use std::path::Path;
#[macro_use]
extern crate error_chain;

#[cfg(windows)]
mod execs {
    pub const NPM: &'static str = "npm.cmd";
    pub const STYLUS: &'static str = "stylus.cmd";
}
#[cfg(not(windows))]
mod execs {
    pub const NPM: &'static str = "npm";
    pub const STYLUS: &'static str = "stylus";
}

error_chain!{
 foreign_links {
        Io(std::io::Error);
    }
}

fn program_exists(program: &str) -> Result<()> {
    Command::new(program)
        .arg("-v")
        .output()
        .chain_err(|| format!("Please install '{}'!", program))?;
    Ok(())
}

fn npm_package_exists(package: &str) -> Result<()> {
    let status = Command::new(execs::NPM)
        .args(&["list", "-g"])
        .arg(package)
        .output();

    match status {
        Ok(ref out) if out.status.success() => Ok(()),
        _ => {
            bail!("Missing npm package '{0}' \
                  install with: 'npm -g install {0}'",
                  package)
        },
    }
}

pub enum Resource<'a> {
    Program(&'a str),
    Package(&'a str),
}
use Resource::{Program, Package};

impl<'a> Resource<'a> {
    pub fn exists(&self) -> Result<()> {
        match *self {
            Program(name) => program_exists(name),
            Package(name) => npm_package_exists(name),
        }
    }
}

fn run() -> Result<()> {

    if let Ok(_) = env::var("CARGO_FEATURE_REGENERATE_CSS") {
        // Check dependencies
        Program(execs::NPM).exists()?;
        Program("node").exists().or(Program("nodejs").exists())?;
        Package("nib").exists()?;
        Package("stylus").exists()?;

        // Compile stylus stylesheet to css
        let manifest_dir = env::var("CARGO_MANIFEST_DIR")
            .chain_err(|| "Please run the script with: 'cargo build'!")?;
        let theme_dir = Path::new(&manifest_dir).join("src/theme/");
        let stylus_dir = theme_dir.join("stylus/book.styl");

        if !Command::new(execs::STYLUS)
                .arg(stylus_dir)
                .arg("--out")
                .arg(theme_dir)
                .arg("--use")
                .arg("nib")
                .status()?
                .success() {
            bail!("Stylus encoutered an error");
        }
    }
    Ok(())
}

quick_main!(run);
<|endoftext|>


<commit_before>use wrapped2d::b2;
use wrapped2d::user_data::*;
use backend::obj;
use backend::obj::Updateable;
use super::*;
use backend::obj::{Solid, Geometry, Transformable};
use backend::world;
use std::collections::HashMap;
use std::f64::consts;

struct CreatureData;

impl UserDataTypes for CreatureData {
	type BodyData = world::CreatureRefs;
	type JointData = ();
	type FixtureData = world::CreatureRefs;
}

pub struct PhysicsSystem {
	edge: f32,
	world: b2::World<CreatureData>,
	handles: HashMap<world::CreatureRefs, b2::BodyHandle>,
	dropped: Vec<world::CreatureRefs>,
}

impl Updateable for PhysicsSystem {
	fn update(&mut self, dt: f32) {
		let world = &mut self.world;
		world.step(dt, 8, 3);
		const MAX_RADIUS: f32 = 5.0;
		let mut v = Vec::new();
		self.dropped.clear();
		// TODO: is this the best way to iterate?
		for (h, b) in world.bodies() {
			let body = b.borrow();
			let position = (*body).position();
			let key = (*body).user_data().clone();
			if position.y < (self.edge - MAX_RADIUS) {
				v.push(h);
				self.dropped.push(key);
			}
		}
		for h in v {
			world.destroy_body(h);
		}
		for key in &self.dropped {
			self.handles.remove(&key);
		}
	}
}

impl System for PhysicsSystem {
	fn register(&mut self, creature: &world::Creature) {
		let world = &mut self.world;
		let object_id = creature.id();

		let mut joint_body: Option<b2::BodyHandle> = None;
		let mut joint_limb: Option<b2::BodyHandle> = None;

		for (limb_index, limb) in creature.limbs().enumerate() {
			let material = limb.material();
			let mut f_def = b2::FixtureDef::new();
			f_def.density = material.density;
			f_def.restitution = material.restitution;
			f_def.friction = material.friction;

			let transform = limb.transform();
			let mut b_def = b2::BodyDef::new();
			b_def.body_type = b2::BodyType::Dynamic;
			b_def.position = b2::Vec2 {
				x: transform.position.x,
				y: transform.position.y,
			};
			let refs = world::CreatureRefs::with_limb(object_id, limb_index as u8);
			let handle = world.create_body_with(&b_def, refs);

			let mesh = limb.mesh();

			match mesh.shape {
				obj::Shape::Ball { radius } => {
					let mut circle_shape = b2::CircleShape::new();
					circle_shape.set_radius(radius);
					world.body_mut(handle).create_fixture_with(&circle_shape, &mut f_def, refs);
				}
				obj::Shape::Box { width, height } => {
					let mut rect_shape = b2::PolygonShape::new();
					rect_shape.set_as_box(width, height);
					world.body_mut(handle).create_fixture_with(&rect_shape, &mut f_def, refs);
				}
				obj::Shape::Star { radius, n, .. } => {
					let p = &mesh.vertices;
					for i in 0..n {
						let mut quad = b2::PolygonShape::new();
						let i1 = (i * 2 + 1) as usize;
						let i2 = (i * 2) as usize;
						let i3 = ((i * 2 + (n * 2) - 1) % (n * 2)) as usize;
						let (p1, p2, p3) = match mesh.winding {
							obj::Winding::CW => (p[i1], p[i2], p[i3]),
							obj::Winding::CCW => (p[i1], p[i3], p[i2]),
						};
						quad.set(&[b2::Vec2 { x: 0., y: 0. },
						           b2::Vec2 {
							           x: p1.x * radius,
							           y: p1.y * radius,
						           },
						           b2::Vec2 {
							           x: p2.x * radius,
							           y: p2.y * radius,
						           },
						           b2::Vec2 {
							           x: p3.x * radius,
							           y: p3.y * radius,
						           }]);
						let refs = world::CreatureRefs::with_bone(object_id, limb_index as u8, i as u8);
						world.body_mut(handle).create_fixture_with(&quad, &mut f_def, refs);
					}
				}
				obj::Shape::Triangle { radius, .. } => {
					let p = &mesh.vertices;
					let mut quad = b2::PolygonShape::new();
					let p1 = p[0];
					let p2 = p[2]; // not a typo, we want cw, physics wants ccw
					let p3 = p[1];
					quad.set(&[b2::Vec2 {
						           x: p1.x * radius,
						           y: p1.y * radius,
					           },
					           b2::Vec2 {
						           x: p2.x * radius,
						           y: p2.y * radius,
					           },
					           b2::Vec2 {
						           x: p3.x * radius,
						           y: p3.y * radius,
					           }]);
					world.body_mut(handle).create_fixture_with(&quad, &mut f_def, refs);
				}
			};
			if joint_body == None {
				joint_body = Some(handle);
			} else {
				joint_limb = Some(handle);
			}
			if let (Some(b), Some(l)) = (joint_body, joint_limb) {
				let mut joint = b2::RevoluteJointDef::new(b, l);
				joint.local_anchor_b = b2::Vec2 { x: 0., y: 2. };
				world.create_joint_with(&joint, ());
			}
			self.handles.insert(refs, handle);
		}
	}

	fn to_world(&self, world: &mut world::World) {
		for key in &self.dropped {
			world.friends.kill(&key.creature_id);
			// println!("Killed object: {}", key.creature_id);
		}
		for (_, b) in self.world.bodies() {
			let body = b.borrow();
			let position = (*body).position();
			let angle = (*body).angle();
			let key = (*body).user_data();

			if let Some(creature) = world.friends.get_mut(key.creature_id) {
				if let Some(object) = creature.limb_mut(key.limb_index) {
					let scale = object.transform().scale;
					object.transform_to(obj::Transform {
						position: obj::Position {
							x: position.x,
							y: position.y,
						},
						angle: angle,
						scale: scale,
					});
				}
			}
		}
	}
}

impl PhysicsSystem {
	pub fn new() -> Self {
		PhysicsSystem {
			world: Self::new_world(),
			edge: 0.,
			handles: HashMap::new(),
			dropped: Vec::new(),
		}
	}

	pub fn drop_below(&mut self, edge: f32) {
		self.edge = edge;
	}

	fn new_world() -> b2::World<CreatureData> {
		let mut world = b2::World::new(&b2::Vec2 { x: 0.0, y: -9.8 });

		let mut b_def = b2::BodyDef::new();
		b_def.body_type = b2::BodyType::Static;
		b_def.position = b2::Vec2 { x: 0.0, y: -8.0 };

		let mut ground_box = b2::PolygonShape::new();
		{
			ground_box.set_as_box(20.0, 1.0);
			let ground_handle = world.create_body(&b_def);
			let ground = &mut world.body_mut(ground_handle);
			ground.create_fast_fixture(&ground_box, 0.);

			ground_box.set_as_oriented_box(1.0,
			                               5.0,
			                               &b2::Vec2 { x: 21.0, y: 5.0 },
			                               (-consts::FRAC_PI_8) as f32);
			ground.create_fast_fixture(&ground_box, 0.);

			ground_box.set_as_oriented_box(1.0,
			                               5.0,
			                               &b2::Vec2 { x: -21.0, y: 5.0 },
			                               (consts::FRAC_PI_8) as f32);
			ground.create_fast_fixture(&ground_box, 0.);
		}
		world
	}
}
<commit_msg>Removed gravity<commit_after>use wrapped2d::b2;
use wrapped2d::user_data::*;
use backend::obj;
use backend::obj::Updateable;
use super::*;
use backend::obj::{Solid, Geometry, Transformable};
use backend::world;
use std::collections::HashMap;
use std::f64::consts;

struct CreatureData;

impl UserDataTypes for CreatureData {
	type BodyData = world::CreatureRefs;
	type JointData = ();
	type FixtureData = world::CreatureRefs;
}

pub struct PhysicsSystem {
	edge: f32,
	world: b2::World<CreatureData>,
	handles: HashMap<world::CreatureRefs, b2::BodyHandle>,
	dropped: Vec<world::CreatureRefs>,
}

impl Updateable for PhysicsSystem {
	fn update(&mut self, dt: f32) {
		let world = &mut self.world;
		world.step(dt, 8, 3);
		const MAX_RADIUS: f32 = 5.0;
		let mut v = Vec::new();
		self.dropped.clear();
		// TODO: is this the best way to iterate?
		for (h, b) in world.bodies() {
			let body = b.borrow();
			let position = (*body).position();
			let key = (*body).user_data().clone();
			if position.y < (self.edge - MAX_RADIUS) {
				v.push(h);
				self.dropped.push(key);
			}
		}
		for h in v {
			world.destroy_body(h);
		}
		for key in &self.dropped {
			self.handles.remove(&key);
		}
	}
}

impl System for PhysicsSystem {
	fn register(&mut self, creature: &world::Creature) {
		let world = &mut self.world;
		let object_id = creature.id();

		let mut joint_body: Option<b2::BodyHandle> = None;
		let mut joint_limb: Option<b2::BodyHandle> = None;

		for (limb_index, limb) in creature.limbs().enumerate() {
			let material = limb.material();
			let mut f_def = b2::FixtureDef::new();
			f_def.density = material.density;
			f_def.restitution = material.restitution;
			f_def.friction = material.friction;

			let transform = limb.transform();
			let mut b_def = b2::BodyDef::new();
			b_def.body_type = b2::BodyType::Dynamic;
			b_def.position = b2::Vec2 {
				x: transform.position.x,
				y: transform.position.y,
			};
			let refs = world::CreatureRefs::with_limb(object_id, limb_index as u8);
			let handle = world.create_body_with(&b_def, refs);

			let mesh = limb.mesh();

			match mesh.shape {
				obj::Shape::Ball { radius } => {
					let mut circle_shape = b2::CircleShape::new();
					circle_shape.set_radius(radius);
					world.body_mut(handle).create_fixture_with(&circle_shape, &mut f_def, refs);
				}
				obj::Shape::Box { width, height } => {
					let mut rect_shape = b2::PolygonShape::new();
					rect_shape.set_as_box(width, height);
					world.body_mut(handle).create_fixture_with(&rect_shape, &mut f_def, refs);
				}
				obj::Shape::Star { radius, n, .. } => {
					let p = &mesh.vertices;
					for i in 0..n {
						let mut quad = b2::PolygonShape::new();
						let i1 = (i * 2 + 1) as usize;
						let i2 = (i * 2) as usize;
						let i3 = ((i * 2 + (n * 2) - 1) % (n * 2)) as usize;
						let (p1, p2, p3) = match mesh.winding {
							obj::Winding::CW => (p[i1], p[i2], p[i3]),
							obj::Winding::CCW => (p[i1], p[i3], p[i2]),
						};
						quad.set(&[b2::Vec2 { x: 0., y: 0. },
						           b2::Vec2 {
							           x: p1.x * radius,
							           y: p1.y * radius,
						           },
						           b2::Vec2 {
							           x: p2.x * radius,
							           y: p2.y * radius,
						           },
						           b2::Vec2 {
							           x: p3.x * radius,
							           y: p3.y * radius,
						           }]);
						let refs = world::CreatureRefs::with_bone(object_id, limb_index as u8, i as u8);
						world.body_mut(handle).create_fixture_with(&quad, &mut f_def, refs);
					}
				}
				obj::Shape::Triangle { radius, .. } => {
					let p = &mesh.vertices;
					let mut quad = b2::PolygonShape::new();
					let p1 = p[0];
					let p2 = p[2]; // not a typo, we want cw, physics wants ccw
					let p3 = p[1];
					quad.set(&[b2::Vec2 {
						           x: p1.x * radius,
						           y: p1.y * radius,
					           },
					           b2::Vec2 {
						           x: p2.x * radius,
						           y: p2.y * radius,
					           },
					           b2::Vec2 {
						           x: p3.x * radius,
						           y: p3.y * radius,
					           }]);
					world.body_mut(handle).create_fixture_with(&quad, &mut f_def, refs);
				}
			};
			if joint_body == None {
				joint_body = Some(handle);
			} else {
				joint_limb = Some(handle);
			}
			if let (Some(b), Some(l)) = (joint_body, joint_limb) {
				let mut joint = b2::RevoluteJointDef::new(b, l);
				joint.local_anchor_b = b2::Vec2 { x: 0., y: 2. };
				world.create_joint_with(&joint, ());
			}
			self.handles.insert(refs, handle);
		}
	}

	fn to_world(&self, world: &mut world::World) {
		for key in &self.dropped {
			world.friends.kill(&key.creature_id);
			// println!("Killed object: {}", key.creature_id);
		}
		for (_, b) in self.world.bodies() {
			let body = b.borrow();
			let position = (*body).position();
			let angle = (*body).angle();
			let key = (*body).user_data();

			if let Some(creature) = world.friends.get_mut(key.creature_id) {
				if let Some(object) = creature.limb_mut(key.limb_index) {
					let scale = object.transform().scale;
					object.transform_to(obj::Transform {
						position: obj::Position {
							x: position.x,
							y: position.y,
						},
						angle: angle,
						scale: scale,
					});
				}
			}
		}
	}
}

impl PhysicsSystem {
	pub fn new() -> Self {
		PhysicsSystem {
			world: Self::new_world(),
			edge: 0.,
			handles: HashMap::new(),
			dropped: Vec::new(),
		}
	}

	pub fn drop_below(&mut self, edge: f32) {
		self.edge = edge;
	}

	fn new_world() -> b2::World<CreatureData> {
		let mut world = b2::World::new(&b2::Vec2 { x: 0.0, y: 0.0 });

		world
	}
}
<|endoftext|>


<commit_before>extern crate onmf;
use onmf::helpers::{ToImage};
use onmf::testimage_generator;

extern crate nalgebra;
use nalgebra::{DMat};

extern crate rand;
use rand::{StdRng, SeedableRng};

fn main() {
    for (i, factor) in testimage_generator::static_factors::<f64>().enumerate() {
        factor.save_to_png(&format!("factor-{}.png", i)[..]).unwrap();
    }

    for (i, factor) in testimage_generator::horizontal_evolving_factors::<f64>().enumerate() {
        factor.save_to_png(&format!("horizontal-{}.png", i)[..]).unwrap();
    }

    for (i, factor) in testimage_generator::vertical_evolving_factors::<f64>().enumerate() {
        factor.save_to_png(&format!("vertical-{}.png", i)[..]).unwrap();
    }

    // let seed: &[_] = &[1, 2, 3, 4];
    // let mut rng: StdRng = SeedableRng::from_seed(seed);

    // let testimages: Box<Iterator<Item=Dmat<f64>>> =
    //     Testimage::testimages(1, &mut rng);
    // for (step, i, factor) in testimages.enumerate() {
    //     factor.save_luma01_to_png(&format!("test-{}-{}.png", step, i)[..]).unwrap();
    // }
}
<commit_msg>generate_testimages seems to be working<commit_after>extern crate onmf;
use onmf::helpers::{ToImage};
use onmf::testimage_generator;

extern crate nalgebra;
use nalgebra::{DMat};

extern crate rand;
use rand::{StdRng, SeedableRng};

fn main() {
    for (i, factor) in testimage_generator::static_factors::<f64>().enumerate() {
        factor.save_to_png(&format!("factor-{}.png", i)[..]).unwrap();
    }

    for (i, factor) in testimage_generator::horizontal_evolving_factors::<f64>().enumerate() {
        factor.save_to_png(&format!("horizontal-{}.png", i)[..]).unwrap();
    }

    for (i, factor) in testimage_generator::vertical_evolving_factors::<f64>().enumerate() {
        factor.save_to_png(&format!("vertical-{}.png", i)[..]).unwrap();
    }

    let seed: &[_] = &[1, 2, 3, 4];
    let mut rng: StdRng = SeedableRng::from_seed(seed);

    for (step, i, factor) in testimage_generator::ImgGen::<_, DMat<f64>, _, _>::new(1, &mut rng) {
        factor.save_to_png(&format!("test-{}-{}.png", step, i)[..]).unwrap();
    }
}
<|endoftext|>


<commit_before>#[path = "../debug/mod.rs"]
pub mod debug;

use syn::parse::{Parse, Result};

#[macro_export]
macro_rules! errorf {
    ($($tt:tt)*) => {{
        use ::std::io::Write;
        let stderr = ::std::io::stderr();
        write!(stderr.lock(), $($tt)*).unwrap();
    }};
}

#[macro_export]
macro_rules! punctuated {
    ($($e:expr,)+) => {{
        let mut seq = ::syn::punctuated::Punctuated::new();
        $(
            seq.push($e);
        )+
        seq
    }};

    ($($e:expr),+) => {
        punctuated!($($e,)+)
    };
}

#[macro_export]
macro_rules! snapshot {
    ($($args:tt)*) => {
        snapshot_impl!(() $($args)*)
    };
}

#[macro_export]
macro_rules! snapshot_impl {
    (($expr:ident) as $t:ty, @$snapshot:literal) => {
        let $expr = crate::macros::Tokens::parse::<$t>($expr).unwrap();
        let debug = crate::macros::debug::Lite(&$expr);
        insta::assert_debug_snapshot!(debug, @$snapshot);
    };
    (($($expr:tt)*) as $t:ty, @$snapshot:literal) => {{
        let syntax_tree = crate::macros::Tokens::parse::<$t>($($expr)*).unwrap();
        let debug = crate::macros::debug::Lite(&syntax_tree);
        insta::assert_debug_snapshot!(debug, @$snapshot);
        syntax_tree
    }};
    (($($expr:tt)*) , @$snapshot:literal) => {{
        let syntax_tree = $($expr)*;
        let debug = crate::macros::debug::Lite(&syntax_tree);
        insta::assert_debug_snapshot!(debug, @$snapshot);
        syntax_tree
    }};
    (($($expr:tt)*) $next:tt $($rest:tt)*) => {
        snapshot_impl!(($($expr)* $next) $($rest)*)
    };
}

pub trait Tokens {
    fn parse<T: Parse>(self) -> Result<T>;
}

impl<'a> Tokens for &'a str {
    fn parse<T: Parse>(self) -> Result<T> {
        syn::parse_str(self)
    }
}

impl Tokens for proc_macro2::TokenStream {
    fn parse<T: Parse>(self) -> Result<T> {
        syn::parse2(self)
    }
}
<commit_msg>Disable insta snapshot tests on miri<commit_after>#[path = "../debug/mod.rs"]
pub mod debug;

use syn::parse::{Parse, Result};

#[macro_export]
macro_rules! errorf {
    ($($tt:tt)*) => {{
        use ::std::io::Write;
        let stderr = ::std::io::stderr();
        write!(stderr.lock(), $($tt)*).unwrap();
    }};
}

#[macro_export]
macro_rules! punctuated {
    ($($e:expr,)+) => {{
        let mut seq = ::syn::punctuated::Punctuated::new();
        $(
            seq.push($e);
        )+
        seq
    }};

    ($($e:expr),+) => {
        punctuated!($($e,)+)
    };
}

#[macro_export]
macro_rules! snapshot {
    ($($args:tt)*) => {
        snapshot_impl!(() $($args)*)
    };
}

#[macro_export]
macro_rules! snapshot_impl {
    (($expr:ident) as $t:ty, @$snapshot:literal) => {
        let $expr = crate::macros::Tokens::parse::<$t>($expr).unwrap();
        let debug = crate::macros::debug::Lite(&$expr);
        if !cfg!(miri) {
            insta::assert_debug_snapshot!(debug, @$snapshot);
        }
    };
    (($($expr:tt)*) as $t:ty, @$snapshot:literal) => {{
        let syntax_tree = crate::macros::Tokens::parse::<$t>($($expr)*).unwrap();
        let debug = crate::macros::debug::Lite(&syntax_tree);
        if !cfg!(miri) {
            insta::assert_debug_snapshot!(debug, @$snapshot);
        }
        syntax_tree
    }};
    (($($expr:tt)*) , @$snapshot:literal) => {{
        let syntax_tree = $($expr)*;
        let debug = crate::macros::debug::Lite(&syntax_tree);
        if !cfg!(miri) {
            insta::assert_debug_snapshot!(debug, @$snapshot);
        }
        syntax_tree
    }};
    (($($expr:tt)*) $next:tt $($rest:tt)*) => {
        snapshot_impl!(($($expr)* $next) $($rest)*)
    };
}

pub trait Tokens {
    fn parse<T: Parse>(self) -> Result<T>;
}

impl<'a> Tokens for &'a str {
    fn parse<T: Parse>(self) -> Result<T> {
        syn::parse_str(self)
    }
}

impl Tokens for proc_macro2::TokenStream {
    fn parse<T: Parse>(self) -> Result<T> {
        syn::parse2(self)
    }
}
<|endoftext|>


<commit_before>//! Test/examples for the brainfuck macro.

#![feature(phase)]

#[phase(plugin)] extern crate brainfuck_macros;

#[cfg(bf_bf_interpreter)]
extern crate bf_bf_interpreter;

use std::{io, rand};
use std::rand::Rng;
use std::io::{BufReader, MemWriter};

/// Takes a compiled brainfuck program, feeds it `input` one byte at a
/// time, and compares the output against `expected_output`.
fn run(bf: fn(&mut Reader, &mut Writer) -> io::IoResult<Vec<u8>>,
       input: &str,
       expected_output: &str) {
    let mut input = BufReader::new(input.as_bytes());
    let mut out = MemWriter::new();

    assert!(bf(&mut input, &mut out).is_ok());

    assert_eq!(std::str::from_utf8(out.into_inner().as_slice()).expect("non-UTF8 bf output"),
               expected_output)
}

#[test]
fn hello_world() {
    run(brainfuck!{
        ++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>
        ---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
    }, "", "Hello World!\n");
}

#[test]
fn hello_world_foreign_tokens() {
    run(brainfuck!{
        +=
        +
        foo bar baz
        ++++++[
        =>
        ++++[>++>+++>+++>+
        <<=
        <
        $100
        <-
        ]>+>+>-
        >>=
        +[<]
        <-
        ]
        >>
        .>
        ---.+++++++
        ..
        +++.
        >>
        .
        <-.<.+++.
        -=
        -----.--------.
        >>
        +.>++.
    }, "", "Hello World!\n");
}

#[test]
fn hello_world_harder() {
    // "This is a slightly more complex variant that often triggers interpreter bugs "
    // http://esolangs.org/wiki/brainfuck
    run(brainfuck!{
        >++++++++[<+++++++++>-]<.>>+>+>++>[-]+<[>[->+<<++++>]<<]>.+++++++..+++.>
        >+++++++.<<<[[-]<[-]>]<+++++++++++++++.>>.+++.------.--------.>>+.>++++.
    }, "", "Hello World!\n");
}

#[test]
fn cat() {
    let bf = brainfuck!(,+[-.,+]);
    let mut rng = rand::task_rng();

    for _ in range(0u, 100) {
        let len = rng.gen::<uint>() % 200;
        let s = rng.gen_ascii_chars().take(len).collect::<String>();
        run(bf, s.as_slice(), s.as_slice())
    }
}
<commit_msg>Update to 636663172 2014-12-28 16:21:58 +0000.<commit_after>//! Test/examples for the brainfuck macro.

#![feature(phase)]

#[phase(plugin)] extern crate brainfuck_macros;

#[cfg(bf_bf_interpreter)]
extern crate bf_bf_interpreter;

use std::{io, rand};
use std::rand::Rng;
use std::io::{BufReader, MemWriter};

/// Takes a compiled brainfuck program, feeds it `input` one byte at a
/// time, and compares the output against `expected_output`.
fn run(bf: fn(&mut Reader, &mut Writer) -> io::IoResult<Vec<u8>>,
       input: &str,
       expected_output: &str) {
    let mut input = BufReader::new(input.as_bytes());
    let mut out = MemWriter::new();

    assert!(bf(&mut input, &mut out).is_ok());

    assert_eq!(std::str::from_utf8(out.into_inner().as_slice()).ok().expect("non-UTF8 bf output"),
               expected_output)
}

#[test]
fn hello_world() {
    run(brainfuck!{
        ++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>
        ---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
    }, "", "Hello World!\n");
}

#[test]
fn hello_world_foreign_tokens() {
    run(brainfuck!{
        +=
        +
        foo bar baz
        ++++++[
        =>
        ++++[>++>+++>+++>+
        <<=
        <
        $100
        <-
        ]>+>+>-
        >>=
        +[<]
        <-
        ]
        >>
        .>
        ---.+++++++
        ..
        +++.
        >>
        .
        <-.<.+++.
        -=
        -----.--------.
        >>
        +.>++.
    }, "", "Hello World!\n");
}

#[test]
fn hello_world_harder() {
    // "This is a slightly more complex variant that often triggers interpreter bugs "
    // http://esolangs.org/wiki/brainfuck
    run(brainfuck!{
        >++++++++[<+++++++++>-]<.>>+>+>++>[-]+<[>[->+<<++++>]<<]>.+++++++..+++.>
        >+++++++.<<<[[-]<[-]>]<+++++++++++++++.>>.+++.------.--------.>>+.>++++.
    }, "", "Hello World!\n");
}

#[test]
fn cat() {
    let bf = brainfuck!(,+[-.,+]);
    let mut rng = rand::task_rng();

    for _ in range(0u, 100) {
        let len = rng.gen::<uint>() % 200;
        let s = rng.gen_ascii_chars().take(len).collect::<String>();
        run(bf, s.as_slice(), s.as_slice())
    }
}
<|endoftext|>


<commit_before><commit_msg>allow dead code / unused variables<commit_after><|endoftext|>


<commit_before>#[macro_use] extern crate log;
#[macro_use] extern crate version;
extern crate semver;
extern crate clap;

extern crate libimagstore;
extern crate libimagrt;
extern crate libimagref;
extern crate libimagerror;
extern crate libimagentrylist;
extern crate libimaginteraction;

mod ui;
use ui::build_ui;

use std::path::PathBuf;

use libimagref::reference::Ref;
use libimagref::flags::RefFlags;
use libimagerror::trace::trace_error;
use libimagrt::setup::generate_runtime_setup;
use libimagrt::runtime::Runtime;

fn main() {
    let rt = generate_runtime_setup("imag-ref",
                                    &version!()[..],
                                    "Reference files outside of the store",
                                    build_ui);
    rt.cli()
        .subcommand_name()
        .map(|name| {
            debug!("Call: {}", name);
            match name {
                "add"    => add(&rt),
                "remove" => remove(&rt),
                "list"   => list(&rt),
                _        => {
                    debug!("Unknown command"); // More error handling
                },
            };
        });
}

fn add(rt: &Runtime) {
    let cmd  = rt.cli().subcommand_matches("add").unwrap();
    let path = cmd.value_of("path").map(PathBuf::from).unwrap(); // saved by clap

    let flags = RefFlags::default()
        .with_content_hashing(cmd.is_present("track-content"))
        .with_permission_tracking(cmd.is_present("track-permissions"));

    match Ref::create(rt.store(), path, flags) {
        Ok(r) => {
            debug!("Reference created: {:?}", r);
            info!("Ok");
        },
        Err(e) => {
            trace_error(&e);
            warn!("Failed to create reference");
        },
    }
}

fn remove(rt: &Runtime) {
    use libimagref::error::RefErrorKind;
    use libimagerror::into::IntoError;
    use libimaginteraction::ask::ask_bool;

    let cmd  = rt.cli().subcommand_matches("remove").unwrap();
    let hash = cmd.value_of("hash").map(String::from).unwrap(); // saved by clap
    let yes  = cmd.is_present("yes");

    if yes || ask_bool(&format!("Delete Ref with hash '{}'", hash)[..], None) {
        match Ref::delete_by_hash(rt.store(), hash) {
            Err(e) => trace_error(&e),
            Ok(_) => info!("Ok"),
        }
    } else {
        info!("Aborted");
    }

}

fn list(rt: &Runtime) {
    unimplemented!()
}

<commit_msg>Impl list()<commit_after>#[macro_use] extern crate log;
#[macro_use] extern crate version;
extern crate semver;
extern crate clap;

extern crate libimagstore;
extern crate libimagrt;
extern crate libimagref;
extern crate libimagerror;
extern crate libimagentrylist;
extern crate libimaginteraction;

mod ui;
use ui::build_ui;

use std::path::PathBuf;

use libimagref::reference::Ref;
use libimagref::flags::RefFlags;
use libimagerror::trace::trace_error;
use libimagrt::setup::generate_runtime_setup;
use libimagrt::runtime::Runtime;

fn main() {
    let rt = generate_runtime_setup("imag-ref",
                                    &version!()[..],
                                    "Reference files outside of the store",
                                    build_ui);
    rt.cli()
        .subcommand_name()
        .map(|name| {
            debug!("Call: {}", name);
            match name {
                "add"    => add(&rt),
                "remove" => remove(&rt),
                "list"   => list(&rt),
                _        => {
                    debug!("Unknown command"); // More error handling
                },
            };
        });
}

fn add(rt: &Runtime) {
    let cmd  = rt.cli().subcommand_matches("add").unwrap();
    let path = cmd.value_of("path").map(PathBuf::from).unwrap(); // saved by clap

    let flags = RefFlags::default()
        .with_content_hashing(cmd.is_present("track-content"))
        .with_permission_tracking(cmd.is_present("track-permissions"));

    match Ref::create(rt.store(), path, flags) {
        Ok(r) => {
            debug!("Reference created: {:?}", r);
            info!("Ok");
        },
        Err(e) => {
            trace_error(&e);
            warn!("Failed to create reference");
        },
    }
}

fn remove(rt: &Runtime) {
    use libimagref::error::RefErrorKind;
    use libimagerror::into::IntoError;
    use libimaginteraction::ask::ask_bool;

    let cmd  = rt.cli().subcommand_matches("remove").unwrap();
    let hash = cmd.value_of("hash").map(String::from).unwrap(); // saved by clap
    let yes  = cmd.is_present("yes");

    if yes || ask_bool(&format!("Delete Ref with hash '{}'", hash)[..], None) {
        match Ref::delete_by_hash(rt.store(), hash) {
            Err(e) => trace_error(&e),
            Ok(_) => info!("Ok"),
        }
    } else {
        info!("Aborted");
    }

}

fn list(rt: &Runtime) {
    use std::process::exit;
    use std::ops::Deref;

    use libimagentrylist::lister::Lister;
    use libimagentrylist::listers::core::CoreLister;
    use libimagref::lister::RefLister;

    let cmd                      = rt.cli().subcommand_matches("list").unwrap();
    let do_check_dead            = cmd.is_present("check-dead");
    let do_check_changed         = cmd.is_present("check-changed");
    let do_check_changed_content = cmd.is_present("check-changed-content");
    let do_check_changed_permiss = cmd.is_present("check-changed-permissions");

    let iter = match rt.store().retrieve_for_module("ref") {
        Ok(iter) => iter.filter_map(|id| {
            match Ref::get(rt.store(), id) {
                Ok(r) => Some(r),
                Err(e) => {
                    trace_error(&e);
                    None
                },
            }
        }),
        Err(e) => {
            trace_error(&e);
            exit(1);
        }
    };

    RefLister::new()
        .check_dead(do_check_dead)
        .check_changed(do_check_changed)
        .check_changed_content(do_check_changed_content)
        .check_changed_permiss(do_check_changed_permiss)
        .list(iter.map(|e| e.into()));
}

<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;
#[macro_use]
extern crate serde_json;

extern crate difference;
extern crate meta;
extern crate serde;
extern crate term;

use std::fs::File;
use std::io::prelude::*;
use std::io;

use clap::{App, Arg};
use difference::{Changeset, Difference};
use term::Terminal;

use meta::{Task, TaskIndex};

const ABOUT: &str = r#"
Query differences between the rust-rosetta repository and the Rosetta Code wiki.

This script prints out the name of each task, followed by whether it is implemented online,
locally, or both.

If no tasks are specified, determines the status for all tasks."#;

arg_enum!{
    #[derive(Debug)]
    enum Filter {
        All,
        LocalOnly,
        RemoteOnly,
        Unimplemented
    }
}

impl Default for Filter {
    fn default() -> Self {
        Filter::All
    }
}

/// Prints a colored diff of two strings to the terminal.
fn print_diff<T: ?Sized>(t: &mut T, s1: &str, s2: &str) -> io::Result<()>
where
    T: Terminal,
{
    let changeset = Changeset::new(s1, s2, "\n");

    for change in changeset.diffs {
        match change {
            Difference::Same(ref x) => {
                try!(t.reset());
                try!(writeln!(t, " {}", x));
            }
            Difference::Add(ref x) => {
                try!(t.fg(term::color::GREEN));
                for line in x.split('\n') {
                    try!(writeln!(t, "+{}", line));
                }
            }
            Difference::Rem(ref x) => {
                try!(t.fg(term::color::RED));
                for line in x.split('\n') {
                    try!(writeln!(t, "-{}", line));
                }
            }
        }
    }
    try!(t.reset());
    try!(t.flush());
    Ok(())
}

/// Prints a task in a human-readable format.
fn print_task<T: ?Sized>(t: &mut T, task: &Task, diff: bool) -> io::Result<()>
where
    T: Terminal,
{
    try!(t.attr(term::Attr::Bold));
    try!(writeln!(t, "{}", task.title()));
    try!(t.reset());

    try!(write!(t, "Local:"));
    try!(write_status(t, task.local_code().is_some()));

    try!(write!(t, "Remote:"));
    try!(write_status(t, task.remote_code().is_some()));
    try!(writeln!(t, ""));

    if let (Some(ref local_code), Some(ref remote_code)) = (task.local_code(), task.remote_code()) {
        if diff {
            try!(print_diff(t, remote_code, local_code));
        }
    }

    Ok(())
}

/// Writes a boolean as a pretty, human-readable string.
fn write_status<T: ?Sized>(t: &mut T, boolean: bool) -> io::Result<()>
where
    T: Terminal,
{
    try!(t.attr(term::Attr::Bold));

    if boolean {
        try!(t.fg(term::color::GREEN));
        try!(write!(t, " ✔ "))
    } else {
        try!(t.fg(term::color::RED));
        try!(write!(t, " ✘ "));
    }

    try!(t.reset());
    Ok(())
}

fn main() {
    let matches = App::new("coverage")
        .about(ABOUT)
        .version(crate_version!())
        .max_term_width(100)
        .arg(
            Arg::with_name("task")
                .help("The name of a task on the wiki, such as 'K-d tree'")
                .multiple(true),
        )
        .arg(
            Arg::with_name("diff")
                .help("Print diffs of tasks between the local and remote version")
                .long("diff"),
        )
        .arg(
            Arg::with_name("filter")
                .help("Filter tasks printed by the program.")
                .possible_values(&["all", "local", "remote", "unimplemented"])
                .long("filter")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("json-file")
                .help("Dump json to the provided filename")
                .long("json")
                .takes_value(true),
        )
        .get_matches();

    let mut t = term::stdout().unwrap();

    let filter = value_t!(matches.value_of("filter"), Filter)
        .ok()
        .unwrap_or_default();

    let task_index = TaskIndex::create(env!("CARGO_MANIFEST_DIR")).unwrap();

    let tasks = if let Some(tasks) = matches.values_of("task") {
        let task_names = tasks.map(String::from).collect::<Vec<_>>();
        task_index.fetch_tasks(&task_names)
    } else {
        task_index.fetch_all_tasks()
    };

    let tasks = tasks
        .flat_map(|task| {
            let task = task.unwrap();

            match filter {
                Filter::LocalOnly if !task.is_local_only() => return None,
                Filter::RemoteOnly if !task.is_remote_only() => return None,
                Filter::Unimplemented if !task.is_unimplemented() => return None,
                Filter::All | _ => {}
            }

            print_task(&mut *t, &task, matches.is_present("diff")).unwrap();

            if matches.is_present("json-file") {
                let json = json!({
                    "title": task.title(),
                    "url": task.url().to_string(),
                    "local_code": task.local_code(),
                    "remote_code": task.remote_code(),
                });

                Some(json)
            } else {
                None
            }
        })
        .collect::<Vec<_>>();

    if let Some(filename) = matches.value_of("json-file") {
        let mut file = File::create(filename).unwrap();
        file.write_all(serde_json::to_string_pretty(&tasks).unwrap().as_bytes())
            .unwrap();
    }
}
<commit_msg>Revert "clippy & rustfmt"<commit_after>#[macro_use]
extern crate clap;
#[macro_use]
extern crate serde_json;

extern crate difference;
extern crate meta;
extern crate serde;
extern crate term;

use std::fs::File;
use std::io::prelude::*;
use std::io;

use clap::{Arg, App};
use difference::{Changeset, Difference};
use term::Terminal;

use meta::{TaskIndex, Task};

const ABOUT: &'static str = r#"
Query differences between the rust-rosetta repository and the Rosetta Code wiki.

This script prints out the name of each task, followed by whether it is implemented online,
locally, or both.

If no tasks are specified, determines the status for all tasks."#;

arg_enum!{
    #[derive(Debug)]
    enum Filter {
        All,
        LocalOnly,
        RemoteOnly,
        Unimplemented
    }
}

impl Default for Filter {
    fn default() -> Self {
        Filter::All
    }
}

/// Prints a colored diff of two strings to the terminal.
fn print_diff<T: ?Sized>(t: &mut T, s1: &str, s2: &str) -> io::Result<()>
where
    T: Terminal,
{
    let changeset = Changeset::new(&s1, &s2, "\n");

    for change in changeset.diffs {
        match change {
            Difference::Same(ref x) => {
                try!(t.reset());
                try!(writeln!(t, " {}", x));
            }
            Difference::Add(ref x) => {
                try!(t.fg(term::color::GREEN));
                for line in x.split("\n") {
                    try!(writeln!(t, "+{}", line));
                }
            }
            Difference::Rem(ref x) => {
                try!(t.fg(term::color::RED));
                for line in x.split("\n") {
                    try!(writeln!(t, "-{}", line));
                }
            }
        }
    }
    try!(t.reset());
    try!(t.flush());
    Ok(())
}

/// Prints a task in a human-readable format.
fn print_task<T: ?Sized>(t: &mut T, task: &Task, diff: bool) -> io::Result<()>
where
    T: Terminal,
{
    try!(t.attr(term::Attr::Bold));
    try!(writeln!(t, "{}", task.title()));
    try!(t.reset());

    try!(write!(t, "Local:"));
    try!(write_status(t, task.local_code().is_some()));

    try!(write!(t, "Remote:"));
    try!(write_status(t, task.remote_code().is_some()));
    try!(writeln!(t, ""));

    if let (Some(ref local_code), Some(ref remote_code)) = (task.local_code(), task.remote_code()) {
        if diff {
            try!(print_diff(t, remote_code, local_code));
        }
    }

    Ok(())
}

/// Writes a boolean as a pretty, human-readable string.
fn write_status<T: ?Sized>(t: &mut T, boolean: bool) -> io::Result<()>
where
    T: Terminal,
{
    try!(t.attr(term::Attr::Bold));

    if boolean {
        try!(t.fg(term::color::GREEN));
        try!(write!(t, " ✔ "))
    } else {
        try!(t.fg(term::color::RED));
        try!(write!(t, " ✘ "));
    }

    try!(t.reset());
    Ok(())
}

fn main() {
    let matches = App::new("coverage")
        .about(ABOUT)
        .version(crate_version!())
        .max_term_width(100)
        .arg(
            Arg::with_name("task")
                .help("The name of a task on the wiki, such as 'K-d tree'")
                .multiple(true),
        )
        .arg(
            Arg::with_name("diff")
                .help("Print diffs of tasks between the local and remote version")
                .long("diff"),
        )
        .arg(
            Arg::with_name("filter")
                .help("Filter tasks printed by the program.")
                .possible_values(&["all", "local", "remote", "unimplemented"])
                .long("filter")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("json-file")
                .help("Dump json to the provided filename")
                .long("json")
                .takes_value(true),
        )
        .get_matches();

    let mut t = term::stdout().unwrap();

    let filter = value_t!(matches.value_of("filter"), Filter)
        .ok()
        .unwrap_or_default();

    let task_index = TaskIndex::create(env!("CARGO_MANIFEST_DIR")).unwrap();

    let tasks = if let Some(tasks) = matches.values_of("task") {
        let task_names = tasks.map(String::from).collect::<Vec<_>>();
        task_index.fetch_tasks(&task_names)
    } else {
        task_index.fetch_all_tasks()
    };

    let tasks = tasks
        .flat_map(|task| {
            let task = task.unwrap();

            match filter {
                Filter::LocalOnly if !task.is_local_only() => return None,
                Filter::RemoteOnly if !task.is_remote_only() => return None,
                Filter::Unimplemented if !task.is_unimplemented() => return None,
                Filter::All | _ => {}
            }

            print_task(&mut *t, &task, matches.is_present("diff")).unwrap();

            if matches.is_present("json-file") {
                let json = json!({
                    "title": task.title(),
                    "url": task.url().to_string(),
                    "local_code": task.local_code(),
                    "remote_code": task.remote_code(),
                });

                Some(json)
            } else {
                None
            }
        })
        .collect::<Vec<_>>();

    if let Some(filename) = matches.value_of("json-file") {
        let mut file = File::create(filename).unwrap();
        file.write_all(serde_json::to_string_pretty(&tasks).unwrap().as_bytes())
            .unwrap();
    }
}
<|endoftext|>