<commit_before>use std::env;
use std::fs::File;
use std::io::Write;
use std::path::Path;
use std::fmt;
use std::num::Wrapping;

const POLY: u8 = 0x1D;

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

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

struct Tables {
    exp: [u8; 256],
    log: [u8; 256],
}

fn generate_tables(mut file: &File) {
    let mut tabs = Tables {
        exp: [0; 256],
        log: [0; 256],
    };

    let mut tmp = 1;
    for power in 0..255usize {
        tabs.exp[power] = tmp;
        tabs.log[tmp as usize] = power as u8;
        tmp = xtimes(tmp);
    }
    tabs.exp[255] = 1;

    match write!(file, "{}", tabs) {
        Ok(()) => {}
        Err(_) => panic!("Could not format the table. Aborting build."),
    };
}

fn farray(array: [u8; 256], f: &mut fmt::Formatter) -> fmt::Result {
    for (index, value) in array.into_iter().enumerate() {
        try!(write!(f, "{}", value));
        if index != array.len() - 1 {
            try!(write!(f, ","));
        }
    }
    Ok(())
}

impl fmt::Display for Tables {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "Tables {{\n"));
        try!(write!(f, "    exp: ["));
        try!(farray(self.exp, f));
        try!(write!(f, "],\n"));
        try!(write!(f, "    log: ["));
        try!(farray(self.log, f));
        try!(write!(f, "]\n"));
        write!(f, "}};")
    }
}

#[allow(unused_must_use)]
fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();
    let dest = Path::new(&out_dir).join("nothinghardcoded.rs");

    let mut f = File::create(&dest).unwrap();

    write!(
        f,
        "pub struct Tables {{ \
             pub exp: [u8; 256], \
             pub log: [u8; 256] \
         }} \
         \
         pub static TABLES: Tables = "
    );

    generate_tables(&f);
}
<commit_msg>Small Rustfmt formatting fix to build.rs<commit_after>use std::env;
use std::fs::File;
use std::io::Write;
use std::path::Path;
use std::fmt;
use std::num::Wrapping;

const POLY: u8 = 0x1D;

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

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

struct Tables {
    exp: [u8; 256],
    log: [u8; 256],
}

fn generate_tables(mut file: &File) {
    let mut tabs = Tables {
        exp: [0; 256],
        log: [0; 256],
    };

    let mut tmp = 1;
    for power in 0..255usize {
        tabs.exp[power] = tmp;
        tabs.log[tmp as usize] = power as u8;
        tmp = xtimes(tmp);
    }
    tabs.exp[255] = 1;

    match write!(file, "{}", tabs) {
        Ok(()) => {}
        Err(_) => panic!("Could not format the table. Aborting build."),
    };
}

fn farray(array: [u8; 256], f: &mut fmt::Formatter) -> fmt::Result {
    for (index, value) in array.into_iter().enumerate() {
        try!(write!(f, "{}", value));
        if index != array.len() - 1 {
            try!(write!(f, ","));
        }
    }
    Ok(())
}

impl fmt::Display for Tables {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "Tables {{\n"));
        try!(write!(f, "    exp: ["));
        try!(farray(self.exp, f));
        try!(write!(f, "],\n"));
        try!(write!(f, "    log: ["));
        try!(farray(self.log, f));
        try!(write!(f, "]\n"));
        write!(f, "}};")
    }
}

#[allow(unused_must_use)]
fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();
    let dest = Path::new(&out_dir).join("nothinghardcoded.rs");

    let mut f = File::create(&dest).unwrap();

    write!(
        f,
        "pub struct Tables {{ \
         pub exp: [u8; 256], \
         pub log: [u8; 256] \
         }} \
         \
         pub static TABLES: Tables = "
    );

    generate_tables(&f);
}
<|endoftext|>


<commit_before>use std::fs::{File, OpenOptions};
use std::io::{Read, Seek, SeekFrom, Write};

#[cfg(feature = "skeptic")]
mod gen_skeptic {
    extern crate skeptic;

    use std::env;
    use std::fs::File;
    use std::io::prelude::*;
    use std::path::Path;

    /// skeptic templates look for `rust` after the opening code fences so writing
    /// ```f#,rust
    /// ```
    /// gives f# syntax highlight while still running the tests through the template
    const TEMPLATE: &'static str = r##"
```rust,skeptic-template
extern crate env_logger;
extern crate gluon;

use gluon::vm::api::{{Hole, OpaqueValue}};
use gluon::{{new_vm, Compiler, Thread}};

fn main() {{
    let _ = ::env_logger::init();
    let text = r#\"{}\"#;
    let vm = new_vm();
    match Compiler::new().run_expr::<OpaqueValue<&Thread, Hole>>(&vm, \"example\", text) .sync_or_error() {{
        Ok(_value) => (),
        Err(err) => {{
            panic!(\"{{}}\", err);
        }}
    }}
    return;
}}
```

"##;

    fn generate_skeptic_tests(file: &str) -> String {
        // Preprocess the readme to inject the skeptic template needed to to run the examples
        let out_file_name = Path::new(&env::var("OUT_DIR").unwrap()).join(file);
        let mut contents = TEMPLATE.as_bytes().into();
        File::open(file)
            .and_then(|mut raw_file| raw_file.read_to_end(&mut contents))
            .unwrap();
        File::create(&out_file_name)
            .and_then(|mut out_file| out_file.write(&contents))
            .unwrap();
        out_file_name.to_str().expect("UTF-8 string").into()
    }

    pub fn generate() {
        let test_locations: Vec<_> = ["README.md", "TUTORIAL.md"]
            .iter()
            .cloned()
            .map(generate_skeptic_tests)
            .collect();

        let str_vec: Vec<_> = test_locations.iter().map(|s| &s[..]).collect();
        skeptic::generate_doc_tests(&str_vec);
    }
}

#[cfg(not(feature = "skeptic"))]
mod gen_skeptic {
    pub fn generate() {
        // If we dont run skeptic we do not need to rebuild anything unless the script itself is
        // changed
        println!("cargo:rerun-if-changed=build.rs");
    }
}

/// Safety check to make sure that all .rs files in `tests/` will run
fn check_test_declarations_in_cargo_file() {
    use std::collections::HashSet;
    use std::fs::{read_dir, File};
    use std::io::{BufRead, BufReader};
    use std::ffi::OsStr;

    let cargo_file = BufReader::new(File::open("Cargo.toml").unwrap());

    let tests_in_cargo_file: HashSet<_> = cargo_file
        .lines()
        .map(|line| line.unwrap())
        .filter(|line| line.starts_with("name = \""))
        .map(|line| line.split('"').nth(1).unwrap().to_string())
        .collect();

    for entry in read_dir("tests").unwrap() {
        let entry = entry.unwrap();
        let path = entry.path();
        if path.extension() == Some(OsStr::new("rs")) {
            let filename = path.file_stem()
                .expect("file_stem")
                .to_str()
                .expect("utf-8 file_stem");
            if !tests_in_cargo_file.contains(filename) {
                panic!(
                    "Test `{}` must be declared in Cargo.toml, otherwise it does not run",
                    filename
                );
            }
        }
    }
}

fn example_24_up_to_date() {
    let mut readme_file = OpenOptions::new().read(true).write(true).open("README.md").unwrap();
    let mut readme = String::new();
    readme_file.read_to_string(&mut readme).unwrap();

    let offset = readme.find("[24 game]").expect("24 game tag");
    let block_start = readme[offset..].find("```").expect("block start") + offset;
    let inside_block_start = readme[block_start..].find('\n').expect("inner block start") + block_start + 1;
    let block_end = readme[(block_start + 3)..].find("```").expect("block end") + block_start + 3;

    readme.drain(inside_block_start..block_end);

    {
        let mut file = File::open("examples/24.glu").unwrap();
        let mut example = String::new();
        file.read_to_string(&mut example).unwrap();
        readme.insert_str(inside_block_start, &example);
    }
    readme_file.seek(SeekFrom::Start(0)).unwrap();
    readme_file.write_all(readme.as_bytes()).unwrap();

    println!("cargo:rerun-if-changed=examples/24.glu");
}

fn main() {
    gen_skeptic::generate();

    check_test_declarations_in_cargo_file();

    example_24_up_to_date();
}
<commit_msg>chore: Avoid writing to the README when using cross<commit_after>use std::fs::{File, OpenOptions};
use std::io::{Read, Seek, SeekFrom, Write};

#[cfg(feature = "skeptic")]
mod gen_skeptic {
    extern crate skeptic;

    use std::env;
    use std::fs::File;
    use std::io::prelude::*;
    use std::path::Path;

    /// skeptic templates look for `rust` after the opening code fences so writing
    /// ```f#,rust
    /// ```
    /// gives f# syntax highlight while still running the tests through the template
    const TEMPLATE: &'static str = r##"
```rust,skeptic-template
extern crate env_logger;
extern crate gluon;

use gluon::vm::api::{{Hole, OpaqueValue}};
use gluon::{{new_vm, Compiler, Thread}};

fn main() {{
    let _ = ::env_logger::init();
    let text = r#\"{}\"#;
    let vm = new_vm();
    match Compiler::new().run_expr::<OpaqueValue<&Thread, Hole>>(&vm, \"example\", text) .sync_or_error() {{
        Ok(_value) => (),
        Err(err) => {{
            panic!(\"{{}}\", err);
        }}
    }}
    return;
}}
```

"##;

    fn generate_skeptic_tests(file: &str) -> String {
        // Preprocess the readme to inject the skeptic template needed to to run the examples
        let out_file_name = Path::new(&env::var("OUT_DIR").unwrap()).join(file);
        let mut contents = TEMPLATE.as_bytes().into();
        File::open(file)
            .and_then(|mut raw_file| raw_file.read_to_end(&mut contents))
            .unwrap();
        File::create(&out_file_name)
            .and_then(|mut out_file| out_file.write(&contents))
            .unwrap();
        out_file_name.to_str().expect("UTF-8 string").into()
    }

    pub fn generate() {
        let test_locations: Vec<_> = ["README.md", "TUTORIAL.md"]
            .iter()
            .cloned()
            .map(generate_skeptic_tests)
            .collect();

        let str_vec: Vec<_> = test_locations.iter().map(|s| &s[..]).collect();
        skeptic::generate_doc_tests(&str_vec);
    }
}

#[cfg(not(feature = "skeptic"))]
mod gen_skeptic {
    pub fn generate() {
        // If we dont run skeptic we do not need to rebuild anything unless the script itself is
        // changed
        println!("cargo:rerun-if-changed=build.rs");
    }
}

/// Safety check to make sure that all .rs files in `tests/` will run
fn check_test_declarations_in_cargo_file() {
    use std::collections::HashSet;
    use std::fs::{read_dir, File};
    use std::io::{BufRead, BufReader};
    use std::ffi::OsStr;

    let cargo_file = BufReader::new(File::open("Cargo.toml").unwrap());

    let tests_in_cargo_file: HashSet<_> = cargo_file
        .lines()
        .map(|line| line.unwrap())
        .filter(|line| line.starts_with("name = \""))
        .map(|line| line.split('"').nth(1).unwrap().to_string())
        .collect();

    for entry in read_dir("tests").unwrap() {
        let entry = entry.unwrap();
        let path = entry.path();
        if path.extension() == Some(OsStr::new("rs")) {
            let filename = path.file_stem()
                .expect("file_stem")
                .to_str()
                .expect("utf-8 file_stem");
            if !tests_in_cargo_file.contains(filename) {
                panic!(
                    "Test `{}` must be declared in Cargo.toml, otherwise it does not run",
                    filename
                );
            }
        }
    }
}

fn example_24_up_to_date() {
    let mut readme = String::new();
    {
        let mut readme_file = File::open("README.md").unwrap();
        readme_file.read_to_string(&mut readme).unwrap();

        let offset = readme.find("[24 game]").expect("24 game tag");
        let block_start = readme[offset..].find("```").expect("block start") + offset;
        let inside_block_start =
            readme[block_start..].find('\n').expect("inner block start") + block_start + 1;
        let block_end =
            readme[(block_start + 3)..].find("```").expect("block end") + block_start + 3;

        let example_24_in_readme = readme
            .drain(inside_block_start..block_end)
            .collect::<String>();

        {
            let mut file = File::open("examples/24.glu").unwrap();
            let mut example = String::new();
            file.read_to_string(&mut example).unwrap();
            // No need to write anything if it is up to date
            if example == example_24_in_readme {
                return;
            }
            readme.insert_str(inside_block_start, &example);
        }
    }
    let mut readme_file = File::create("README.md").unwrap();
    readme_file.write_all(readme.as_bytes()).unwrap();
}

fn main() {
    gen_skeptic::generate();

    check_test_declarations_in_cargo_file();

    example_24_up_to_date();
    println!("cargo:rerun-if-changed=examples/24.glu");
}
<|endoftext|>


<commit_before>//! The following environment variables affect the build:
//!
//! * `UPDATE_CAPSTONE_BINDINGS`: setting indicates that the pre-generated `capstone.rs` should be
//!   updated with the output bindgen

#[cfg(feature = "use_bindgen")]
extern crate bindgen;
extern crate pkg_config;

#[cfg(feature = "build_src_cmake")]
extern crate cmake;

#[cfg(feature = "use_bindgen")]
use std::fs::copy;
use std::path::PathBuf;
use std::process::Command;
use std::env;

#[cfg(feature = "use_bindgen")]
include!("common.rs");

/// Indicates how capstone library should be linked
enum LinkType {
    Dynamic,
    Static,
}

#[cfg(feature = "build_src_cmake")]
fn cmake() {
    let mut cfg = cmake::Config::new("capstone");
    let dst = cfg.build();
    println!("cargo:rustc-link-search=native={}/lib", dst.display());
}

#[cfg(feature = "use_bindgen")]
/// Search for header in search paths
fn find_capstone_header(header_search_paths: &Vec<PathBuf>, name: &str) -> Option<PathBuf> {
    for search_path in header_search_paths.iter() {
        let potential_file = search_path.join(name);
        if potential_file.is_file() {
            return Some(potential_file);
        }
    }
    None
}

/// Create bindings using bindgen
#[cfg(feature = "use_bindgen")]
fn write_bindgen_bindings(header_search_paths: &Vec<PathBuf>, update_pregenerated_bindings: bool) {
    let mut builder = bindgen::Builder::default()
        .unstable_rust(false)
        .header(
            find_capstone_header(header_search_paths, "capstone.h")
                .expect("Could not find header")
                .to_str()
                .unwrap(),
        )
        .disable_name_namespacing()
        .prepend_enum_name(false)
        .generate_comments(true)
        .constified_enum_module("[^_]+_reg$"); // Some registers have aliases

    // Whitelist cs_.* functions and types
    let pattern = String::from("cs_.*");
    builder = builder
        .whitelisted_function(pattern.clone())
        .whitelisted_type(pattern.clone());

    // Whitelist types with architectures
    for arch in ARCH_INCLUDES {
        let pattern = format!(".*(^|_){}(_|$).*", arch.cs_name);
        builder = builder.whitelisted_type(pattern);
    }

    let bindings = builder.generate().expect("Unable to generate bindings");

    // Write bindings to $OUT_DIR/bindings.rs
    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join(BINDINGS_FILE);
    bindings.write_to_file(out_path.clone()).expect(
        "Unable to write bindings",
    );

    if update_pregenerated_bindings {
        let stored_bindgen_header: PathBuf =
            [
                env::var("CARGO_MANIFEST_DIR").expect("Could not find cargo environment variable"),
                "pre_generated".into(),
                BINDINGS_FILE.into(),
            ].iter()
                .collect();
        copy(out_path, stored_bindgen_header).expect("Unable to update capstone bindings");
    }
}

fn main() {
    let link_type: Option<LinkType>;

    // C header search paths
    let mut header_search_paths: Vec<PathBuf> = Vec::new();

    if cfg!(feature = "use_system_capstone") {
        assert!(
            !cfg!(feature = "build_capstone_cmake"),
            "build_capstone_cmake feature is only valid when using bundled cmake"
        );

        let capstone_lib =
            pkg_config::find_library("capstone").expect("Could not find system capstone");
        header_search_paths.append(&mut capstone_lib.include_paths.clone());
        link_type = Some(LinkType::Dynamic);
    } else {
        if cfg!(feature = "build_capstone_cmake") {
            #[cfg(feature = "build_src_cmake")]
            cmake();
        } else {
            //let target = env::var("TARGET").unwrap();
            //let windows = target.contains("windows");
            // TODO: need to add this argument for windows 64-bit, msvc, dunno, read
            // COMPILE_MSVC.txt file cygwin-mingw64
            let out_dir = env::var("OUT_DIR").unwrap();
            let _ = Command::new("./make.sh")
                .current_dir("capstone")
                .status();
            let capstone = "libcapstone.a";
            let _ = Command::new("cp")
                .current_dir("capstone")
                .arg(&capstone)
                .arg(&out_dir)
                .status();
            println!("cargo:rustc-link-search=native={}", out_dir);
        }
        header_search_paths.push(PathBuf::from("capstone/include"));
        link_type = Some(LinkType::Static);
    }

    match link_type.expect("Must specify link type") {
        LinkType::Dynamic => {
            println!("cargo:rustc-link-lib=dylib=capstone");
        }
        LinkType::Static => {
            println!("cargo:rustc-link-lib=static=capstone");
        }
    }

    // If UPDATE_CAPSTONE_BINDINGS is set, then updated the pre-generated capstone bindings
    let update_pregenerated_bindings = env::var("UPDATE_CAPSTONE_BINDINGS").is_ok();
    if update_pregenerated_bindings {
        assert!(
            cfg!(feature = "use_bindgen"),
            concat!(
                "Setting UPDATE_CAPSTONE_BINDINGS only makes ",
                "sense when enabling feature \"use_bindgen\""
            )
        );
    }

    // Only run bindgen if we are *not* using the bundled capstone bindings
    #[cfg(feature = "use_bindgen")]
    write_bindgen_bindings(&header_search_paths, update_pregenerated_bindings);
}
<commit_msg>Fix cmake feature<commit_after>//! The following environment variables affect the build:
//!
//! * `UPDATE_CAPSTONE_BINDINGS`: setting indicates that the pre-generated `capstone.rs` should be
//!   updated with the output bindgen

#[cfg(feature = "use_bindgen")]
extern crate bindgen;
extern crate pkg_config;

#[cfg(feature = "build_capstone_cmake")]
extern crate cmake;

#[cfg(feature = "use_bindgen")]
use std::fs::copy;
use std::path::PathBuf;
use std::process::Command;
use std::env;

#[cfg(feature = "use_bindgen")]
include!("common.rs");

/// Indicates how capstone library should be linked
enum LinkType {
    Dynamic,
    Static,
}

#[cfg(feature = "build_capstone_cmake")]
fn cmake() {
    let mut cfg = cmake::Config::new("capstone");
    let dst = cfg.build();
    println!("cargo:rustc-link-search=native={}/lib", dst.display());
}

#[cfg(feature = "use_bindgen")]
/// Search for header in search paths
fn find_capstone_header(header_search_paths: &Vec<PathBuf>, name: &str) -> Option<PathBuf> {
    for search_path in header_search_paths.iter() {
        let potential_file = search_path.join(name);
        if potential_file.is_file() {
            return Some(potential_file);
        }
    }
    None
}

/// Create bindings using bindgen
#[cfg(feature = "use_bindgen")]
fn write_bindgen_bindings(header_search_paths: &Vec<PathBuf>, update_pregenerated_bindings: bool) {
    let mut builder = bindgen::Builder::default()
        .unstable_rust(false)
        .header(
            find_capstone_header(header_search_paths, "capstone.h")
                .expect("Could not find header")
                .to_str()
                .unwrap(),
        )
        .disable_name_namespacing()
        .prepend_enum_name(false)
        .generate_comments(true)
        .constified_enum_module("[^_]+_reg$"); // Some registers have aliases

    // Whitelist cs_.* functions and types
    let pattern = String::from("cs_.*");
    builder = builder
        .whitelisted_function(pattern.clone())
        .whitelisted_type(pattern.clone());

    // Whitelist types with architectures
    for arch in ARCH_INCLUDES {
        let pattern = format!(".*(^|_){}(_|$).*", arch.cs_name);
        builder = builder.whitelisted_type(pattern);
    }

    let bindings = builder.generate().expect("Unable to generate bindings");

    // Write bindings to $OUT_DIR/bindings.rs
    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join(BINDINGS_FILE);
    bindings.write_to_file(out_path.clone()).expect(
        "Unable to write bindings",
    );

    if update_pregenerated_bindings {
        let stored_bindgen_header: PathBuf =
            [
                env::var("CARGO_MANIFEST_DIR").expect("Could not find cargo environment variable"),
                "pre_generated".into(),
                BINDINGS_FILE.into(),
            ].iter()
                .collect();
        copy(out_path, stored_bindgen_header).expect("Unable to update capstone bindings");
    }
}

fn main() {
    let link_type: Option<LinkType>;

    // C header search paths
    let mut header_search_paths: Vec<PathBuf> = Vec::new();

    if cfg!(feature = "use_system_capstone") {
        assert!(
            !cfg!(feature = "build_capstone_cmake"),
            "build_capstone_cmake feature is only valid when using bundled cmake"
        );

        let capstone_lib =
            pkg_config::find_library("capstone").expect("Could not find system capstone");
        header_search_paths.append(&mut capstone_lib.include_paths.clone());
        link_type = Some(LinkType::Dynamic);
    } else {
        if cfg!(feature = "build_capstone_cmake") {
            #[cfg(feature = "build_capstone_cmake")]
            cmake();
        } else {
            //let target = env::var("TARGET").unwrap();
            //let windows = target.contains("windows");
            // TODO: need to add this argument for windows 64-bit, msvc, dunno, read
            // COMPILE_MSVC.txt file cygwin-mingw64
            let out_dir = env::var("OUT_DIR").unwrap();
            let _ = Command::new("./make.sh")
                .current_dir("capstone")
                .status();
            let capstone = "libcapstone.a";
            let _ = Command::new("cp")
                .current_dir("capstone")
                .arg(&capstone)
                .arg(&out_dir)
                .status();
            println!("cargo:rustc-link-search=native={}", out_dir);
        }
        header_search_paths.push(PathBuf::from("capstone/include"));
        link_type = Some(LinkType::Static);
    }

    match link_type.expect("Must specify link type") {
        LinkType::Dynamic => {
            println!("cargo:rustc-link-lib=dylib=capstone");
        }
        LinkType::Static => {
            println!("cargo:rustc-link-lib=static=capstone");
        }
    }

    // If UPDATE_CAPSTONE_BINDINGS is set, then updated the pre-generated capstone bindings
    let update_pregenerated_bindings = env::var("UPDATE_CAPSTONE_BINDINGS").is_ok();
    if update_pregenerated_bindings {
        assert!(
            cfg!(feature = "use_bindgen"),
            concat!(
                "Setting UPDATE_CAPSTONE_BINDINGS only makes ",
                "sense when enabling feature \"use_bindgen\""
            )
        );
    }

    // Only run bindgen if we are *not* using the bundled capstone bindings
    #[cfg(feature = "use_bindgen")]
    write_bindgen_bindings(&header_search_paths, update_pregenerated_bindings);
}
<|endoftext|>


<commit_before>extern crate gcc;
//extern crate bindgen;
extern crate regex;

use std::path::*;
use std::env;
use std::process::Command;
use std::fs::*;
use std::io::*;
use regex::Regex;

#[derive(Default)]
struct State {
    project_path: Option<PathBuf>,
    dpdk_path: Option<PathBuf>,
    dpdk_headers: Vec<PathBuf>,
    dpdk_links: Vec<PathBuf>,
    dpdk_config: Option<PathBuf>,
}

fn find_dpdk(state: &mut State) {
    if let Ok(path_string) = env::var("RTE_SDK") {
        state.dpdk_path = Some(PathBuf::from(&path_string));
    } else {
        // Automatic download
        let dir_path = Path::new("3rdparty");
        if !dir_path.exists() {
            create_dir(dir_path).ok();
        }
        assert!(dir_path.exists());
        let git_path = dir_path.join("dpdk");
        if !git_path.exists() {
            Command::new("git")
                .args(&["clone",
                        "-b",
                        "anlab",
                        "https://github.com/ANLAB-KAIST/dpdk",
                        git_path.to_str().unwrap()])
                .output()
                .expect("failed to run git command");
        }
        Command::new("make")
            .args(&["-C", git_path.to_str().unwrap(), "config", "T=anlab_shared"])
            .output()
            .expect("failed to run make command");
        Command::new("make")
            .args(&["-C", git_path.to_str().unwrap(), "-j", "T=anlab_shared"])
            .output()
            .expect("failed to run make command");

        state.dpdk_path = Some(git_path.join("build"));
    }
    assert!(state.dpdk_path
                .clone()
                .unwrap()
                .exists());
    let config_header = state.dpdk_path
        .clone()
        .unwrap()
        .join("include")
        .join("rte_config.h");
    assert!(config_header.exists());
    state.dpdk_config = Some(config_header);
}

fn find_link_libs(state: &mut State) {
    let dpdk_path = state.dpdk_path.clone().unwrap();
    let lib_dir = dpdk_path.join("lib");

    let mut libs = vec![];
    for entry in lib_dir.read_dir().expect("read_dir failed") {
        if let Ok(entry) = entry {
            let path = entry.path();
            if !path.is_file() {
                continue;
            }

            if let Some(ext) = path.extension() {
                if ext != "a" && ext != "so" {
                    continue;
                }
            } else {
                continue;
            }

            if let Some(file_stem) = path.file_stem() {
                let string = file_stem.to_str().unwrap();
                if !string.starts_with("librte_") {
                    continue;
                }
                libs.push(path.clone());
            } else {
                continue;
            }
        } else {
            continue;
        }
    }
    libs.sort();
    state.dpdk_links = libs;
}

fn check_direct_include(path: &Path) -> bool {
    if !path.is_file() {
        return false;
    }
    let file = File::open(path).unwrap();
    let reader = BufReader::new(&file);
    for (_, line) in reader.lines().enumerate() {
        let line_str = line.ok()
            .unwrap()
            .trim()
            .to_lowercase();
        if line_str.starts_with("#error") {
            if line_str.find("do not").is_some() && line_str.find("include").is_some() &&
               line_str.find("directly").is_some() {
                return false;
            }
        }
    }
    return true;
}

fn make_all_in_one_header(state: &mut State) {
    let include_dir = state.dpdk_path
        .clone()
        .unwrap()
        .join("include");
    let dpdk_config = state.dpdk_config.clone().unwrap();
    let mut headers = vec![];
    for entry in include_dir.read_dir().expect("read_dir failed") {
        if let Ok(entry) = entry {

            let path = entry.path();

            if !path.is_file() {
                continue;
            }

            if let Some(ext) = path.extension() {
                if ext != "h" {
                    continue;
                }
            } else {
                continue;
            }
            if path == dpdk_config {
                continue;
            }
            if !check_direct_include(&path) {
                continue;
            }
            headers.push(path);
        } else {
            continue;
        }
    }
    headers.sort();
    state.dpdk_headers = headers;
    let template_path = state.project_path
        .clone()
        .unwrap()
        .join("dpdk.h.template");
    let target_path = state.project_path
        .clone()
        .unwrap()
        .join("dpdk.h");
    let mut template = File::open(template_path).unwrap();
    let mut target = File::create(target_path).unwrap();

    let mut template_string = String::new();
    template.read_to_string(&mut template_string).ok();

    let mut headers_string = String::new();
    for header in &state.dpdk_headers {
        headers_string += &format!("#include <{}>\n",
                                   header.clone()
                                       .file_name()
                                       .unwrap()
                                       .to_str()
                                       .unwrap());
    }
    let formatted_string = template_string.replace("%header_list%", &headers_string);

    target.write_fmt(format_args!("{}", formatted_string)).ok();
}

fn generate_rust_def(state: &mut State) {
    let dpdk_include_path = state.dpdk_path
        .clone()
        .unwrap()
        .join("include");
    let c_include_path = state.project_path
        .clone()
        .unwrap()
        .join("c_header");
    let dpdk_config_path = state.dpdk_config.clone().unwrap();

    let header_path = state.project_path
        .clone()
        .unwrap()
        .join("dpdk.h");
    let target_path = state.project_path
        .clone()
        .unwrap()
        .join("src")
        .join("dpdk.rs");
    /*
    bindgen::builder()
        .header(header_path.to_str().unwrap())
        .no_unstable_rust()
        .clang_arg(format!("-I{}", dpdk_include_path.to_str().unwrap()))
        .clang_arg(format!("-I{}", c_include_path.to_str().unwrap()))
        .clang_arg("-imacros")
        .clang_arg(dpdk_config_path.to_str().unwrap())
        .clang_arg("-march=native")
        .generate()
        .unwrap()
        .write_to_file(target_path)
        .ok();
        */

    //XXX replace with native bindgen package later
    Command::new("bindgen")
        .args(&[header_path.to_str().unwrap(),
                "--output",
                target_path.to_str().unwrap(),
                "--no-unstable-rust",
                "--",
                &format!("-I{}", dpdk_include_path.to_str().unwrap()),
                &format!("-I{}", c_include_path.to_str().unwrap()),
                "-imacros",
                dpdk_config_path.to_str().unwrap(),
                "-march=native"])
        .output()
        .expect("failed to run bindgen command");
}

fn generate_lib_rs(state: &mut State) {
    let template_path = state.project_path
        .clone()
        .unwrap()
        .join("lib.rs.template");
    let target_path = state.project_path
        .clone()
        .unwrap()
        .join("src")
        .join("lib.rs");

    let format = Regex::new(r"rte_pmd_(\w+)").unwrap();

    let mut pmds = vec![];
    for link in &state.dpdk_links {
        let link_name = link.file_stem()
            .unwrap()
            .to_str()
            .unwrap();
        if let Some(capture) = format.captures(link_name) {
            pmds.push(String::from(&capture[1]));
        }
    }

    let mut pmds_string = String::new();
    for pmd in pmds {
        pmds_string += &format!("\n\"{}\",", pmd);
    }

    let mut template = File::open(template_path).unwrap();
    let mut template_string = String::new();
    template.read_to_string(&mut template_string).ok();

    let formatted_string = template_string.replace("%pmd_list%", &pmds_string);
    let mut target = File::create(target_path).unwrap();
    target.write_fmt(format_args!("{}", formatted_string)).ok();
}

fn compile(state: &mut State) {

    let dpdk_path = state.dpdk_path.clone().unwrap();
    let dpdk_config = state.dpdk_config.clone().unwrap();
    let project_path = state.project_path.clone().unwrap();
    let lib_path = dpdk_path.join("lib");
    println!("cargo:rustc-link-search=native={}",
             lib_path.to_str().unwrap());
    for link in &state.dpdk_links {
        println!("cargo:rustc-link-lib={}",
                 link.file_stem()
                     .unwrap()
                     .to_str()
                     .unwrap());
    }
    let dpdk_include_path = dpdk_path.join("include");
    let c_include_path = project_path.join("c_header");
    let c_source_path = project_path.join("c_source");
    gcc::Config::new()
        .file(c_source_path.join("inline_wrapper.c"))
        .include(&dpdk_include_path)
        .include(&c_include_path)
        .include(&project_path)
        .flag("-march=native")
        .flag("-imacros")
        .flag(dpdk_config.to_str().unwrap())
        .compile("lib_c_inline_wrapper.a");

    gcc::Config::new()
        .file(c_source_path.join("macro_wrapper.c"))
        .include(&c_include_path)
        .flag("-march=native")
        .compile("lib_c_macro_wrapper.a");
}
fn main() {
    let mut state: State = Default::default();
    state.project_path = Some(PathBuf::from("."));
    find_dpdk(&mut state);
    find_link_libs(&mut state);
    make_all_in_one_header(&mut state);
    generate_rust_def(&mut state);
    generate_lib_rs(&mut state);
    compile(&mut state);
}
<commit_msg>Fix link path<commit_after>extern crate gcc;
//extern crate bindgen;
extern crate regex;

use std::path::*;
use std::env;
use std::process::Command;
use std::fs::*;
use std::io::*;
use regex::Regex;

#[derive(Default)]
struct State {
    project_path: Option<PathBuf>,
    dpdk_path: Option<PathBuf>,
    dpdk_headers: Vec<PathBuf>,
    dpdk_links: Vec<PathBuf>,
    dpdk_config: Option<PathBuf>,
}

fn find_dpdk(state: &mut State) {
    if let Ok(path_string) = env::var("RTE_SDK") {
        state.dpdk_path = Some(PathBuf::from(&path_string));
    } else {
        // Automatic download
        let dir_path = Path::new("3rdparty");
        if !dir_path.exists() {
            create_dir(dir_path).ok();
        }
        assert!(dir_path.exists());
        let git_path = dir_path.join("dpdk");
        if !git_path.exists() {
            Command::new("git")
                .args(&["clone",
                        "-b",
                        "anlab",
                        "https://github.com/ANLAB-KAIST/dpdk",
                        git_path.to_str().unwrap()])
                .output()
                .expect("failed to run git command");
        }
        Command::new("make")
            .args(&["-C", git_path.to_str().unwrap(), "config", "T=anlab_shared"])
            .output()
            .expect("failed to run make command");
        Command::new("make")
            .args(&["-C", git_path.to_str().unwrap(), "-j", "T=anlab_shared"])
            .output()
            .expect("failed to run make command");

        state.dpdk_path = Some(git_path.join("build"));
    }
    assert!(state.dpdk_path
                .clone()
                .unwrap()
                .exists());
    let config_header = state.dpdk_path
        .clone()
        .unwrap()
        .join("include")
        .join("rte_config.h");
    assert!(config_header.exists());
    state.dpdk_config = Some(config_header);
}

fn find_link_libs(state: &mut State) {
    let dpdk_path = state.dpdk_path.clone().unwrap();
    let lib_dir = dpdk_path.join("lib");

    let mut libs = vec![];
    for entry in lib_dir.read_dir().expect("read_dir failed") {
        if let Ok(entry) = entry {
            let path = entry.path();
            if !path.is_file() {
                continue;
            }

            if let Some(ext) = path.extension() {
                if ext != "a" && ext != "so" {
                    continue;
                }
            } else {
                continue;
            }

            if let Some(file_stem) = path.file_stem() {
                let string = file_stem.to_str().unwrap();
                if !string.starts_with("librte_") {
                    continue;
                }
                libs.push(path.clone());
            } else {
                continue;
            }
        } else {
            continue;
        }
    }
    libs.sort();
    state.dpdk_links = libs;
}

fn check_direct_include(path: &Path) -> bool {
    if !path.is_file() {
        return false;
    }
    let file = File::open(path).unwrap();
    let reader = BufReader::new(&file);
    for (_, line) in reader.lines().enumerate() {
        let line_str = line.ok()
            .unwrap()
            .trim()
            .to_lowercase();
        if line_str.starts_with("#error") {
            if line_str.find("do not").is_some() && line_str.find("include").is_some() &&
               line_str.find("directly").is_some() {
                return false;
            }
        }
    }
    return true;
}

fn make_all_in_one_header(state: &mut State) {
    let include_dir = state.dpdk_path
        .clone()
        .unwrap()
        .join("include");
    let dpdk_config = state.dpdk_config.clone().unwrap();
    let mut headers = vec![];
    for entry in include_dir.read_dir().expect("read_dir failed") {
        if let Ok(entry) = entry {

            let path = entry.path();

            if !path.is_file() {
                continue;
            }

            if let Some(ext) = path.extension() {
                if ext != "h" {
                    continue;
                }
            } else {
                continue;
            }
            if path == dpdk_config {
                continue;
            }
            if !check_direct_include(&path) {
                continue;
            }
            headers.push(path);
        } else {
            continue;
        }
    }
    headers.sort();
    state.dpdk_headers = headers;
    let template_path = state.project_path
        .clone()
        .unwrap()
        .join("dpdk.h.template");
    let target_path = state.project_path
        .clone()
        .unwrap()
        .join("dpdk.h");
    let mut template = File::open(template_path).unwrap();
    let mut target = File::create(target_path).unwrap();

    let mut template_string = String::new();
    template.read_to_string(&mut template_string).ok();

    let mut headers_string = String::new();
    for header in &state.dpdk_headers {
        headers_string += &format!("#include <{}>\n",
                                   header.clone()
                                       .file_name()
                                       .unwrap()
                                       .to_str()
                                       .unwrap());
    }
    let formatted_string = template_string.replace("%header_list%", &headers_string);

    target.write_fmt(format_args!("{}", formatted_string)).ok();
}

fn generate_rust_def(state: &mut State) {
    let dpdk_include_path = state.dpdk_path
        .clone()
        .unwrap()
        .join("include");
    let c_include_path = state.project_path
        .clone()
        .unwrap()
        .join("c_header");
    let dpdk_config_path = state.dpdk_config.clone().unwrap();

    let header_path = state.project_path
        .clone()
        .unwrap()
        .join("dpdk.h");
    let target_path = state.project_path
        .clone()
        .unwrap()
        .join("src")
        .join("dpdk.rs");
    /*
    bindgen::builder()
        .header(header_path.to_str().unwrap())
        .no_unstable_rust()
        .clang_arg(format!("-I{}", dpdk_include_path.to_str().unwrap()))
        .clang_arg(format!("-I{}", c_include_path.to_str().unwrap()))
        .clang_arg("-imacros")
        .clang_arg(dpdk_config_path.to_str().unwrap())
        .clang_arg("-march=native")
        .generate()
        .unwrap()
        .write_to_file(target_path)
        .ok();
        */

    //XXX replace with native bindgen package later
    Command::new("bindgen")
        .args(&[header_path.to_str().unwrap(),
                "--output",
                target_path.to_str().unwrap(),
                "--no-unstable-rust",
                "--",
                &format!("-I{}", dpdk_include_path.to_str().unwrap()),
                &format!("-I{}", c_include_path.to_str().unwrap()),
                "-imacros",
                dpdk_config_path.to_str().unwrap(),
                "-march=native"])
        .output()
        .expect("failed to run bindgen command");
}

fn generate_lib_rs(state: &mut State) {
    let template_path = state.project_path
        .clone()
        .unwrap()
        .join("lib.rs.template");
    let target_path = state.project_path
        .clone()
        .unwrap()
        .join("src")
        .join("lib.rs");

    let format = Regex::new(r"rte_pmd_(\w+)").unwrap();

    let mut pmds = vec![];
    for link in &state.dpdk_links {
        let link_name = link.file_stem()
            .unwrap()
            .to_str()
            .unwrap();
        if let Some(capture) = format.captures(link_name) {
            pmds.push(String::from(&capture[1]));
        }
    }

    let mut pmds_string = String::new();
    for pmd in pmds {
        pmds_string += &format!("\n\"{}\",", pmd);
    }

    let mut template = File::open(template_path).unwrap();
    let mut template_string = String::new();
    template.read_to_string(&mut template_string).ok();

    let formatted_string = template_string.replace("%pmd_list%", &pmds_string);
    let mut target = File::create(target_path).unwrap();
    target.write_fmt(format_args!("{}", formatted_string)).ok();
}

fn compile(state: &mut State) {

    let dpdk_path = state.dpdk_path.clone().unwrap();
    let dpdk_config = state.dpdk_config.clone().unwrap();
    let project_path = state.project_path.clone().unwrap();
    let lib_path = dpdk_path.join("lib");
    println!("cargo:rustc-link-search=native={}",
             lib_path.to_str().unwrap());
    let format = Regex::new(r"lib(.*)\.(a|so)").unwrap();
    for link in &state.dpdk_links {
        let link_name = link.file_name()
            .unwrap()
            .to_str()
            .unwrap();
        if let Some(capture) = format.captures(link_name) {
            println!("cargo:rustc-link-lib={}", &capture[1]);
        }
    }
    let dpdk_include_path = dpdk_path.join("include");
    let c_include_path = project_path.join("c_header");
    let c_source_path = project_path.join("c_source");
    gcc::Config::new()
        .file(c_source_path.join("inline_wrapper.c"))
        .include(&dpdk_include_path)
        .include(&c_include_path)
        .include(&project_path)
        .flag("-march=native")
        .flag("-imacros")
        .flag(dpdk_config.to_str().unwrap())
        .compile("lib_c_inline_wrapper.a");

    gcc::Config::new()
        .file(c_source_path.join("macro_wrapper.c"))
        .include(&c_include_path)
        .flag("-march=native")
        .compile("lib_c_macro_wrapper.a");
}
fn main() {
    let mut state: State = Default::default();
    state.project_path = Some(PathBuf::from("."));
    find_dpdk(&mut state);
    find_link_libs(&mut state);
    make_all_in_one_header(&mut state);
    generate_rust_def(&mut state);
    generate_lib_rs(&mut state);
    compile(&mut state);
}
<|endoftext|>


<commit_before>fn env(name: &str) -> Option<std::ffi::OsString> {
    let target = std::env::var("TARGET").expect("Cargo didn't provide `TARGET` environment var");
    let target = target.to_uppercase().replace("-", "_");
    let prefixed_name = format!("{}_{}", target, name);
    println!("cargo:rerun-if-env-changed={}", prefixed_name);
    match std::env::var_os(prefixed_name) {
        Some(v) => Some(v),
        None => {
            println!("cargo:rerun-if-env-changed={}", name);
            std::env::var_os(name)
        }
    }
}

fn main() {
    if let Some(magic_dir) = env("MAGIC_DIR").map(std::path::PathBuf::from) {
        if !std::path::Path::new(&magic_dir).exists() {
            panic!("Magic library directory {:?} does not exist", magic_dir);
        }
        println!(
            "cargo:rustc-link-search=native={}",
            magic_dir.to_string_lossy()
        );

        let static_lib = magic_dir.join("libmagic.a");
        let shared_lib = magic_dir.join("libmagic.so");
        match env("MAGIC_STATIC").as_ref().and_then(|s| s.to_str()) {
            Some("false") | Some("FALSE") | Some("0") => {
                if !shared_lib.exists() {
                    panic!("No libmagic.so found in {:?}", magic_dir);
                }
                println!("cargo:rustc-link-lib=dylib=magic");
            }
            Some(_) => {
                if !static_lib.exists() {
                    panic!("No libmagic.a found in {:?}", magic_dir);
                }
                println!("cargo:rustc-link-lib=static=magic");
            }
            None => {
                match (static_lib.exists(), shared_lib.exists()) {
                    (false, false) => panic!("Neither libmagic.so, nor libmagic.a was found in {:?}", magic_dir),
                    (true, false) => println!("cargo:rustc-link-lib=static=magic"),
                    (false, true) => println!("cargo:rustc-link-lib=dylib=magic"),
                    (true, true) => panic!("Both a static and a shared library were found in {:?}\nspecify a choice with `MAGIC_STATIC=true|false`", magic_dir),
                }
            }
        }
    } else {
        if let Err(err) = vcpkg::find_package("libmagic") {
            println!("Could not find vcpkg package: {}", err);
        }

        println!("cargo:rustc-link-lib=dylib=magic");
    }
}
<commit_msg>Add workaround for Windows build<commit_after>fn env(name: &str) -> Option<std::ffi::OsString> {
    let target = std::env::var("TARGET").expect("Cargo didn't provide `TARGET` environment var");
    let target = target.to_uppercase().replace("-", "_");
    let prefixed_name = format!("{}_{}", target, name);
    println!("cargo:rerun-if-env-changed={}", prefixed_name);
    match std::env::var_os(prefixed_name) {
        Some(v) => Some(v),
        None => {
            println!("cargo:rerun-if-env-changed={}", name);
            std::env::var_os(name)
        }
    }
}

fn main() {
    if let Some(magic_dir) = env("MAGIC_DIR").map(std::path::PathBuf::from) {
        if !std::path::Path::new(&magic_dir).exists() {
            panic!("Magic library directory {:?} does not exist", magic_dir);
        }
        println!(
            "cargo:rustc-link-search=native={}",
            magic_dir.to_string_lossy()
        );

        let static_lib = magic_dir.join("libmagic.a");
        let shared_lib = magic_dir.join("libmagic.so");
        match env("MAGIC_STATIC").as_ref().and_then(|s| s.to_str()) {
            Some("false") | Some("FALSE") | Some("0") => {
                if !shared_lib.exists() {
                    panic!("No libmagic.so found in {:?}", magic_dir);
                }
                println!("cargo:rustc-link-lib=dylib=magic");
            }
            Some(_) => {
                if !static_lib.exists() {
                    panic!("No libmagic.a found in {:?}", magic_dir);
                }
                println!("cargo:rustc-link-lib=static=magic");
            }
            None => {
                match (static_lib.exists(), shared_lib.exists()) {
                    (false, false) => panic!("Neither libmagic.so, nor libmagic.a was found in {:?}", magic_dir),
                    (true, false) => println!("cargo:rustc-link-lib=static=magic"),
                    (false, true) => println!("cargo:rustc-link-lib=dylib=magic"),
                    (true, true) => panic!("Both a static and a shared library were found in {:?}\nspecify a choice with `MAGIC_STATIC=true|false`", magic_dir),
                }
            }
        }
    } else {
        if let Err(err) = vcpkg::find_package("libmagic") {
            println!("Could not find vcpkg package: {}", err);
        } else if cfg!(windows) {
            // workaround, see https://github.com/robo9k/rust-magic-sys/pull/16#issuecomment-949094327
            println!("cargo:rustc-link-lib=shlwapi");

            // vcpkg was successful, don't print anything else
            return;
        }

        // default fall through: try linking dynamically to just `libmagic` without further config
        println!("cargo:rustc-link-lib=dylib=magic");
    }
}
<|endoftext|>


<commit_before>use std::io::process::{ProcessOutput, ProcessExit, ExitStatus, ExitSignal};
use std::io::IoError;
use std::fmt::{mod, Show, Formatter, FormatError};
use std::str;
use serialize::json;
use semver;

use curl;
use docopt;
use toml::Error as TomlError;
use url;
use git2;

pub trait CargoError: Send {
    fn description(&self) -> String;
    fn detail(&self) -> Option<String> { None }
    fn cause(&self) -> Option<&CargoError> { None }
    fn is_human(&self) -> bool { false }

    fn to_error<E: FromError<Self>>(self) -> E {
        FromError::from_error(self)
    }

    fn box_error(self) -> Box<CargoError + Send> {
        box self as Box<CargoError + Send>
    }

    fn concrete(&self) -> ConcreteCargoError {
        ConcreteCargoError {
            description: self.description(),
            detail: self.detail(),
            cause: self.cause().map(|c| box c.concrete() as Box<CargoError + Send>),
            is_human: self.is_human()
        }
    }

    fn with_cause<E: CargoError + Send>(self, cause: E) -> Box<CargoError + Send> {
        let mut concrete = self.concrete();
        concrete.cause = Some(cause.box_error());
        box concrete as Box<CargoError + Send>
    }

    fn mark_human(self) -> Box<CargoError + Send> {
        let mut concrete = self.concrete();
        concrete.is_human = true;
        box concrete as Box<CargoError + Send>
    }
}

pub trait FromError<E> {
    fn from_error(error: E) -> Self;
}

impl<E: CargoError + Send> FromError<E> for Box<CargoError + Send> {
    fn from_error(error: E) -> Box<CargoError + Send> {
        error.box_error()
    }
}

macro_rules! from_error (
    ($ty:ty) => {
        impl FromError<$ty> for $ty {
            fn from_error(error: $ty) -> $ty {
                error
            }
        }
    }
)

impl Show for Box<CargoError + Send> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        try!(write!(f, "{}", self.description()));
        Ok(())
    }
}

impl CargoError for Box<CargoError + Send> {
    fn description(&self) -> String {
        (*self).description()
    }

    fn detail(&self) -> Option<String> {
        (*self).detail()
    }

    fn cause(&self) -> Option<&CargoError> {
        (*self).cause()
    }

    fn is_human(&self) -> bool {
        (*self).is_human()
    }

    fn box_error(self) -> Box<CargoError + Send> {
        self
    }
}

impl CargoError for semver::ReqParseError {
    fn description(&self) -> String {
        self.to_string()
    }
}

pub type CargoResult<T> = Result<T, Box<CargoError + Send>>;

pub trait BoxError<T> {
    fn box_error(self) -> CargoResult<T>;
}

pub trait ChainError<T> {
    fn chain_error<E: CargoError + Send>(self, callback: || -> E) -> CargoResult<T> ;
}

impl<'a, T> ChainError<T> for ||:'a -> CargoResult<T> {
    fn chain_error<E: CargoError + Send>(self, callback: || -> E) -> CargoResult<T> {
        self().map_err(|err| callback().with_cause(err))
    }
}

impl<T, E: CargoError + Send> BoxError<T> for Result<T, E> {
    fn box_error(self) -> CargoResult<T> {
        self.map_err(|err| err.box_error())
    }
}

impl<T, E: CargoError + Send> ChainError<T> for Result<T, E> {
    fn chain_error<E: CargoError + Send>(self, callback: || -> E) -> CargoResult<T>  {
        self.map_err(|err| callback().with_cause(err))
    }
}

impl CargoError for IoError {
    fn description(&self) -> String { self.to_string() }
}

from_error!(IoError)

impl CargoError for TomlError {
    fn description(&self) -> String { self.to_string() }
}

from_error!(TomlError)

impl CargoError for FormatError {
    fn description(&self) -> String {
        "formatting failed".to_string()
    }
}

from_error!(FormatError)

impl CargoError for curl::ErrCode {
    fn description(&self) -> String { self.to_string() }
}

from_error!(curl::ErrCode)

impl CargoError for json::DecoderError {
    fn description(&self) -> String { self.to_string() }
}

from_error!(json::DecoderError)

pub struct ProcessError {
    pub msg: String,
    pub exit: Option<ProcessExit>,
    pub output: Option<ProcessOutput>,
    pub detail: Option<String>,
    pub cause: Option<Box<CargoError + Send>>
}

from_error!(ProcessError)

impl Show for ProcessError {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let exit = match self.exit {
            Some(ExitStatus(i)) | Some(ExitSignal(i)) => i.to_string(),
            None => "never executed".to_string()
        };
        try!(write!(f, "{} (status={})", self.msg, exit));
        self.output().map(|out| { let _ = write!(f, "{}", out); });
        Ok(())
    }
}

impl ProcessError {
    pub fn output(&self) -> Option<String> {
        match self.output {
            Some(ref out) => {
                let mut string = String::new();
                match str::from_utf8(out.output.as_slice()) {
                    Some(s) if s.trim().len() > 0 => {
                        string.push_str("\n--- stdout\n");
                        string.push_str(s);
                    }
                    Some(..) | None => {}
                }
                match str::from_utf8(out.error.as_slice()) {
                    Some(s) if s.trim().len() > 0 => {
                        string.push_str("\n--- stderr\n");
                        string.push_str(s);
                    }
                    Some(..) | None => {}
                }
                Some(string)
            },
            None => None
        }
    }
}

impl CargoError for ProcessError {
    fn description(&self) -> String { self.to_string() }

    fn detail(&self) -> Option<String> {
        self.detail.clone()
    }

    fn cause(&self) -> Option<&CargoError> {
        self.cause.as_ref().map(|c| { let err: &CargoError = &**c; err })
    }

    fn with_cause<E: CargoError + Send>(mut self,
                                        err: E) -> Box<CargoError + Send> {
        self.cause = Some(err.box_error());
        box self as Box<CargoError + Send>
    }
}

pub struct ConcreteCargoError {
    description: String,
    detail: Option<String>,
    cause: Option<Box<CargoError + Send>>,
    is_human: bool
}

impl Show for ConcreteCargoError {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}", self.description)
    }
}

impl CargoError for ConcreteCargoError {
    fn description(&self) -> String {
        self.description.clone()
    }

    fn detail(&self) -> Option<String> {
        self.detail.clone()
    }

    fn cause(&self) -> Option<&CargoError> {
        self.cause.as_ref().map(|c| { let err: &CargoError = &**c; err })
    }

    fn with_cause<E: CargoError + Send>(mut self,
                                        err: E) -> Box<CargoError + Send> {
        self.cause = Some(err.box_error());
        box self as Box<CargoError + Send>
    }

    fn mark_human(mut self) -> Box<CargoError + Send> {
        self.is_human = true;
        box self as Box<CargoError + Send>
    }

    fn is_human(&self) -> bool {
        self.is_human
    }
}

pub type CliResult<T> = Result<T, CliError>;

#[deriving(Show)]
pub struct CliError {
    pub error: Box<CargoError + Send>,
    pub unknown: bool,
    pub exit_code: uint
}

impl CargoError for CliError {
    fn description(&self) -> String {
        self.error.to_string()
    }
}

from_error!(CliError)

impl CargoError for docopt::Error {
    fn description(&self) -> String {
        match *self {
            docopt::WithProgramUsage(ref other, _) => other.description(),
            ref e if e.fatal() => self.to_string(),
            _ => "".to_string(),
        }
    }

    fn detail(&self) -> Option<String> {
        match *self {
            docopt::WithProgramUsage(_, ref usage) => Some(usage.clone()),
            ref e if e.fatal() => None,
            ref e => Some(e.to_string()),
        }
    }

    fn is_human(&self) -> bool { true }
}

from_error!(docopt::Error)

impl CargoError for url::ParseError {
    fn description(&self) -> String { self.to_string() }
}

from_error!(url::ParseError)

impl CargoError for git2::Error {
    fn description(&self) -> String { self.to_string() }
}

from_error!(git2::Error)

impl CliError {
    pub fn new<S: Str>(error: S, code: uint) -> CliError {
        let error = human(error.as_slice().to_string());
        CliError::from_boxed(error, code)
    }

    pub fn from_error<E: CargoError + 'static>(error: E, code: uint) -> CliError {
        let error = box error as Box<CargoError + Send>;
        CliError::from_boxed(error, code)
    }

    pub fn from_boxed(error: Box<CargoError + Send>, code: uint) -> CliError {
        let human = error.is_human();
        CliError { error: error, exit_code: code, unknown: !human }
    }
}

pub fn process_error<S: Str>(msg: S,
                             cause: Option<IoError>,
                             status: Option<&ProcessExit>,
                             output: Option<&ProcessOutput>) -> ProcessError {
    ProcessError {
        msg: msg.as_slice().to_string(),
        exit: status.map(|o| o.clone()),
        output: output.map(|o| o.clone()),
        detail: None,
        cause: cause.map(|c| box c as Box<CargoError + Send>)
    }
}

pub fn internal_error<S1: Str, S2: Str>(error: S1,
                                        detail: S2) -> Box<CargoError + Send> {
    box ConcreteCargoError {
        description: error.as_slice().to_string(),
        detail: Some(detail.as_slice().to_string()),
        cause: None,
        is_human: false
    } as Box<CargoError + Send>
}

pub fn internal<S: Show>(error: S) -> Box<CargoError + Send> {
    box ConcreteCargoError {
        description: error.to_string(),
        detail: None,
        cause: None,
        is_human: false
    } as Box<CargoError + Send>
}

pub fn human<S: Show>(error: S) -> Box<CargoError + Send> {
    box ConcreteCargoError {
        description: error.to_string(),
        detail: None,
        cause: None,
        is_human: true
    } as Box<CargoError + Send>
}

pub fn caused_human<S: Show, E: CargoError + Send>(error: S, cause: E) -> Box<CargoError + Send> {
    box ConcreteCargoError {
        description: error.to_string(),
        detail: None,
        cause: Some(cause.box_error()),
        is_human: true
    } as Box<CargoError + Send>
}
<commit_msg>Fix infinite recursion in CargoError impl for Box<CargoError><commit_after>use std::io::process::{ProcessOutput, ProcessExit, ExitStatus, ExitSignal};
use std::io::IoError;
use std::fmt::{mod, Show, Formatter, FormatError};
use std::str;
use serialize::json;
use semver;

use curl;
use docopt;
use toml::Error as TomlError;
use url;
use git2;

pub trait CargoError: Send {
    fn description(&self) -> String;
    fn detail(&self) -> Option<String> { None }
    fn cause(&self) -> Option<&CargoError> { None }
    fn is_human(&self) -> bool { false }

    fn to_error<E: FromError<Self>>(self) -> E {
        FromError::from_error(self)
    }

    fn box_error(self) -> Box<CargoError + Send> {
        box self as Box<CargoError + Send>
    }

    fn concrete(&self) -> ConcreteCargoError {
        ConcreteCargoError {
            description: self.description(),
            detail: self.detail(),
            cause: self.cause().map(|c| box c.concrete() as Box<CargoError + Send>),
            is_human: self.is_human()
        }
    }

    fn with_cause<E: CargoError + Send>(self, cause: E) -> Box<CargoError + Send> {
        let mut concrete = self.concrete();
        concrete.cause = Some(cause.box_error());
        box concrete as Box<CargoError + Send>
    }

    fn mark_human(self) -> Box<CargoError + Send> {
        let mut concrete = self.concrete();
        concrete.is_human = true;
        box concrete as Box<CargoError + Send>
    }
}

pub trait FromError<E> {
    fn from_error(error: E) -> Self;
}

impl<E: CargoError + Send> FromError<E> for Box<CargoError + Send> {
    fn from_error(error: E) -> Box<CargoError + Send> {
        error.box_error()
    }
}

macro_rules! from_error (
    ($ty:ty) => {
        impl FromError<$ty> for $ty {
            fn from_error(error: $ty) -> $ty {
                error
            }
        }
    }
)

impl Show for Box<CargoError + Send> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        try!(write!(f, "{}", self.description()));
        Ok(())
    }
}

impl CargoError for Box<CargoError + Send> {
    fn description(&self) -> String {
        (**self).description()
    }

    fn detail(&self) -> Option<String> {
        (**self).detail()
    }

    fn cause(&self) -> Option<&CargoError> {
        (**self).cause()
    }

    fn is_human(&self) -> bool {
        (**self).is_human()
    }

    fn box_error(self) -> Box<CargoError + Send> {
        self
    }
}

impl CargoError for semver::ReqParseError {
    fn description(&self) -> String {
        self.to_string()
    }
}

pub type CargoResult<T> = Result<T, Box<CargoError + Send>>;

pub trait BoxError<T> {
    fn box_error(self) -> CargoResult<T>;
}

pub trait ChainError<T> {
    fn chain_error<E: CargoError + Send>(self, callback: || -> E) -> CargoResult<T> ;
}

impl<'a, T> ChainError<T> for ||:'a -> CargoResult<T> {
    fn chain_error<E: CargoError + Send>(self, callback: || -> E) -> CargoResult<T> {
        self().map_err(|err| callback().with_cause(err))
    }
}

impl<T, E: CargoError + Send> BoxError<T> for Result<T, E> {
    fn box_error(self) -> CargoResult<T> {
        self.map_err(|err| err.box_error())
    }
}

impl<T, E: CargoError + Send> ChainError<T> for Result<T, E> {
    fn chain_error<E: CargoError + Send>(self, callback: || -> E) -> CargoResult<T>  {
        self.map_err(|err| callback().with_cause(err))
    }
}

impl CargoError for IoError {
    fn description(&self) -> String { self.to_string() }
}

from_error!(IoError)

impl CargoError for TomlError {
    fn description(&self) -> String { self.to_string() }
}

from_error!(TomlError)

impl CargoError for FormatError {
    fn description(&self) -> String {
        "formatting failed".to_string()
    }
}

from_error!(FormatError)

impl CargoError for curl::ErrCode {
    fn description(&self) -> String { self.to_string() }
}

from_error!(curl::ErrCode)

impl CargoError for json::DecoderError {
    fn description(&self) -> String { self.to_string() }
}

from_error!(json::DecoderError)

pub struct ProcessError {
    pub msg: String,
    pub exit: Option<ProcessExit>,
    pub output: Option<ProcessOutput>,
    pub detail: Option<String>,
    pub cause: Option<Box<CargoError + Send>>
}

from_error!(ProcessError)

impl Show for ProcessError {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let exit = match self.exit {
            Some(ExitStatus(i)) | Some(ExitSignal(i)) => i.to_string(),
            None => "never executed".to_string()
        };
        try!(write!(f, "{} (status={})", self.msg, exit));
        self.output().map(|out| { let _ = write!(f, "{}", out); });
        Ok(())
    }
}

impl ProcessError {
    pub fn output(&self) -> Option<String> {
        match self.output {
            Some(ref out) => {
                let mut string = String::new();
                match str::from_utf8(out.output.as_slice()) {
                    Some(s) if s.trim().len() > 0 => {
                        string.push_str("\n--- stdout\n");
                        string.push_str(s);
                    }
                    Some(..) | None => {}
                }
                match str::from_utf8(out.error.as_slice()) {
                    Some(s) if s.trim().len() > 0 => {
                        string.push_str("\n--- stderr\n");
                        string.push_str(s);
                    }
                    Some(..) | None => {}
                }
                Some(string)
            },
            None => None
        }
    }
}

impl CargoError for ProcessError {
    fn description(&self) -> String { self.to_string() }

    fn detail(&self) -> Option<String> {
        self.detail.clone()
    }

    fn cause(&self) -> Option<&CargoError> {
        self.cause.as_ref().map(|c| { let err: &CargoError = &**c; err })
    }

    fn with_cause<E: CargoError + Send>(mut self,
                                        err: E) -> Box<CargoError + Send> {
        self.cause = Some(err.box_error());
        box self as Box<CargoError + Send>
    }
}

pub struct ConcreteCargoError {
    description: String,
    detail: Option<String>,
    cause: Option<Box<CargoError + Send>>,
    is_human: bool
}

impl Show for ConcreteCargoError {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}", self.description)
    }
}

impl CargoError for ConcreteCargoError {
    fn description(&self) -> String {
        self.description.clone()
    }

    fn detail(&self) -> Option<String> {
        self.detail.clone()
    }

    fn cause(&self) -> Option<&CargoError> {
        self.cause.as_ref().map(|c| { let err: &CargoError = &**c; err })
    }

    fn with_cause<E: CargoError + Send>(mut self,
                                        err: E) -> Box<CargoError + Send> {
        self.cause = Some(err.box_error());
        box self as Box<CargoError + Send>
    }

    fn mark_human(mut self) -> Box<CargoError + Send> {
        self.is_human = true;
        box self as Box<CargoError + Send>
    }

    fn is_human(&self) -> bool {
        self.is_human
    }
}

pub type CliResult<T> = Result<T, CliError>;

#[deriving(Show)]
pub struct CliError {
    pub error: Box<CargoError + Send>,
    pub unknown: bool,
    pub exit_code: uint
}

impl CargoError for CliError {
    fn description(&self) -> String {
        self.error.to_string()
    }
}

from_error!(CliError)

impl CargoError for docopt::Error {
    fn description(&self) -> String {
        match *self {
            docopt::WithProgramUsage(ref other, _) => other.description(),
            ref e if e.fatal() => self.to_string(),
            _ => "".to_string(),
        }
    }

    fn detail(&self) -> Option<String> {
        match *self {
            docopt::WithProgramUsage(_, ref usage) => Some(usage.clone()),
            ref e if e.fatal() => None,
            ref e => Some(e.to_string()),
        }
    }

    fn is_human(&self) -> bool { true }
}

from_error!(docopt::Error)

impl CargoError for url::ParseError {
    fn description(&self) -> String { self.to_string() }
}

from_error!(url::ParseError)

impl CargoError for git2::Error {
    fn description(&self) -> String { self.to_string() }
}

from_error!(git2::Error)

impl CliError {
    pub fn new<S: Str>(error: S, code: uint) -> CliError {
        let error = human(error.as_slice().to_string());
        CliError::from_boxed(error, code)
    }

    pub fn from_error<E: CargoError + 'static>(error: E, code: uint) -> CliError {
        let error = box error as Box<CargoError + Send>;
        CliError::from_boxed(error, code)
    }

    pub fn from_boxed(error: Box<CargoError + Send>, code: uint) -> CliError {
        let human = error.is_human();
        CliError { error: error, exit_code: code, unknown: !human }
    }
}

pub fn process_error<S: Str>(msg: S,
                             cause: Option<IoError>,
                             status: Option<&ProcessExit>,
                             output: Option<&ProcessOutput>) -> ProcessError {
    ProcessError {
        msg: msg.as_slice().to_string(),
        exit: status.map(|o| o.clone()),
        output: output.map(|o| o.clone()),
        detail: None,
        cause: cause.map(|c| box c as Box<CargoError + Send>)
    }
}

pub fn internal_error<S1: Str, S2: Str>(error: S1,
                                        detail: S2) -> Box<CargoError + Send> {
    box ConcreteCargoError {
        description: error.as_slice().to_string(),
        detail: Some(detail.as_slice().to_string()),
        cause: None,
        is_human: false
    } as Box<CargoError + Send>
}

pub fn internal<S: Show>(error: S) -> Box<CargoError + Send> {
    box ConcreteCargoError {
        description: error.to_string(),
        detail: None,
        cause: None,
        is_human: false
    } as Box<CargoError + Send>
}

pub fn human<S: Show>(error: S) -> Box<CargoError + Send> {
    box ConcreteCargoError {
        description: error.to_string(),
        detail: None,
        cause: None,
        is_human: true
    } as Box<CargoError + Send>
}

pub fn caused_human<S: Show, E: CargoError + Send>(error: S, cause: E) -> Box<CargoError + Send> {
    box ConcreteCargoError {
        description: error.to_string(),
        detail: None,
        cause: Some(cause.box_error()),
        is_human: true
    } as Box<CargoError + Send>
}
<|endoftext|>


<commit_before>#[derive(Eq, PartialEq)]
enum Direction { North, East, South, West, Unplaced, }

use Direction::*;

struct Table {
    w: i32,
    h: i32,
}

struct Robot {
    x: i32,
    y: i32,
    d: Direction,
    t: Table,
}

impl Direction {
    fn from_string(d: &str) -> Option<Direction> {
        match d {
            "NORTH" => Some(North),
            "EAST" => Some(East),
            "SOUTH" => Some(South),
            "WEST" => Some(West),
            _ => None,
        }
    }

    fn to_string(&self) -> String {
        let s = match *self {
            North => "NORTH",
            East => "EAST",
            South => "SOUTH",
            West => "WEST",
            _ => "UNPLACED",
        };

        s.to_string()
    }
}

impl Default for Robot {
    fn default() -> Robot {
        let table = Table{w: 5, h: 5};

        Robot{x: 0, y: 0, d: Unplaced, t: table}
    }
}

impl Table {
    fn valid_pos(&self, x: i32, y: i32) -> bool {
        x >= 0 && x < self.w && y >= 0 && y < self.h
    }
}

impl Robot {
    fn place(&mut self, x: i32, y: i32, d: Direction) {
        if self.t.valid_pos(x, y) && d != Unplaced {
            self.x = x;
            self.y = y;
            self.d = d;
        }
    }

    fn right(&mut self) {
        let d = match self.d {
            North => East,
            East => South,
            South => West,
            West => North,
            _ => Unplaced,
        };

        self.d = d;
    }

    fn left(&mut self) {
        let d = match self.d {
            North => West,
            West => South,
            South => East,
            East => North,
            _ => Unplaced,
        };

        self.d = d;
    }

    fn step(&mut self) {
        match self.d {
            North => if self.t.valid_pos(self.x, self.y + 1) {self.y += 1;},
            East => if self.t.valid_pos(self.x + 1, self.y) {self.x += 1;},
            South => if self.t.valid_pos(self.x, self.y - 1) {self.y -= 1;},
            West => if self.t.valid_pos(self.x - 1, self.y) {self.y -= 1;},
            _ => (),
        }
    }

    fn report(&self) {
        println!("{}, {}, {}", self.x, self.y, self.d.to_string());
    }
}

fn parse_place(args: &[&str]) -> (i32, i32, Direction) {
    // TODO: Implement trait for str with first_char():
    //*args[0].first_char().expect("Invalid X pos");
    let (x, y, d) = (*args[0].chars().collect::<Vec<char>>().first().expect("Invalid place"),
                     *args[1].chars().collect::<Vec<char>>().first().expect("Invalid place"),
                     Direction::from_string(args[2]));

    match (x.to_digit(10), y.to_digit(10), d) {
        (Some(xpos), Some(ypos), Some(dir)) => (xpos as i32, ypos as i32, dir),
        _ => (0, 0, Unplaced),
    }
}

fn main() {
    let mut robot: Robot = Default::default();
    let commands = "MOVE
                    LEFT
                    PLACE 1 2 EAST
                    MOVE
                    MOVE
                    LEFT
                    MOVE
                    REPORT";

    let parsed: Vec<&str> = commands.split("\n").map(|c| c.trim()).collect();

    for c in parsed {
        let args: Vec<&str> = c.split(" ").collect();

        if let Some(arg) = args.first() {
            match *arg {
                "PLACE" if args.len() == 4 => {
                    let (x, y, d) = parse_place(&args[1..]);
                    robot.place(x, y, d);
                },
                "MOVE" => robot.step(),
                "LEFT" => robot.left(),
                "RIGHT" => robot.right(),
                "REPORT" => robot.report(),
                _ => (),
            }
        }
    }
}
<commit_msg>Added array of programs to run<commit_after>#[derive(Eq, PartialEq)]
enum Direction { North, East, South, West, Unplaced, }

use Direction::*;

struct Table {
    w: i32,
    h: i32,
}

struct Robot {
    x: i32,
    y: i32,
    d: Direction,
    t: Table,
}

impl Direction {
    fn from_string(d: &str) -> Option<Direction> {
        match d {
            "NORTH" => Some(North),
            "EAST" => Some(East),
            "SOUTH" => Some(South),
            "WEST" => Some(West),
            _ => None,
        }
    }

    fn to_string(&self) -> String {
        let s = match *self {
            North => "NORTH",
            East => "EAST",
            South => "SOUTH",
            West => "WEST",
            _ => "UNPLACED",
        };

        s.to_string()
    }
}

impl Default for Robot {
    fn default() -> Robot {
        let table = Table{w: 5, h: 5};

        Robot{x: 0, y: 0, d: Unplaced, t: table}
    }
}

impl Table {
    fn valid_pos(&self, x: i32, y: i32) -> bool {
        x >= 0 && x < self.w && y >= 0 && y < self.h
    }
}

impl Robot {
    fn place(&mut self, x: i32, y: i32, d: Direction) {
        if self.t.valid_pos(x, y) && d != Unplaced {
            self.x = x;
            self.y = y;
            self.d = d;
        }
    }

    fn right(&mut self) {
        let d = match self.d {
            North => East,
            East => South,
            South => West,
            West => North,
            _ => Unplaced,
        };

        self.d = d;
    }

    fn left(&mut self) {
        let d = match self.d {
            North => West,
            West => South,
            South => East,
            East => North,
            _ => Unplaced,
        };

        self.d = d;
    }

    fn step(&mut self) {
        match self.d {
            North => if self.t.valid_pos(self.x, self.y + 1) {self.y += 1;},
            East => if self.t.valid_pos(self.x + 1, self.y) {self.x += 1;},
            South => if self.t.valid_pos(self.x, self.y - 1) {self.y -= 1;},
            West => if self.t.valid_pos(self.x - 1, self.y) {self.y -= 1;},
            _ => (),
        }
    }

    fn report(&self) {
        println!("{}, {}, {}", self.x, self.y, self.d.to_string());
    }
}

fn parse_place(args: &[&str]) -> (i32, i32, Direction) {
    // TODO: Implement trait for str with first_char():
    //*args[0].first_char().expect("Invalid X pos");
    let (x, y, d) = (*args[0].chars().collect::<Vec<char>>().first().expect("Invalid place"),
                     *args[1].chars().collect::<Vec<char>>().first().expect("Invalid place"),
                     Direction::from_string(args[2]));

    match (x.to_digit(10), y.to_digit(10), d) {
        (Some(xpos), Some(ypos), Some(dir)) => (xpos as i32, ypos as i32, dir),
        _ => (0, 0, Unplaced),
    }
}

fn main() {
    let programs = ["PLACE 0 0 NORTH\nMOVE\nREPORT",
                    "PLACE 0 0 NORTH\nLEFT\nREPORT",
                    "MOVE\nLEFT\nPLACE 1 2 EAST\nEAST\nMOVE\nMOVE\nLEFT\nMOVE\nREPORT",
                    "PLACE 0 0 EAST\nMOVE\nMOVE\nMOVE\nMOVE\nMOVE\nMOVE\nMOVE\nREPORT\nLEFT\nMOVE\nREPORT"];

    for p in programs.iter() {
        let mut robot: Robot = Default::default();
        let parsed: Vec<&str> = p.split("\n").map(|c| c.trim()).collect();

        for c in parsed {
            let args: Vec<&str> = c.split(" ").collect();

            if let Some(arg) = args.first() {
                match *arg {
                    "PLACE" if args.len() == 4 => {
                        let (x, y, d) = parse_place(&args[1..]);
                        robot.place(x, y, d);
                    },
                    "MOVE" => robot.step(),
                    "LEFT" => robot.left(),
                    "RIGHT" => robot.right(),
                    "REPORT" => robot.report(),
                    _ => (),
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::io::{BufRead, BufReader};
use std::net::TcpListener;
use std::sync::mpsc::{channel, Sender};
use std::thread;
use std::u64;

pub struct StatsdListener {
    listener: TcpListener,
}

impl StatsdListener {
    pub fn listen(&self) {
        let (send, recv) = channel();

        let listener = self.listener.try_clone().unwrap();
        thread::spawn(move || {
            accept_on_listener(listener, send)
        });

        for line in recv {
            self.handle_line(line)
        }
    }

    fn handle_line(&self, line: String) {

    }
}

fn accept_on_listener(listener: TcpListener, send: Sender<String>) {
    for stream in listener.incoming() {
        match stream {
            Ok(stream) => {
                let mut reader = BufReader::new(stream);
                let mut line = String::new();

                reader.read_line(&mut line);
                send.send(line).unwrap();
            },
            Err(e) => panic!("Failed to listen on TCP socket: {}", e),
        }
    }
}
<commit_msg>Bugfixes in StatsD TCP listener<commit_after>use std::io::{BufRead, BufReader};
use std::net::{TcpListener, ToSocketAddrs};
use std::sync::mpsc::{channel, Sender};
use std::thread;
use std::u64;

use super::super::parsers::statsd::parse_metrics;

pub struct StatsdTcpListener;

impl StatsdTcpListener {
    pub fn new() -> StatsdTcpListener {
        StatsdTcpListener
    }

    pub fn listen<A>(&self, addr: A)
        where A: ToSocketAddrs {
        let (send, recv) = channel();

        let listener = TcpListener::bind(addr).unwrap();
        thread::spawn(move || {
            accept_on_listener(listener, send)
        });

        for line in recv {
            self.handle_line(line)
        }
    }

    fn handle_line(&self, line: String) {

    }
}

fn accept_on_listener(listener: TcpListener, send: Sender<String>) {
    for stream in listener.incoming() {
        match stream {
            Ok(stream) => {
                let mut reader = BufReader::new(stream);
                let mut line = String::new();

                reader.read_line(&mut line);
                send.send(line).unwrap();
            },
            Err(e) => panic!("Failed to listen on TCP socket: {}", e),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// 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.

use std::io::Error;
use std::ptr::null_mut;

use widestring::WideCString;
use winapi::winerror::*;
use winapi::{BOOL, LPCWSTR, LPDWORD, PSID, PSID_NAME_USE, SID_NAME_USE};

use super::sid::Sid;

extern "system" {
    fn LookupAccountNameW(
        lpSystemName: LPCWSTR,
        lpAccountName: LPCWSTR,
        Sid: PSID,
        cbSid: LPDWORD,
        ReferencedDomainName: LPCWSTR,
        cchReferencedDomainName: LPDWORD,
        peUse: PSID_NAME_USE,
    ) -> BOOL;
}

pub struct Account {
    pub name: String,
    pub system_name: Option<String>,
    pub domain: String,
    pub account_type: SID_NAME_USE,
    pub sid: Sid,
}

impl Account {
    pub fn from_name(name: &str) -> Option<Account> {
        lookup_account(name, None)
    }

    pub fn from_name_and_system(name: &str, system_name: &str) -> Option<Account> {
        lookup_account(name, Some(system_name.to_string()))
    }
}

fn lookup_account(name: &str, system_name: Option<String>) -> Option<Account> {
    // if this is a machine account, strip the terminating '$'
    // LookupAccountName will return the sid of the computer account
    // given the computer name. Windows forbids usernames to match the
    // computer name
    let stripped_name = if name.ends_with("$") {
        &name[..name.len() - 1]
    } else {
        name
    };
    let mut sid_size: u32 = 0;
    let mut domain_size: u32 = 0;
    let wide = WideCString::from_str(stripped_name).unwrap();
    unsafe {
        LookupAccountNameW(
            null_mut(),
            wide.as_ptr(),
            null_mut(),
            &mut sid_size as LPDWORD,
            null_mut(),
            &mut domain_size as LPDWORD,
            null_mut(),
        )
    };
    match Error::last_os_error().raw_os_error().unwrap() as u32 {
        ERROR_INSUFFICIENT_BUFFER => {}
        ERROR_NONE_MAPPED => return None,
        _ => panic!(
            "Error while looking up account for {}: {}",
            name,
            Error::last_os_error()
        ),
    }

    let mut sid: Vec<u8> = Vec::with_capacity(sid_size as usize);
    let mut domain: Vec<u16> = Vec::with_capacity(domain_size as usize);
    let mut sid_type = SID_NAME_USE(0);

    let ret = unsafe {
        LookupAccountNameW(
            null_mut(),
            wide.as_ptr(),
            sid.as_mut_ptr() as PSID,
            &mut sid_size as LPDWORD,
            domain.as_mut_ptr(),
            &mut domain_size as LPDWORD,
            &mut sid_type as PSID_NAME_USE,
        )
    };
    if ret == 0 {
        panic!(
            "Failed to retrieve SID for {}: {}",
            name,
            Error::last_os_error()
        );
    }
    unsafe {
        domain.set_len(domain_size as usize);
        sid.set_len(sid_size as usize);
    }
    let domain_str = WideCString::from_vec(domain).unwrap().to_string_lossy();
    Some(Account {
        name: name.to_string(),
        system_name: system_name,
        domain: domain_str,
        account_type: sid_type,
        sid: Sid { raw: sid },
    })
}

#[cfg(test)]
mod tests {
    use std::env;

    use winapi::winnt::{SidTypeUser, SidTypeWellKnownGroup};

    use super::*;

    #[test]
    fn real_account_returns_some() {
        assert_eq!(Account::from_name("Administrator").is_some(), true)
    }

    #[test]
    fn bogus_account_returns_none() {
        assert_eq!(Account::from_name("bogus").is_none(), true)
    }

    #[test]
    fn user_account_returns_user_type() {
        let acct_type = Account::from_name("Administrator").unwrap().account_type;
        assert_eq!(acct_type, SidTypeUser)
    }

    #[test]
    fn local_user_account_returns_local_machine_as_domain() {
        let acct_domain = Account::from_name("Administrator").unwrap().domain;
        assert_eq!(acct_domain, env::var("COMPUTERNAME").unwrap())
    }

    #[test]
    fn well_known_group_account_returns_correct_type() {
        let acct_type = Account::from_name("Everyone").unwrap().account_type;
        assert_eq!(acct_type, SidTypeWellKnownGroup)
    }

    #[test]
    fn well_known_group_account_has_well_known_sid() {
        let sid = Account::from_name("Everyone").unwrap().sid;
        assert_eq!(sid.to_string().unwrap(), "S-1-1-0")
    }

    #[test]
    fn mixing_case_returns_same_account() {
        let current_user = env::var("USERNAME").unwrap();
        let lower_sid = Account::from_name(current_user.to_lowercase().as_str())
            .unwrap()
            .sid;
        let upper_sid = Account::from_name(current_user.to_uppercase().as_str())
            .unwrap()
            .sid;
        assert_eq!(
            lower_sid.to_string().unwrap(),
            upper_sid.to_string().unwrap()
        )
    }
}
<commit_msg>only trim trailing $ from windows account check if it is the local machine account<commit_after>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// 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.

use std::env;
use std::io::Error;
use std::ptr::null_mut;

use widestring::WideCString;
use winapi::winerror::*;
use winapi::{BOOL, LPCWSTR, LPDWORD, PSID, PSID_NAME_USE, SID_NAME_USE};

use super::sid::Sid;

extern "system" {
    fn LookupAccountNameW(
        lpSystemName: LPCWSTR,
        lpAccountName: LPCWSTR,
        Sid: PSID,
        cbSid: LPDWORD,
        ReferencedDomainName: LPCWSTR,
        cchReferencedDomainName: LPDWORD,
        peUse: PSID_NAME_USE,
    ) -> BOOL;
}

pub struct Account {
    pub name: String,
    pub system_name: Option<String>,
    pub domain: String,
    pub account_type: SID_NAME_USE,
    pub sid: Sid,
}

impl Account {
    pub fn from_name(name: &str) -> Option<Account> {
        lookup_account(name, None)
    }

    pub fn from_name_and_system(name: &str, system_name: &str) -> Option<Account> {
        lookup_account(name, Some(system_name.to_string()))
    }
}

fn lookup_account(name: &str, system_name: Option<String>) -> Option<Account> {
    // if this is a machine account, strip the terminating '$'
    // LookupAccountName will return the sid of the computer account
    // given the computer name. Windows forbids usernames to match the
    // computer name
    let stripped_name =
        if name.to_lowercase() == (env::var("COMPUTERNAME").unwrap().to_lowercase() + "$") {
            &name[..name.len() - 1]
        } else {
            name
        };
    let mut sid_size: u32 = 0;
    let mut domain_size: u32 = 0;
    let wide = WideCString::from_str(stripped_name).unwrap();
    unsafe {
        LookupAccountNameW(
            null_mut(),
            wide.as_ptr(),
            null_mut(),
            &mut sid_size as LPDWORD,
            null_mut(),
            &mut domain_size as LPDWORD,
            null_mut(),
        )
    };
    match Error::last_os_error().raw_os_error().unwrap() as u32 {
        ERROR_INSUFFICIENT_BUFFER => {}
        ERROR_NONE_MAPPED => return None,
        _ => panic!(
            "Error while looking up account for {}: {}",
            name,
            Error::last_os_error()
        ),
    }

    let mut sid: Vec<u8> = Vec::with_capacity(sid_size as usize);
    let mut domain: Vec<u16> = Vec::with_capacity(domain_size as usize);
    let mut sid_type = SID_NAME_USE(0);

    let ret = unsafe {
        LookupAccountNameW(
            null_mut(),
            wide.as_ptr(),
            sid.as_mut_ptr() as PSID,
            &mut sid_size as LPDWORD,
            domain.as_mut_ptr(),
            &mut domain_size as LPDWORD,
            &mut sid_type as PSID_NAME_USE,
        )
    };
    if ret == 0 {
        panic!(
            "Failed to retrieve SID for {}: {}",
            name,
            Error::last_os_error()
        );
    }
    unsafe {
        domain.set_len(domain_size as usize);
        sid.set_len(sid_size as usize);
    }
    let domain_str = WideCString::from_vec(domain).unwrap().to_string_lossy();
    Some(Account {
        name: name.to_string(),
        system_name: system_name,
        domain: domain_str,
        account_type: sid_type,
        sid: Sid { raw: sid },
    })
}

#[cfg(test)]
mod tests {
    use std::env;

    use winapi::winnt::{SidTypeUser, SidTypeWellKnownGroup};

    use super::*;

    #[test]
    fn real_account_returns_some() {
        assert_eq!(Account::from_name("Administrator").is_some(), true)
    }

    #[test]
    fn bogus_account_returns_none() {
        assert_eq!(Account::from_name("bogus").is_none(), true)
    }

    #[test]
    fn user_account_returns_user_type() {
        let acct_type = Account::from_name("Administrator").unwrap().account_type;
        assert_eq!(acct_type, SidTypeUser)
    }

    #[test]
    fn local_user_account_returns_local_machine_as_domain() {
        let acct_domain = Account::from_name("Administrator").unwrap().domain;
        assert_eq!(acct_domain, env::var("COMPUTERNAME").unwrap())
    }

    #[test]
    fn well_known_group_account_returns_correct_type() {
        let acct_type = Account::from_name("Everyone").unwrap().account_type;
        assert_eq!(acct_type, SidTypeWellKnownGroup)
    }

    #[test]
    fn well_known_group_account_has_well_known_sid() {
        let sid = Account::from_name("Everyone").unwrap().sid;
        assert_eq!(sid.to_string().unwrap(), "S-1-1-0")
    }

    #[test]
    fn mixing_case_returns_same_account() {
        let current_user = env::var("USERNAME").unwrap();
        let lower_sid = Account::from_name(current_user.to_lowercase().as_str())
            .unwrap()
            .sid;
        let upper_sid = Account::from_name(current_user.to_uppercase().as_str())
            .unwrap()
            .sid;
        assert_eq!(
            lower_sid.to_string().unwrap(),
            upper_sid.to_string().unwrap()
        )
    }

    #[test]
    fn machine_account_returns_some() {
        assert_eq!(
            Account::from_name((env::var("COMPUTERNAME").unwrap() + "$").as_str()).is_some(),
            true
        )
    }
}
<|endoftext|>


<commit_before>use super::simplex_vertex::SimplexVertex;
use super::super::common::math::vec_distance;
use super::super::common::Vec2;

pub struct Simplex {
    pub m_v1: SimplexVertex,
    pub m_v2: SimplexVertex,
    pub m_v3: SimplexVertex,
    pub m_count: i32
}

impl Simplex {
    // TODO implement
    // pub fn read_cache()

    // TODO implement
    // pub fn write_cache()

    pub fn get_search_direction(&self) -> Vec2 {
        match self.m_count {
            1 => {
                return -self.m_v1.w;
            },
            2 => {
                let e12 = self.m_v2.w - self.m_v1.w;
                let sgn = Vec2::cross_vec(e12, -self.m_v1.w);
                if sgn > 0.0 {
                    // Origin is left of e12.
                    return Vec2::cross_scalar_vec(1.0, e12);
                } else {
                    // Origin is right of e12.
					return Vec2::cross_vec_scalar(e12, 1.0);
                }
            },
            _ => {
                assert!(false);
                return Vec2::zero();
            }
        }
    }

    pub fn get_closest_point(&self) -> Vec2 {
        match self.m_count {
            0 => {
                assert!(false);
                return Vec2::zero();
            },
            1 => {
                return self.m_v1.w;
            },
            2 => {
                return self.m_v1.a * self.m_v1.w + self.m_v2.a * self.m_v2.w;
            },
            3 => {
                return Vec2::zero();
            },
            _ => {
                assert!(false);
                return Vec2::zero();
            }
        }
    }

    pub fn get_witness_points(&self) -> (Vec2, Vec2) {
        match self.m_count {
            0 => {
                assert!(false);
                return (Vec2::zero(), Vec2::zero());
            },
            1 => {
                return (self.m_v1.w_a, self.m_v1.w_b);
            },
            2 => {
                return (self.m_v1.a * self.m_v1.w_a + self.m_v2.a * self.m_v2.w_a,
                    self.m_v1.a * self.m_v1.w_b + self.m_v2.a * self.m_v2.w_b)
            },
            3 => {
                let p_a = self.m_v1.a * self.m_v1.w_a + self.m_v2.a * self.m_v2.w_a + self.m_v3.a * self.m_v3.w_a;
                return (p_a, p_a)
            },
            _ => {
                assert!(false);
                return (Vec2::zero(), Vec2::zero());
            }
        }
    }

    pub fn get_metric(&self) -> f32 {
        match self.m_count {
            0 => {
                assert!(false);
                return 0.0;
            },
            1 => 0.0,
            2 => {
                return vec_distance(self.m_v1.w, self.m_v2.w);
            },
            3 => {
                return Vec2::cross_vec(self.m_v2.w - self.m_v1.w, self.m_v3.w - self.m_v1.w);
            },
            _ => {
                assert!(false);
                return 0.0;
            }
        }
    }

    pub fn solve_2(&mut self) {
        let w1 = self.m_v1.w;
        let w2 = self.m_v2.w;
        let e12 = w2 - w1;

        // w1 region
        let d12_2 = - Vec2::dot(w1, e12);
        if d12_2 <= 0.0 {
            // a2 <= 0, so we clamp it to 0
            self.m_v1.a = 1.0;
            self.m_count = 1;
            return;
        }

        // w2 region
        let d12_1 = Vec2::dot(w2, e12);
        if d12_1 <= 0.0 {
            // a1 <= 0, so we clamp it to 0
            self.m_v1.a = 1.0;
            self.m_count = 1;
            self.m_v1 = self.m_v2.clone();
            return;
        }

        let inv_d12 = 1.0 / (d12_1 + d12_2);
        self.m_v1.a = d12_1 * inv_d12;
        self.m_v2.a = d12_2 * inv_d12;
        self.m_count = 2;
    }

    // TODO implement
    pub fn solve_3() {

    }
}
<commit_msg>Adding comment for solve2 simplex methods<commit_after>use super::simplex_vertex::SimplexVertex;
use super::super::common::math::vec_distance;
use super::super::common::Vec2;

pub struct Simplex {
    pub m_v1: SimplexVertex,
    pub m_v2: SimplexVertex,
    pub m_v3: SimplexVertex,
    pub m_count: i32
}

impl Simplex {
    // TODO implement
    // pub fn read_cache()

    // TODO implement
    // pub fn write_cache()

    pub fn get_search_direction(&self) -> Vec2 {
        match self.m_count {
            1 => {
                return -self.m_v1.w;
            },
            2 => {
                let e12 = self.m_v2.w - self.m_v1.w;
                let sgn = Vec2::cross_vec(e12, -self.m_v1.w);
                if sgn > 0.0 {
                    // Origin is left of e12.
                    return Vec2::cross_scalar_vec(1.0, e12);
                } else {
                    // Origin is right of e12.
					return Vec2::cross_vec_scalar(e12, 1.0);
                }
            },
            _ => {
                assert!(false);
                return Vec2::zero();
            }
        }
    }

    pub fn get_closest_point(&self) -> Vec2 {
        match self.m_count {
            0 => {
                assert!(false);
                return Vec2::zero();
            },
            1 => {
                return self.m_v1.w;
            },
            2 => {
                return self.m_v1.a * self.m_v1.w + self.m_v2.a * self.m_v2.w;
            },
            3 => {
                return Vec2::zero();
            },
            _ => {
                assert!(false);
                return Vec2::zero();
            }
        }
    }

    pub fn get_witness_points(&self) -> (Vec2, Vec2) {
        match self.m_count {
            0 => {
                assert!(false);
                return (Vec2::zero(), Vec2::zero());
            },
            1 => {
                return (self.m_v1.w_a, self.m_v1.w_b);
            },
            2 => {
                return (self.m_v1.a * self.m_v1.w_a + self.m_v2.a * self.m_v2.w_a,
                    self.m_v1.a * self.m_v1.w_b + self.m_v2.a * self.m_v2.w_b)
            },
            3 => {
                let p_a = self.m_v1.a * self.m_v1.w_a + self.m_v2.a * self.m_v2.w_a + self.m_v3.a * self.m_v3.w_a;
                return (p_a, p_a)
            },
            _ => {
                assert!(false);
                return (Vec2::zero(), Vec2::zero());
            }
        }
    }

    pub fn get_metric(&self) -> f32 {
        match self.m_count {
            0 => {
                assert!(false);
                return 0.0;
            },
            1 => 0.0,
            2 => {
                return vec_distance(self.m_v1.w, self.m_v2.w);
            },
            3 => {
                return Vec2::cross_vec(self.m_v2.w - self.m_v1.w, self.m_v3.w - self.m_v1.w);
            },
            _ => {
                assert!(false);
                return 0.0;
            }
        }
    }

    // Solve a line segment using barycentric coordinates.
    //
    // p = a1 * w1 + a2 * w2
    // a1 + a2 = 1
    //
    // The vector from the origin to the closest point on the line is
    // perpendicular to the line.
    // e12 = w2 - w1
    // dot(p, e) = 0
    // a1 * dot(w1, e) + a2 * dot(w2, e) = 0
    //
    // 2-by-2 linear system
    // [1      1     ][a1] = [1]
    // [w1.e12 w2.e12][a2] = [0]
    //
    // Define
    // d12_1 =  dot(w2, e12)
    // d12_2 = -dot(w1, e12)
    // d12 = d12_1 + d12_2
    //
    // Solution
    // a1 = d12_1 / d12
    // a2 = d12_2 / d12
    pub fn solve_2(&mut self) {
        let w1 = self.m_v1.w;
        let w2 = self.m_v2.w;
        let e12 = w2 - w1;

        // w1 region
        let d12_2 = - Vec2::dot(w1, e12);
        if d12_2 <= 0.0 {
            // a2 <= 0, so we clamp it to 0
            self.m_v1.a = 1.0;
            self.m_count = 1;
            return;
        }

        // w2 region
        let d12_1 = Vec2::dot(w2, e12);
        if d12_1 <= 0.0 {
            // a1 <= 0, so we clamp it to 0
            self.m_v1.a = 1.0;
            self.m_count = 1;
            self.m_v1 = self.m_v2.clone();
            return;
        }

        let inv_d12 = 1.0 / (d12_1 + d12_2);
        self.m_v1.a = d12_1 * inv_d12;
        self.m_v2.a = d12_2 * inv_d12;
        self.m_count = 2;
    }

    // TODO implement
    pub fn solve_3() {

    }
}
<|endoftext|>