<commit_before>extern crate centralgithook;
extern crate git2;
extern crate clap;

use std::env;
use std::process::exit;
use std::path::Path;
use std::path::PathBuf;
use centralgithook::migrate;
use centralgithook::migrate::RepoHost;
use centralgithook::migrate::ReviewUploadResult;

const GERRIT_PORT: &'static str = "29418";
const AUTOMATION_USER: &'static str = "automation";
// const MODULE_PATH_PREFIX: &'static str = "bsw";
const CENTRAL_NAME: &'static str = "central";

struct Gerrit
{
    path: PathBuf,
}

impl Gerrit
{
    pub fn new() -> Self
    {
        let git_dir = env::var("GIT_DIR").expect("GIT_DIR not set");
        let mut p = Path::new(&git_dir);
        while !p.join("bin").join("gerrit.sh").exists() {
            p = p.parent().expect("can't find gerrit root");
        }

        Gerrit { path: p.to_path_buf() }
    }
}

impl migrate::RepoHost for Gerrit
{
    fn fetch_url(&self, module_path: &str) -> String
    {
        if let Some(root) = self.path.as_os_str().to_str() {
            format!("{}/git/{}.git", root, module_path)
        }
        else {
            self.remote_url(module_path)
        }
    }

    fn remote_url(&self, module_path: &str) -> String
    {
        format!("ssh://{}@gerrit-test-git:{}/{}",
                AUTOMATION_USER,
                GERRIT_PORT,
                module_path)
    }

    fn projects(&self) -> Vec<String>
    {
        let path = self.path.join("git");
        migrate::find_repos(&path, &path, vec![])
    }

    fn central(&self) -> &str
    {
        "central"
    }
}

fn main()
{
    exit(main_ret());
}

fn main_ret() -> i32
{

    let args = clap::App::new("centralgithook")
        .arg(clap::Arg::with_name("branch").long("branch").takes_value(true))
        .arg(clap::Arg::with_name("change").long("change").takes_value(true))
        .arg(clap::Arg::with_name("change-owner").long("change-owner").takes_value(true))
        .arg(clap::Arg::with_name("change-url").long("change-url").takes_value(true))
        .arg(clap::Arg::with_name("commit").long("commit").takes_value(true))
        .arg(clap::Arg::with_name("head").long("head").takes_value(true))
        .arg(clap::Arg::with_name("newrev").long("newrev").takes_value(true))
        .arg(clap::Arg::with_name("oldrev").long("oldrev").takes_value(true))
        .arg(clap::Arg::with_name("project").long("project").takes_value(true))
        .arg(clap::Arg::with_name("refname").long("refname").takes_value(true))
        .arg(clap::Arg::with_name("submitter").long("submitter").takes_value(true))
        .arg(clap::Arg::with_name("topic").long("topic").takes_value(true))
        .arg(clap::Arg::with_name("uploader").long("uploader").takes_value(true))
        .get_matches();

    let commit = args.value_of("commit").unwrap_or("");
    let newrev = args.value_of("newrev").unwrap_or("");
    let oldrev = args.value_of("oldrev").unwrap_or("");
    let project = args.value_of("project").unwrap_or("");
    let refname = args.value_of("refname").unwrap_or("");

    let gerrit = Gerrit::new();

    if let Some(hook) = env::args().nth(0) {

        // ref-update: fired after push
        // change-merged: fired after gerrit-submit
        let is_update = hook.ends_with("ref-update");
        let is_submit = hook.ends_with("change-merged");
        let is_project_created = hook.ends_with("project-created");

        let is_review = is_update && refname == "refs/for/master";
        let is_module = project != CENTRAL_NAME;
        let is_initial = oldrev == "0000000000000000000000000000000000000000";

        let uploader = args.value_of("uploader").unwrap_or("");
        if !is_initial && is_update && !is_review && !uploader.contains("Automation") {
            println!("==== uploader: {}", uploader);
            println!("==== only push to refs/for/master");
            return 1;
        }

        let scratch_dir = gerrit.path.join("centralgithook_scratch");
        let scratch = migrate::Scratch::new(&scratch_dir, &gerrit);
        if is_submit {
            // submit to central
            migrate::central_submit(&scratch, scratch.transfer(commit, &Path::new(".")));
        }
        else if is_project_created {
            migrate::project_created(&scratch);
            println!("==== project_created");
        }
        else if is_review {
            // module was pushed, get changes to central
            match migrate::review_upload(&scratch,
                                         scratch.transfer(newrev, Path::new(".")),
                                         project) {
                ReviewUploadResult::RejectNoFF => {
                    println!(".");
                    println!("===================================================================");
                    println!("=========== Commit not based on master, rebase first! =============");
                    println!("===================================================================");
                }
                ReviewUploadResult::NoChanges => {}
                ReviewUploadResult::RejectMerge => {
                    println!(".");
                    println!("===================================================================");
                    println!("=================== Do not submit merge commits! ==================");
                    println!("===================================================================");
                }
                ReviewUploadResult::Uploaded(oid) => {
                    println!("================ Doing actual upload in central git ===============");

                    println!("{}", scratch.push(oid, gerrit.central(), "refs/for/master"));
                    println!("==== The review upload may have worked, even if it says error \
                              below. Look UP! ====")
                }
                ReviewUploadResult::Central => return 0,
            }

            // stop gerrit from allowing push to module directly
            return 1;
        }
        else if !is_module && is_update && !is_review {
            // direct push to master-branch of central
            if is_initial {
                println!(".\n\n##### INITIAL IMPORT ######");
                migrate::central_submit(&scratch, scratch.transfer(newrev, &Path::new(".")));
                return 0;
            }
            else {
                println!(".\n\n###########################################");
                println!("##### INITIAL IMPORT already happened #####");
                println!("###########################################");
                return 1;
            }
        }
    }
    return 0;
}
<commit_msg>support gerrit prefix<commit_after>extern crate centralgithook;
extern crate git2;
extern crate clap;
extern crate env_logger;

use std::env;
use std::process::exit;
use std::path::Path;
use std::path::PathBuf;
use centralgithook::migrate;
use centralgithook::migrate::RepoHost;
use centralgithook::migrate::ReviewUploadResult;

const GERRIT_PORT: &'static str = "29418";
const AUTOMATION_USER: &'static str = "automation";
const CENTRAL_NAME: &'static str = "central";

struct Gerrit
{
    path: PathBuf,
    prefix: String,
}

impl Gerrit
{
    pub fn new() -> Self
    {
        let git_dir = env::var("GIT_DIR").expect("GIT_DIR not set");
        let mut p = Path::new(&git_dir);
        while !p.join(&format!("{}.git",CENTRAL_NAME)).exists() {
            p = p.parent().expect("can't find gerrit git root");
        }

        let root = p.to_path_buf();

        while !p.join("bin").join("gerrit.sh").exists() {
            p = p.parent().expect("can't find gerrit root");
        }

        let path = p.to_path_buf();
        let p = p.join("git");

        println!("Gerrit path: {:?}", path);
        println!("Gerrit root: {:?}", root);
        println!("Gerrit p: {:?}", p);

        let prefix = root.strip_prefix(&p).unwrap().to_path_buf();

        println!("Gerrit prefix: {:?}", prefix);

        Gerrit { path: path, prefix: format!("{}/",prefix.as_os_str().to_str().unwrap()) }
    }

}

impl migrate::RepoHost for Gerrit
{
    fn fetch_url(&self, module_path: &str) -> String
    {
        if let Some(root) = self.path.as_os_str().to_str() {
            format!("{}/git/{}{}.git", root, self.prefix, module_path)
        }
        else {
            self.remote_url(module_path)
        }
    }

    fn remote_url(&self, module_path: &str) -> String
    {
        format!("ssh://{}@gerrit-test-git:{}/{}{}.git",
                AUTOMATION_USER,
                GERRIT_PORT,
                self.prefix,
                module_path)
    }

    fn projects(&self) -> Vec<String>
    {
        let path = self.path.join("git").join(&self.prefix);
        migrate::find_repos(&path, &path, vec![])
    }

    fn central(&self) -> &str
    {
        CENTRAL_NAME
    }
}

fn main()
{
    ::std::env::set_var("RUST_LOG","centralgithook=debug");
    env_logger::init().expect("can't init logger");
    exit(main_ret());
}

fn main_ret() -> i32
{

    let args = clap::App::new("centralgithook")
        .arg(clap::Arg::with_name("branch").long("branch").takes_value(true))
        .arg(clap::Arg::with_name("change").long("change").takes_value(true))
        .arg(clap::Arg::with_name("change-owner").long("change-owner").takes_value(true))
        .arg(clap::Arg::with_name("change-url").long("change-url").takes_value(true))
        .arg(clap::Arg::with_name("commit").long("commit").takes_value(true))
        .arg(clap::Arg::with_name("head").long("head").takes_value(true))
        .arg(clap::Arg::with_name("newrev").long("newrev").takes_value(true))
        .arg(clap::Arg::with_name("oldrev").long("oldrev").takes_value(true))
        .arg(clap::Arg::with_name("project").long("project").takes_value(true))
        .arg(clap::Arg::with_name("refname").long("refname").takes_value(true))
        .arg(clap::Arg::with_name("submitter").long("submitter").takes_value(true))
        .arg(clap::Arg::with_name("topic").long("topic").takes_value(true))
        .arg(clap::Arg::with_name("uploader").long("uploader").takes_value(true))
        .get_matches();

    let commit = args.value_of("commit").unwrap_or("");
    let newrev = args.value_of("newrev").unwrap_or("");
    let oldrev = args.value_of("oldrev").unwrap_or("");
    let project = args.value_of("project").unwrap_or("");
    let refname = args.value_of("refname").unwrap_or("");

    let gerrit = Gerrit::new();

    let (_, project) = project.split_at(gerrit.prefix.len());
    println!("PJECT: {}", project);

    if let Some(hook) = env::args().nth(0) {

        // ref-update: fired after push
        // change-merged: fired after gerrit-submit
        let is_update = hook.ends_with("ref-update");
        let is_submit = hook.ends_with("change-merged");
        let is_project_created = hook.ends_with("project-created");

        let is_review = is_update && refname == "refs/for/master";
        let is_module = project != format!("{}{}", gerrit.prefix, gerrit.central());
        let is_initial = !is_module && oldrev == "0000000000000000000000000000000000000000";

        let uploader = args.value_of("uploader").unwrap_or("");
        if is_update && !is_review && !uploader.contains("Automation") {
            println!(".");
            // debug!("==== uploader: {}", uploader);
            println!("===================================================================");
            println!("================= Do not push directly to master! =================");
            println!("===================================================================");
            return 1;
        }

        let scratch_dir = gerrit.path.join("centralgithook_scratch");
        let scratch = migrate::Scratch::new(&scratch_dir, &gerrit);
        if is_submit {
            // submit to central
            migrate::central_submit(&scratch, scratch.transfer(commit, &Path::new(".")));
        }
        else if is_project_created {
            migrate::project_created(&scratch);
            println!("==== project_created");
        }
        else if is_review {
            // module was pushed, get changes to central
            match migrate::review_upload(&scratch,
                                         scratch.transfer(newrev, Path::new(".")),
                                         project) {
                ReviewUploadResult::RejectNoFF => {
                    println!(".");
                    println!("===================================================================");
                    println!("=========== Commit not based on master, rebase first! =============");
                    println!("===================================================================");
                }
                ReviewUploadResult::NoChanges => {}
                ReviewUploadResult::RejectMerge => {
                    println!(".");
                    println!("===================================================================");
                    println!("=================== Do not submit merge commits! ==================");
                    println!("===================================================================");
                }
                ReviewUploadResult::Uploaded(oid) => {
                    println!("================ Doing actual upload in central git ===============");

                    println!("{}", scratch.push(oid, gerrit.central(), "refs/for/master"));
                    println!("==== The review upload may have worked, even if it says error \
                              below. Look UP! ====")
                }
                ReviewUploadResult::Central => return 0,
            }

            // stop gerrit from allowing push to module directly
            return 1;
        }
        else if !is_module && is_update && !is_review {
            // direct push to master-branch of central
            if is_initial {
                println!(".\n\n##### INITIAL IMPORT ######");
                migrate::central_submit(&scratch, scratch.transfer(newrev, &Path::new(".")));
                return 0;
            }
            else {
                println!(".\n\n###########################################");
                println!("##### INITIAL IMPORT already happened #####");
                println!("###########################################");
                return 1;
            }
        }
    }
    return 0;
}
<|endoftext|>


<commit_before>extern crate compiletest_rs as compiletest;

use std::path::{PathBuf, Path};
use std::io::Write;

fn compile_fail(sysroot: &str) {
    let flags = format!("--sysroot {} -Dwarnings", sysroot);
    for_all_targets(sysroot, |target| {
        let mut config = compiletest::default_config();
        config.host_rustcflags = Some(flags.clone());
        config.mode = "compile-fail".parse().expect("Invalid mode");
        config.run_lib_path = Path::new(sysroot).join("lib").join("rustlib").join(&target).join("lib");
        config.rustc_path = "target/debug/miri".into();
        config.src_base = PathBuf::from("tests/compile-fail".to_string());
        config.target = target.to_owned();
        config.target_rustcflags = Some(flags.clone());
        compiletest::run_tests(&config);
    });
}

fn run_pass() {
    let mut config = compiletest::default_config();
    config.mode = "run-pass".parse().expect("Invalid mode");
    config.src_base = PathBuf::from("tests/run-pass".to_string());
    config.target_rustcflags = Some("-Dwarnings".to_string());
    config.host_rustcflags = Some("-Dwarnings".to_string());
    compiletest::run_tests(&config);
}

fn miri_pass(path: &str, target: &str, host: &str) {
    let mut config = compiletest::default_config();
    config.mode = "mir-opt".parse().expect("Invalid mode");
    config.src_base = PathBuf::from(path);
    config.target = target.to_owned();
    config.rustc_path = PathBuf::from("target/debug/miri");
    // don't actually execute the final binary, it might be for other targets and we only care
    // about running miri, not the binary.
    config.runtool = Some("echo \"\" || ".to_owned());
    if target == host {
        std::env::set_var("MIRI_HOST_TARGET", "yes");
    }
    compiletest::run_tests(&config);
    std::env::set_var("MIRI_HOST_TARGET", "");
}

fn is_target_dir<P: Into<PathBuf>>(path: P) -> bool {
    let mut path = path.into();
    path.push("lib");
    path.metadata().map(|m| m.is_dir()).unwrap_or(false)
}

fn for_all_targets<F: FnMut(String)>(sysroot: &str, mut f: F) {
    for entry in std::fs::read_dir(format!("{}/lib/rustlib/", sysroot)).unwrap() {
        let entry = entry.unwrap();
        if !is_target_dir(entry.path()) { continue; }
        let target = entry.file_name().into_string().unwrap();
        let stderr = std::io::stderr();
        writeln!(stderr.lock(), "running tests for target {}", target).unwrap();
        f(target);
    }
}

#[test]
fn compile_test() {
    // Taken from https://github.com/Manishearth/rust-clippy/pull/911.
    let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
    let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
    let sysroot = match (home, toolchain) {
        (Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain),
        _ => option_env!("RUST_SYSROOT")
            .expect("need to specify RUST_SYSROOT env var or use rustup or multirust")
            .to_owned(),
    };
    run_pass();
    let host = Path::new(&sysroot).file_name()
                                  .unwrap()
                                  .to_str()
                                  .unwrap()
                                  .splitn(2, '-')
                                  .skip(1)
                                  .next()
                                  .unwrap();
    for_all_targets(&sysroot, |target| {
        miri_pass("tests/run-pass", &target, host);
        if let Ok(path) = std::env::var("MIRI_RUSTC_TEST") {
            miri_pass(&path, &target, host);
        }
    });
    compile_fail(&sysroot);
}
<commit_msg>try to pin down the travis failure<commit_after>extern crate compiletest_rs as compiletest;

use std::path::{PathBuf, Path};
use std::io::Write;

fn compile_fail(sysroot: &str) {
    let flags = format!("--sysroot {} -Dwarnings", sysroot);
    for_all_targets(sysroot, |target| {
        let mut config = compiletest::default_config();
        config.host_rustcflags = Some(flags.clone());
        config.mode = "compile-fail".parse().expect("Invalid mode");
        config.run_lib_path = Path::new(sysroot).join("lib").join("rustlib").join(&target).join("lib");
        config.rustc_path = "target/debug/miri".into();
        config.src_base = PathBuf::from("tests/compile-fail".to_string());
        config.target = target.to_owned();
        config.target_rustcflags = Some(flags.clone());
        compiletest::run_tests(&config);
    });
}

fn run_pass() {
    let mut config = compiletest::default_config();
    config.mode = "run-pass".parse().expect("Invalid mode");
    config.src_base = PathBuf::from("tests/run-pass".to_string());
    config.target_rustcflags = Some("-Dwarnings".to_string());
    config.host_rustcflags = Some("-Dwarnings".to_string());
    compiletest::run_tests(&config);
}

fn miri_pass(path: &str, target: &str, host: &str) {
    let mut config = compiletest::default_config();
    config.mode = "mir-opt".parse().expect("Invalid mode");
    config.src_base = PathBuf::from(path);
    config.target = target.to_owned();
    config.rustc_path = PathBuf::from("target/debug/miri");
    // don't actually execute the final binary, it might be for other targets and we only care
    // about running miri, not the binary.
    config.runtool = Some("echo \"\" || ".to_owned());
    if target == host {
        std::env::set_var("MIRI_HOST_TARGET", "yes");
    }
    compiletest::run_tests(&config);
    std::env::set_var("MIRI_HOST_TARGET", "");
}

fn is_target_dir<P: Into<PathBuf>>(path: P) -> bool {
    let mut path = path.into();
    path.push("lib");
    path.metadata().map(|m| m.is_dir()).unwrap_or(false)
}

fn for_all_targets<F: FnMut(String)>(sysroot: &str, mut f: F) {
    for entry in std::fs::read_dir(format!("{}/lib/rustlib/", sysroot)).unwrap() {
        let entry = entry.unwrap();
        if !is_target_dir(entry.path()) { continue; }
        let target = entry.file_name().into_string().unwrap();
        let stderr = std::io::stderr();
        writeln!(stderr.lock(), "running tests for target {}", target).unwrap();
        f(target);
    }
}

#[test]
fn compile_test() {
    // Taken from https://github.com/Manishearth/rust-clippy/pull/911.
    let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
    let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
    let sysroot = match (home, toolchain) {
        (Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain),
        _ => option_env!("RUST_SYSROOT")
            .expect("need to specify RUST_SYSROOT env var or use rustup or multirust")
            .to_owned(),
    };
    run_pass();
    let host = Path::new(&sysroot).file_name()
                                  .expect("sysroot has no last par")
                                  .to_str()
                                  .expect("sysroot contains non utf8")
                                  .splitn(2, '-')
                                  .skip(1)
                                  .next()
                                  .expect("target dir not prefixed");
    for_all_targets(&sysroot, |target| {
        miri_pass("tests/run-pass", &target, host);
        if let Ok(path) = std::env::var("MIRI_RUSTC_TEST") {
            miri_pass(&path, &target, host);
        }
    });
    compile_fail(&sysroot);
}
<|endoftext|>


<commit_before>#![feature(question_mark)]

#[macro_use(message)]
extern crate exonum;

use exonum::crypto::PublicKey;
use exonum::storage::{Blockchain, LevelDB, Database, Fork};

pub const TIMESTAMPING_TRANSACTION_MESSAGE_ID : u16 = 128;

message! {
    TimestampTx {
        const ID = TIMESTAMPING_TRANSACTION_MESSAGE_ID;
        const SIZE = 40;

        pub_key:        &PublicKey  [00 => 32]
        data:           &[u8]       [32 => 40]
    }
}

pub struct TimestampingBlockchain<D: Database> {
    pub db: D
}

impl<D> Blockchain for TimestampingBlockchain<D> where D: Database {
    type Database = D;
    type Transaction = TimestampTx;

    fn db(&self) -> &Self::Database {
        &self.db
    }

    fn db_mut(&mut self) -> &mut Self::Database {
        &mut self.db
    }
}
<commit_msg>Remove warnings<commit_after>#![feature(question_mark)]

#[macro_use(message)]
extern crate exonum;

use exonum::crypto::PublicKey;
use exonum::storage::{Blockchain, Database};

pub const TIMESTAMPING_TRANSACTION_MESSAGE_ID : u16 = 128;

message! {
    TimestampTx {
        const ID = TIMESTAMPING_TRANSACTION_MESSAGE_ID;
        const SIZE = 40;

        pub_key:        &PublicKey  [00 => 32]
        data:           &[u8]       [32 => 40]
    }
}

pub struct TimestampingBlockchain<D: Database> {
    pub db: D
}

impl<D> Blockchain for TimestampingBlockchain<D> where D: Database {
    type Database = D;
    type Transaction = TimestampTx;

    fn db(&self) -> &Self::Database {
        &self.db
    }

    fn db_mut(&mut self) -> &mut Self::Database {
        &mut self.db
    }
}
<|endoftext|>


<commit_before>// ignore-windows: File handling is not implemented yet
// compile-flags: -Zmiri-disable-isolation

use std::fs::{File, remove_file};
use std::io::{Read, Write};

fn main() {
    let path = "miri_test_fs.txt";
    let bytes = b"Hello, World!\n";
    // Test creating, writing and closing a file (closing is tested when `file` is dropped).
    let mut file = File::create(path).unwrap();
    // Writing 0 bytes should not change the file contents.
    file.write(&mut []).unwrap();

    file.write(bytes).unwrap();
    // Test opening, reading and closing a file.
    let mut file = File::open(path).unwrap();
    let mut contents = Vec::new();
    // Reading 0 bytes should not move the file pointer.
    file.read(&mut []).unwrap();
    // Reading until EOF should get the whole text.
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());
    // Removing file should succeed
    remove_file(path).unwrap();
    // Opening non-existing file should fail
    assert!(File::open(path).is_err());
    // Removing non-existing file should fail
    assert!(remove_file(path).is_err());
}
<commit_msg>use temp_dir for FS test<commit_after>// ignore-windows: File handling is not implemented yet
// compile-flags: -Zmiri-disable-isolation

use std::fs::{File, remove_file};
use std::io::{Read, Write};

fn main() {
    let path = std::env::temp_dir().join("miri_test_fs.txt");
    let bytes = b"Hello, World!\n";
    // Test creating, writing and closing a file (closing is tested when `file` is dropped).
    let mut file = File::create(&path).unwrap();
    // Writing 0 bytes should not change the file contents.
    file.write(&mut []).unwrap();

    file.write(bytes).unwrap();
    // Test opening, reading and closing a file.
    let mut file = File::open(&path).unwrap();
    let mut contents = Vec::new();
    // Reading 0 bytes should not move the file pointer.
    file.read(&mut []).unwrap();
    // Reading until EOF should get the whole text.
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());
    // Removing file should succeed
    remove_file(&path).unwrap();
    // Opening non-existing file should fail
    assert!(File::open(&path).is_err());
    // Removing non-existing file should fail
    assert!(remove_file(&path).is_err());
}
<|endoftext|>


<commit_before>use clap::{App, Arg};

#[derive(Default)]
pub struct Options {
    pub target: String,
    pub no_css: bool,
    pub no_fonts: bool,
    pub no_frames: bool,
    pub no_images: bool,
    pub no_js: bool,
    pub insecure: bool,
    pub isolate: bool,
    pub output: String,
    pub silent: bool,
    pub timeout: u64,
    pub user_agent: String,
    pub no_metadata: bool,
}

const ASCII: &str = " \
 _____     ______________    __________      ___________________    ___
|     \\   /              \\  |          |    |                   |  |   |
|      \\_/       __       \\_|    __    |    |    ___     ___    |__|   |
|               |  |            |  |   |    |   |   |   |   |          |
|   |\\     /|   |__|    _       |__|   |____|   |   |   |   |    __    |
|   | \\___/ |          | \\                      |   |   |   |   |  |   |
|___|       |__________|  \\_____________________|   |___|   |___|  |___|
";
const DEFAULT_NETWORK_TIMEOUT: u64 = 120;
const DEFAULT_USER_AGENT: &str =
    "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:73.0) Gecko/20100101 Firefox/73.0";

impl Options {
    pub fn from_args() -> Options {
        let app = App::new(env!("CARGO_PKG_NAME"))
            .version(crate_version!())
            .author(crate_authors!("\n"))
            .about(format!("{}\n{}", ASCII, crate_description!()).as_str())
            .arg(
                Arg::with_name("target")
                    .required(true)
                    .takes_value(true)
                    .index(1)
                    .help("URL or file path"),
            )
            // .args_from_usage("-a, --no-audio 'Removes audio sources'")
            .args_from_usage("-c, --no-css 'Removes CSS'")
            .args_from_usage("-f, --no-frames 'Removes frames and iframes'")
            .args_from_usage("-F, --no-fonts 'Removes fonts'")
            .args_from_usage("-i, --no-images 'Removes images'")
            .args_from_usage("-I, --isolate 'Cuts off document from the Internet'")
            .args_from_usage("-j, --no-js 'Removes JavaScript'")
            .args_from_usage("-k, --insecure 'Allows invalid X.509 (TLS) certificates'")
            .args_from_usage("-M, --no-metadata 'Excludes metadata information from the document'")
            .args_from_usage("-o, --output=[document.html] 'Writes output to <file>'")
            .args_from_usage("-s, --silent 'Suppresses verbosity'")
            .args_from_usage("-t, --timeout=[60] 'Adjusts network request timeout'")
            .args_from_usage("-u, --user-agent=[Firefox] 'Sets custom User-Agent string'")
            // .args_from_usage("-v, --no-video 'Removes video sources'")
            .get_matches();
        let mut options: Options = Options::default();

        // Process the command
        options.target = app
            .value_of("target")
            .expect("please set target")
            .to_string();
        options.no_css = app.is_present("no-css");
        options.no_frames = app.is_present("no-frames");
        options.no_fonts = app.is_present("no-fonts");
        options.no_images = app.is_present("no-images");
        options.isolate = app.is_present("isolate");
        options.no_js = app.is_present("no-js");
        options.insecure = app.is_present("insecure");
        options.no_metadata = app.is_present("no-metadata");
        options.output = app.value_of("output").unwrap_or("").to_string();
        options.silent = app.is_present("silent");
        options.timeout = app
            .value_of("timeout")
            .unwrap_or(&DEFAULT_NETWORK_TIMEOUT.to_string())
            .parse::<u64>()
            .unwrap();
        options.user_agent = app
            .value_of("user-agent")
            .unwrap_or(DEFAULT_USER_AGENT)
            .to_string();

        options
    }
}
<commit_msg>update help message<commit_after>use clap::{App, Arg};

#[derive(Default)]
pub struct Options {
    pub target: String,
    pub no_css: bool,
    pub no_fonts: bool,
    pub no_frames: bool,
    pub no_images: bool,
    pub no_js: bool,
    pub insecure: bool,
    pub isolate: bool,
    pub output: String,
    pub silent: bool,
    pub timeout: u64,
    pub user_agent: String,
    pub no_metadata: bool,
}

const ASCII: &str = " \
 _____     ______________    __________      ___________________    ___
|     \\   /              \\  |          |    |                   |  |   |
|      \\_/       __       \\_|    __    |    |    ___     ___    |__|   |
|               |  |            |  |   |    |   |   |   |   |          |
|   |\\     /|   |__|    _       |__|   |____|   |   |   |   |    __    |
|   | \\___/ |          | \\                      |   |   |   |   |  |   |
|___|       |__________|  \\_____________________|   |___|   |___|  |___|
";
const DEFAULT_NETWORK_TIMEOUT: u64 = 120;
const DEFAULT_USER_AGENT: &str =
    "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:73.0) Gecko/20100101 Firefox/73.0";

impl Options {
    pub fn from_args() -> Options {
        let app = App::new(env!("CARGO_PKG_NAME"))
            .version(crate_version!())
            .author(crate_authors!("\n"))
            .about(format!("{}\n{}", ASCII, crate_description!()).as_str())
            .arg(
                Arg::with_name("target")
                    .required(true)
                    .takes_value(true)
                    .index(1)
                    .help("URL or file path"),
            )
            // .args_from_usage("-a, --no-audio 'Removes audio sources'")
            .args_from_usage("-c, --no-css 'Removes CSS'")
            .args_from_usage("-f, --no-frames 'Removes frames and iframes'")
            .args_from_usage("-F, --no-fonts 'Removes fonts'")
            .args_from_usage("-i, --no-images 'Removes images'")
            .args_from_usage("-I, --isolate 'Cuts off document from the Internet'")
            .args_from_usage("-j, --no-js 'Removes JavaScript'")
            .args_from_usage("-k, --insecure 'Allows invalid X.509 (TLS) certificates'")
            .args_from_usage("-M, --no-metadata 'Excludes metadata information from the document'")
            .args_from_usage("-o, --output=[document.html] 'Write output to <file>'")
            .args_from_usage("-s, --silent 'Suppresses verbosity'")
            .args_from_usage("-t, --timeout=[60] 'Adjust network request timeout'")
            .args_from_usage("-u, --user-agent=[Firefox] 'Set custom User-Agent string'")
            // .args_from_usage("-v, --no-video 'Removes video sources'")
            .get_matches();
        let mut options: Options = Options::default();

        // Process the command
        options.target = app
            .value_of("target")
            .expect("please set target")
            .to_string();
        options.no_css = app.is_present("no-css");
        options.no_frames = app.is_present("no-frames");
        options.no_fonts = app.is_present("no-fonts");
        options.no_images = app.is_present("no-images");
        options.isolate = app.is_present("isolate");
        options.no_js = app.is_present("no-js");
        options.insecure = app.is_present("insecure");
        options.no_metadata = app.is_present("no-metadata");
        options.output = app.value_of("output").unwrap_or("").to_string();
        options.silent = app.is_present("silent");
        options.timeout = app
            .value_of("timeout")
            .unwrap_or(&DEFAULT_NETWORK_TIMEOUT.to_string())
            .parse::<u64>()
            .unwrap();
        options.user_agent = app
            .value_of("user-agent")
            .unwrap_or(DEFAULT_USER_AGENT)
            .to_string();

        options
    }
}
<|endoftext|>


<commit_before>use std::cmp;

use self::ApplyResult::*;
use super::Leading::{self, Top, Bot};

#[derive(Copy, Clone)]
struct SPart(u64);

#[derive(Copy, Clone)]
pub struct SPair {
    a: SPart,
    b: SPart,
}

/// A variable length pair.
#[derive(Clone)]
pub struct VPair {
    data: Vec<u64>,
    /// Who is leading.
    leading: Leading,
    /// How many bits of the first block are shared.
    prefix: u8,
    /// How many bits of the last block are used.
    used: u8,
}

#[derive(Copy, Clone)]
struct VHead {
    data: u64,
    /// How many bits are shared
    prefix: u8,
    /// How many bits are used
    used: u8,
}

impl VPair {
    pub fn new() -> VPair {
        let mut v = Vec::with_capacity(1);
        v.push(0);

        VPair {
            data: v,
            prefix: 0,
            used: 0,
            leading: Top,
        }
    }

    pub fn is_complete(&self) -> bool {
        self.data.len() == 1 && self.used == 0
    }

    pub fn apply(&self, p: &SPair) -> Option<VPair> {
        let (mut lead, mut follow) = match self.leading {
            Top => (p.a, p.b),
            Bot => (p.b, p.a),
        };

        let mut head = self.head();

        match head.apply(&mut follow, &mut lead) {
            Mismatch => None,
            Match => Some(self.with_offset_prefix_and_add_lead(0, head.prefix, lead)),
            LeadSwitch => Some(self.switched_with_new_lead(follow)),
            MatchRemaining => {
                let mut head2 = self.head2();

                match head2.apply(&mut follow, &mut lead) {
                    Mismatch => None,
                    Match => Some(self.with_offset_prefix_and_add_lead(1, head2.prefix, lead)),
                    LeadSwitch => Some(self.switched_with_new_lead(follow)),
                    MatchRemaining => unreachable!("SPairs contain at most 56 bit, which always fit in 64 bit"),
                }
            }
        }
    }

    fn with_offset_prefix_and_add_lead(&self, offset: usize, prefix: u8, lead: SPart) -> VPair {
        // Reserve an additional block in case apply_lead spills over
        let mut v = Vec::with_capacity(self.data.len() + 1 - offset);
        v.push_all(&self.data[offset..]);

        let mut p = VPair {
            data: v,
            prefix: prefix,
            used: self.used,
            leading: self.leading,
        };

        p.apply_lead(lead);

        p
    }

    fn switched_with_new_lead(&self, lead: SPart) -> VPair {
        let mut v = Vec::with_capacity(1);
        v.push(lead.data());

        VPair {
            data: v,
            prefix: 0,
            used: lead.len(),
            leading: self.leading.switched(),
        }
    }

    fn apply_lead(&mut self, mut lead: SPart) {
        let pushable;

        { // make the borrowchecker happy
            let last = self.data.last_mut().unwrap();

            // push all we can into the current byte
            pushable = cmp::min(64 - self.used, lead.len());
            *last |= lead.shift_data(pushable) << self.used;
        }

        let new_used = self.used + pushable;

        // if new_used is 64 need to open a new block
        if lead.len() == 0 && new_used < 64 {
            self.used = new_used;
        } else {
            self.data.push(lead.data());
            self.used = lead.len();
        }

        debug_assert!(self.used != 64);
    }

    fn head(&self) -> VHead {
        debug_assert!(self.used != 64);

        VHead {
            data: self.data[0],
            prefix: self.prefix,
            used: if self.data.len() > 1 { 64 } else { self.used },
        }
    }

    fn head2(&self) -> VHead {
        debug_assert!(self.data.len() > 1);

        VHead {
            data: self.data[1],
            prefix: 0,
            used: if self.data.len() > 2 { 64 } else { self. used },
        }
    }
}

enum ApplyResult {
    /// No match
    Mismatch,
    /// Completely matched, bits in lead need to be appended
    Match,
    /// Matched but end of block reached, repeat with second block
    MatchRemaining,
    /// Completely caught up, bits in follow make up a new block
    LeadSwitch,
}

impl SPart {
    fn data(&self) -> u64 {
        self.0 & 0x00FF_FFFF_FFFF_FFFF
    }

    fn len(&self) -> u8 {
        (self.0 >> 56) as u8
    }

    fn shift(&mut self, shift: u8) {
        let new_len = self.len() - shift;
        let new_val = self.data() >> shift;
        self.0 = ((new_len as u64) << 56) | new_val;
    }

    fn shift_data(&mut self, shift: u8) -> u64 {
        let data = self.0 & mask(shift);
        self.shift(shift);
        data
    }

    fn shift_prefix(a: &mut SPart, b: &mut SPart) {
        // after the xor the first mismatched bit is a one
        // theres no need for masking data since we need to use the min of the
        // lens and prefix anyway
        let prefix = (a.0 ^ b.0).trailing_zeros() as u8; // 0-64 always fit in an u8
        let prefix = cmp::min(prefix, cmp::min(a.len(), b.len()));
        a.shift(prefix);
        b.shift(prefix);
    }
}

impl VHead {
    fn apply(&mut self, follow: &mut SPart, lead: &mut SPart) -> ApplyResult {
        // fist, check that overlapping follows are equal
        let overlap = cmp::min(self.used - self.prefix, follow.len());

        // check
        let m = mask(overlap);
        let h = (self.data >> self.prefix) & m;
        let p = follow.data() & m;

        if h != p { return Mismatch; }

        // update
        self.prefix += overlap;
        follow.shift(overlap);

        // follow.len() == 0 implies self.prefix == self.used
        // debug_assert!(follow.len() != 0 || self.prefix == self.used)

        if self.prefix == 64 {
            debug_assert!(self.used == 64);
            return MatchRemaining; // Reached the end of block, needs to be removed
        }

        // at this point follow has caught up to lead, so we can eliminate any common prefix from follow and lead
        SPart::shift_prefix(follow, lead);

        match (follow.len() == 0, lead.len() == 0) {
            (_, true) => LeadSwitch, // lead is empty, start a new block with follow
            (false, false) => Mismatch, // both have non matching bits remaining
            (true, false) => Match, // follow is empty
        }
    }
}

/// Create a bitmask of which the lower `cnt` bits are set.
fn mask(cnt: u8) -> u64 {
    (1 << cnt) - 1
}

impl<'a> From<&'a str> for SPart {
    fn from(s: &'a str) -> SPart {
        let mut val = 0u64;
        let mut len = 0u64;

        for b in s.bytes().rev() {
            len += 1;
            val <<= 1;

            match b {
                b'0' => (),
                b'1' => val |= 1,
                _ => panic!("invalid input byte: {}", b),
            }
        }

        assert!(len <= 56, "invalid input: too long");

        SPart((len << 56) | val)
    }
}

impl<'a> From<(&'a str, &'a str)> for SPair {
    fn from((a, b): (&'a str, &'a str)) -> SPair {
        SPair {
            a: a.into(),
            b: b.into(),
        }
    }
}
<commit_msg>removed left over comment<commit_after>use std::cmp;

use self::ApplyResult::*;
use super::Leading::{self, Top, Bot};

#[derive(Copy, Clone)]
struct SPart(u64);

#[derive(Copy, Clone)]
pub struct SPair {
    a: SPart,
    b: SPart,
}

/// A variable length pair.
#[derive(Clone)]
pub struct VPair {
    data: Vec<u64>,
    /// Who is leading.
    leading: Leading,
    /// How many bits of the first block are shared.
    prefix: u8,
    /// How many bits of the last block are used.
    used: u8,
}

#[derive(Copy, Clone)]
struct VHead {
    data: u64,
    /// How many bits are shared
    prefix: u8,
    /// How many bits are used
    used: u8,
}

impl VPair {
    pub fn new() -> VPair {
        let mut v = Vec::with_capacity(1);
        v.push(0);

        VPair {
            data: v,
            prefix: 0,
            used: 0,
            leading: Top,
        }
    }

    pub fn is_complete(&self) -> bool {
        self.data.len() == 1 && self.used == 0
    }

    pub fn apply(&self, p: &SPair) -> Option<VPair> {
        let (mut lead, mut follow) = match self.leading {
            Top => (p.a, p.b),
            Bot => (p.b, p.a),
        };

        let mut head = self.head();

        match head.apply(&mut follow, &mut lead) {
            Mismatch => None,
            Match => Some(self.with_offset_prefix_and_add_lead(0, head.prefix, lead)),
            LeadSwitch => Some(self.switched_with_new_lead(follow)),
            MatchRemaining => {
                let mut head2 = self.head2();

                match head2.apply(&mut follow, &mut lead) {
                    Mismatch => None,
                    Match => Some(self.with_offset_prefix_and_add_lead(1, head2.prefix, lead)),
                    LeadSwitch => Some(self.switched_with_new_lead(follow)),
                    MatchRemaining => unreachable!("SPairs contain at most 56 bit, which always fit in 64 bit"),
                }
            }
        }
    }

    fn with_offset_prefix_and_add_lead(&self, offset: usize, prefix: u8, lead: SPart) -> VPair {
        // Reserve an additional block in case apply_lead spills over
        let mut v = Vec::with_capacity(self.data.len() + 1 - offset);
        v.push_all(&self.data[offset..]);

        let mut p = VPair {
            data: v,
            prefix: prefix,
            used: self.used,
            leading: self.leading,
        };

        p.apply_lead(lead);

        p
    }

    fn switched_with_new_lead(&self, lead: SPart) -> VPair {
        let mut v = Vec::with_capacity(1);
        v.push(lead.data());

        VPair {
            data: v,
            prefix: 0,
            used: lead.len(),
            leading: self.leading.switched(),
        }
    }

    fn apply_lead(&mut self, mut lead: SPart) {
        let pushable;

        { // make the borrowchecker happy
            let last = self.data.last_mut().unwrap();

            // push all we can into the current byte
            pushable = cmp::min(64 - self.used, lead.len());
            *last |= lead.shift_data(pushable) << self.used;
        }

        let new_used = self.used + pushable;

        // if new_used is 64 need to open a new block
        if lead.len() == 0 && new_used < 64 {
            self.used = new_used;
        } else {
            self.data.push(lead.data());
            self.used = lead.len();
        }

        debug_assert!(self.used != 64);
    }

    fn head(&self) -> VHead {
        debug_assert!(self.used != 64);

        VHead {
            data: self.data[0],
            prefix: self.prefix,
            used: if self.data.len() > 1 { 64 } else { self.used },
        }
    }

    fn head2(&self) -> VHead {
        debug_assert!(self.data.len() > 1);

        VHead {
            data: self.data[1],
            prefix: 0,
            used: if self.data.len() > 2 { 64 } else { self. used },
        }
    }
}

enum ApplyResult {
    /// No match
    Mismatch,
    /// Completely matched, bits in lead need to be appended
    Match,
    /// Matched but end of block reached, repeat with second block
    MatchRemaining,
    /// Completely caught up, bits in follow make up a new block
    LeadSwitch,
}

impl SPart {
    fn data(&self) -> u64 {
        self.0 & 0x00FF_FFFF_FFFF_FFFF
    }

    fn len(&self) -> u8 {
        (self.0 >> 56) as u8
    }

    fn shift(&mut self, shift: u8) {
        let new_len = self.len() - shift;
        let new_val = self.data() >> shift;
        self.0 = ((new_len as u64) << 56) | new_val;
    }

    fn shift_data(&mut self, shift: u8) -> u64 {
        let data = self.0 & mask(shift);
        self.shift(shift);
        data
    }

    fn shift_prefix(a: &mut SPart, b: &mut SPart) {
        // after the xor the first mismatched bit is a one
        // theres no need for masking data since we need to use the min of the
        // lens and prefix anyway
        let prefix = (a.0 ^ b.0).trailing_zeros() as u8; // 0-64 always fit in an u8
        let prefix = cmp::min(prefix, cmp::min(a.len(), b.len()));
        a.shift(prefix);
        b.shift(prefix);
    }
}

impl VHead {
    fn apply(&mut self, follow: &mut SPart, lead: &mut SPart) -> ApplyResult {
        // fist, check that overlapping follows are equal
        let overlap = cmp::min(self.used - self.prefix, follow.len());

        // check
        let m = mask(overlap);
        let h = (self.data >> self.prefix) & m;
        let p = follow.data() & m;

        if h != p { return Mismatch; }

        // update
        self.prefix += overlap;
        follow.shift(overlap);

        if self.prefix == 64 {
            debug_assert!(self.used == 64);
            return MatchRemaining; // Reached the end of block, needs to be removed
        }

        // at this point follow has caught up to lead, so we can eliminate any common prefix from follow and lead
        SPart::shift_prefix(follow, lead);

        match (follow.len() == 0, lead.len() == 0) {
            (_, true) => LeadSwitch, // lead is empty, start a new block with follow
            (false, false) => Mismatch, // both have non matching bits remaining
            (true, false) => Match, // follow is empty
        }
    }
}

/// Create a bitmask of which the lower `cnt` bits are set.
fn mask(cnt: u8) -> u64 {
    (1 << cnt) - 1
}

impl<'a> From<&'a str> for SPart {
    fn from(s: &'a str) -> SPart {
        let mut val = 0u64;
        let mut len = 0u64;

        for b in s.bytes().rev() {
            len += 1;
            val <<= 1;

            match b {
                b'0' => (),
                b'1' => val |= 1,
                _ => panic!("invalid input byte: {}", b),
            }
        }

        assert!(len <= 56, "invalid input: too long");

        SPart((len << 56) | val)
    }
}

impl<'a> From<(&'a str, &'a str)> for SPair {
    fn from((a, b): (&'a str, &'a str)) -> SPair {
        SPair {
            a: a.into(),
            b: b.into(),
        }
    }
}
<|endoftext|>


<commit_before>//! POET - the Performance with Optimal Energy Toolkit. Used to meet timing constraints while
//! minimizing energy consumption.

use libc::{c_void, c_char, c_int, c_uint, c_double};
use std::ffi::CString;
use std::ptr;

/// Typedef for an "apply" function - used to manipulate system or application settings.
pub type POETApplyFn = unsafe extern fn(states: *mut c_void,
                                        num_states: c_uint,
                                        id: c_uint,
                                        last_id: c_uint);

/// Typedef for "current state" function - used to try and determine the current system or
/// application state.
pub type POETCurrentStateFn = unsafe extern fn(states: *const c_void,
                                               num_states: c_uint,
                                               curr_state_id: *mut c_uint) -> i32;

#[link(name = "poet")]
extern {
    /*
     * Core functions - poet.h
     */

    fn poet_init(perf_goal: c_double,
                 num_system_states: c_uint,
                 control_states: *mut POETControlState,
                 apply_states: *mut POETCpuState,
                 apply_func: POETApplyFn,
                 curr_state_func: POETCurrentStateFn,
                 period: c_uint,
                 buffer_depth: c_uint,
                 log_filename: *const c_char) -> *mut c_void;

    fn poet_apply_control(state: *mut c_void,
                          id: u64,
                          perf: c_double,
                          pwr: c_double);

    fn poet_destroy(state: *mut c_void);

    /*
     * Configuration/utility functions - poet_config.h
     */

    fn apply_cpu_config(states: *mut c_void,
                        num_states: c_uint,
                        id: c_uint,
                        last_id: c_uint);

    fn get_control_states(path: *const c_char,
                          states: *mut *mut POETControlState,
                          num_states: *mut c_uint) -> c_int;

    fn get_cpu_states(path: *const c_char,
                      states: *mut *mut POETCpuState,
                      num_states: *mut c_uint) -> c_int;

    fn get_current_cpu_state(states: *const c_void,
                             num_states: c_uint,
                             curr_state_id: *mut c_uint) -> c_int;

}

#[repr(C)]
/// Representation of native struct `poet_control_state_t`.
pub struct POETControlState {
    pub id: c_uint,
    pub speedup: c_double,
    pub cost: c_double,
}

impl POETControlState {
    /// Attempt to load control states from a file.
    pub fn new(filename: Option<&str>) -> Result<(*mut POETControlState, u32), String> {
        let filename = match filename {
            Some(f) => CString::new(f).unwrap().as_ptr(),
            None => ptr::null(),
        };
        let mut control_states = ptr::null_mut();
        let mut num_ctl_states : u32 = 0;
        let res = unsafe {
            get_control_states(filename,
                               &mut control_states,
                               &mut num_ctl_states)
        };
        if res != 0 {
            return Err("Failed to load control states".to_string());
        }
        Ok((control_states, num_ctl_states))
    }
}

impl Default for POETControlState {
    fn default() -> POETControlState {
        POETControlState {
            id: 0,
            speedup: 1.0,
            cost: 1.0,
        }
    }
}

#[repr(C)]
/// Representation of native struct `poet_cpu_state_t`.
pub struct POETCpuState {
    id: c_uint,
    freq: c_uint,
    cores: c_uint,
}

impl POETCpuState {
    /// Attempt to load cpu states from a file.
    pub fn new(filename: Option<&str>) -> Result<(*mut POETCpuState, u32), String> {
        let filename = match filename {
            Some(f) => CString::new(f).unwrap().as_ptr(),
            None => ptr::null(),
        };
        let mut cpu_states = ptr::null_mut();
        let mut num_cpu_states : u32 = 0;
        let res = unsafe {
            get_cpu_states(filename,
                           &mut cpu_states,
                           &mut num_cpu_states)
        };
        if res != 0 {
            return Err("Failed to load cpu states".to_string());
        }
        Ok((cpu_states, num_cpu_states))
    }
}

impl Default for POETCpuState {
    fn default() -> POETCpuState {
        POETCpuState {
            id: 0,
            freq: 0,
            cores: 0,
        }
    }
}

/// The `POET` struct wraps an underyling C struct.
pub struct POET {
    /// The underlying C struct `poet_state`.
    pub poet: *mut c_void,
}

impl POET {
    /// Attempt to initialize POET and allocate resources in the underlying C struct.
    pub fn new(perf_goal: f64,
               control_states: *mut POETControlState,
               cpu_states: *mut POETCpuState,
               num_states: u32,
               apply_func: Option<POETApplyFn>,
               curr_state_func: Option<POETCurrentStateFn>,
               period: u32,
               buffer_depth: u32,
               log_filename: Option<&str>) -> Result<POET, String> {
        let apply_func = match apply_func {
            Some(p) => p,
            None => apply_cpu_config,
        };
        let curr_state_func = match curr_state_func {
            Some(p) => p,
            None => get_current_cpu_state,
        };
        let log_filename = match log_filename {
            Some(l) => CString::new(l).unwrap().as_ptr(),
            None => ptr::null(),
        };
        let poet = unsafe {
            poet_init(perf_goal,
                      num_states, control_states, cpu_states,
                      apply_func, curr_state_func,
                      period, buffer_depth, log_filename)
        };
        if poet.is_null() {
            return Err("Failed to instantiate POET object".to_string());
        }
        Ok(POET { poet: poet, })
    }

    /// Call at every iteration - at specified periods this function will (potentially) order
    /// changes to system or application state to try and meet timing constraints.
    pub fn apply_control(&mut self, tag: u64, window_rate: f64, window_power: f64) {
        unsafe {
            poet_apply_control(self.poet, tag, window_rate, window_power);
        }
    }
}

impl Drop for POET {
    /// Cleanup POET and deallocate resources in the underlying C struct.
    fn drop(&mut self) {
        unsafe {
            poet_destroy(self.poet);
        }
        println!("Cleaned up POET");
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use libc::{c_void, c_uint};

    #[test]
    fn test_basic() {
        let mut control_states = vec![POETControlState::default()];
        let mut cpu_states = vec![POETCpuState::default()];
        let mut poet = POET::new(100.0,
                                 control_states.as_mut_ptr(), cpu_states.as_mut_ptr(), 1,
                                 None, None,
                                 20u32, 1u32, None).unwrap();
        poet.apply_control(0, 1.0, 1.0);
    }

    #[test]
    fn test_rust_callbacks() {
        let mut control_states = vec![POETControlState::default()];
        let mut cpu_states = vec![POETCpuState::default()];
        let mut poet = POET::new(100.0,
                                 control_states.as_mut_ptr(), cpu_states.as_mut_ptr(), 1,
                                 Some(dummy_apply), Some(dummy_curr_state),
                                 20u32, 1u32, None).unwrap();
        for i in 0..50 {
            poet.apply_control(i, 1.0, 1.0);
        }
    }

    unsafe extern fn dummy_apply(_states: *mut c_void,
                                 _num_states: c_uint,
                                 _id: c_uint,
                                 _last_id: c_uint) {
        // do nothing
        println!("Received apply call");
    }

    unsafe extern fn dummy_curr_state (_states: *const c_void,
                                       _num_states: c_uint,
                                       _curr_state_id: *mut c_uint) -> i32 {
        println!("Received curr state call");
        // this is actually an invalid value, but forces the apply function to be called
        *_curr_state_id = _num_states;
        0
    }

}
<commit_msg>Change Err to return static str ref instead of String<commit_after>//! POET - the Performance with Optimal Energy Toolkit. Used to meet timing constraints while
//! minimizing energy consumption.

use libc::{c_void, c_char, c_int, c_uint, c_double};
use std::ffi::CString;
use std::ptr;

/// Typedef for an "apply" function - used to manipulate system or application settings.
pub type POETApplyFn = unsafe extern fn(states: *mut c_void,
                                        num_states: c_uint,
                                        id: c_uint,
                                        last_id: c_uint);

/// Typedef for "current state" function - used to try and determine the current system or
/// application state.
pub type POETCurrentStateFn = unsafe extern fn(states: *const c_void,
                                               num_states: c_uint,
                                               curr_state_id: *mut c_uint) -> i32;

#[link(name = "poet")]
extern {
    /*
     * Core functions - poet.h
     */

    fn poet_init(perf_goal: c_double,
                 num_system_states: c_uint,
                 control_states: *mut POETControlState,
                 apply_states: *mut POETCpuState,
                 apply_func: POETApplyFn,
                 curr_state_func: POETCurrentStateFn,
                 period: c_uint,
                 buffer_depth: c_uint,
                 log_filename: *const c_char) -> *mut c_void;

    fn poet_apply_control(state: *mut c_void,
                          id: u64,
                          perf: c_double,
                          pwr: c_double);

    fn poet_destroy(state: *mut c_void);

    /*
     * Configuration/utility functions - poet_config.h
     */

    fn apply_cpu_config(states: *mut c_void,
                        num_states: c_uint,
                        id: c_uint,
                        last_id: c_uint);

    fn get_control_states(path: *const c_char,
                          states: *mut *mut POETControlState,
                          num_states: *mut c_uint) -> c_int;

    fn get_cpu_states(path: *const c_char,
                      states: *mut *mut POETCpuState,
                      num_states: *mut c_uint) -> c_int;

    fn get_current_cpu_state(states: *const c_void,
                             num_states: c_uint,
                             curr_state_id: *mut c_uint) -> c_int;

}

#[repr(C)]
/// Representation of native struct `poet_control_state_t`.
pub struct POETControlState {
    pub id: c_uint,
    pub speedup: c_double,
    pub cost: c_double,
}

impl POETControlState {
    /// Attempt to load control states from a file.
    pub fn new(filename: Option<&str>) -> Result<(*mut POETControlState, u32), &'static str> {
        let filename = match filename {
            Some(f) => CString::new(f).unwrap().as_ptr(),
            None => ptr::null(),
        };
        let mut control_states = ptr::null_mut();
        let mut num_ctl_states : u32 = 0;
        let res = unsafe {
            get_control_states(filename,
                               &mut control_states,
                               &mut num_ctl_states)
        };
        if res != 0 {
            return Err("Failed to load control states");
        }
        Ok((control_states, num_ctl_states))
    }
}

impl Default for POETControlState {
    fn default() -> POETControlState {
        POETControlState {
            id: 0,
            speedup: 1.0,
            cost: 1.0,
        }
    }
}

#[repr(C)]
/// Representation of native struct `poet_cpu_state_t`.
pub struct POETCpuState {
    id: c_uint,
    freq: c_uint,
    cores: c_uint,
}

impl POETCpuState {
    /// Attempt to load cpu states from a file.
    pub fn new(filename: Option<&str>) -> Result<(*mut POETCpuState, u32), &'static str> {
        let filename = match filename {
            Some(f) => CString::new(f).unwrap().as_ptr(),
            None => ptr::null(),
        };
        let mut cpu_states = ptr::null_mut();
        let mut num_cpu_states : u32 = 0;
        let res = unsafe {
            get_cpu_states(filename,
                           &mut cpu_states,
                           &mut num_cpu_states)
        };
        if res != 0 {
            return Err("Failed to load cpu states");
        }
        Ok((cpu_states, num_cpu_states))
    }
}

impl Default for POETCpuState {
    fn default() -> POETCpuState {
        POETCpuState {
            id: 0,
            freq: 0,
            cores: 0,
        }
    }
}

/// The `POET` struct wraps an underyling C struct.
pub struct POET {
    /// The underlying C struct `poet_state`.
    pub poet: *mut c_void,
}

impl POET {
    /// Attempt to initialize POET and allocate resources in the underlying C struct.
    pub fn new(perf_goal: f64,
               control_states: *mut POETControlState,
               cpu_states: *mut POETCpuState,
               num_states: u32,
               apply_func: Option<POETApplyFn>,
               curr_state_func: Option<POETCurrentStateFn>,
               period: u32,
               buffer_depth: u32,
               log_filename: Option<&str>) -> Result<POET, &'static str> {
        let apply_func = match apply_func {
            Some(p) => p,
            None => apply_cpu_config,
        };
        let curr_state_func = match curr_state_func {
            Some(p) => p,
            None => get_current_cpu_state,
        };
        let log_filename = match log_filename {
            Some(l) => CString::new(l).unwrap().as_ptr(),
            None => ptr::null(),
        };
        let poet = unsafe {
            poet_init(perf_goal,
                      num_states, control_states, cpu_states,
                      apply_func, curr_state_func,
                      period, buffer_depth, log_filename)
        };
        if poet.is_null() {
            return Err("Failed to instantiate POET object");
        }
        Ok(POET { poet: poet, })
    }

    /// Call at every iteration - at specified periods this function will (potentially) order
    /// changes to system or application state to try and meet timing constraints.
    pub fn apply_control(&mut self, tag: u64, window_rate: f64, window_power: f64) {
        unsafe {
            poet_apply_control(self.poet, tag, window_rate, window_power);
        }
    }
}

impl Drop for POET {
    /// Cleanup POET and deallocate resources in the underlying C struct.
    fn drop(&mut self) {
        unsafe {
            poet_destroy(self.poet);
        }
        println!("Cleaned up POET");
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use libc::{c_void, c_uint};

    #[test]
    fn test_basic() {
        let mut control_states = vec![POETControlState::default()];
        let mut cpu_states = vec![POETCpuState::default()];
        let mut poet = POET::new(100.0,
                                 control_states.as_mut_ptr(), cpu_states.as_mut_ptr(), 1,
                                 None, None,
                                 20u32, 1u32, None).unwrap();
        poet.apply_control(0, 1.0, 1.0);
    }

    #[test]
    fn test_rust_callbacks() {
        let mut control_states = vec![POETControlState::default()];
        let mut cpu_states = vec![POETCpuState::default()];
        let mut poet = POET::new(100.0,
                                 control_states.as_mut_ptr(), cpu_states.as_mut_ptr(), 1,
                                 Some(dummy_apply), Some(dummy_curr_state),
                                 20u32, 1u32, None).unwrap();
        for i in 0..50 {
            poet.apply_control(i, 1.0, 1.0);
        }
    }

    unsafe extern fn dummy_apply(_states: *mut c_void,
                                 _num_states: c_uint,
                                 _id: c_uint,
                                 _last_id: c_uint) {
        // do nothing
        println!("Received apply call");
    }

    unsafe extern fn dummy_curr_state (_states: *const c_void,
                                       _num_states: c_uint,
                                       _curr_state_id: *mut c_uint) -> i32 {
        println!("Received curr state call");
        // this is actually an invalid value, but forces the apply function to be called
        *_curr_state_id = _num_states;
        0
    }

}
<|endoftext|>


<commit_before>// Copyright (c) 2017 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::mem;

use enums;
use parse;

/// Returns true if the document has specialization constants.
pub fn has_specialization_constants(doc: &parse::Spirv) -> bool {
    for instruction in doc.instructions.iter() {
        match instruction {
            &parse::Instruction::SpecConstantTrue { .. } => return true,
            &parse::Instruction::SpecConstantFalse { .. } => return true,
            &parse::Instruction::SpecConstant { .. } => return true,
            &parse::Instruction::SpecConstantComposite { .. } => return true,
            _ => (),
        }
    }

    false
}

/// Writes the `SpecializationConstants` struct that contains the specialization constants and
/// implements the `Default` and the `vulkano::pipeline::shader::SpecializationConstants` traits.
pub fn write_specialization_constants(doc: &parse::Spirv) -> String {
    struct SpecConst {
        name: String,
        constant_id: u32,
        rust_ty: String,
        rust_size: usize,
        rust_alignment: usize,
        default_value: String,
    }

    let mut spec_consts = Vec::new();

    for instruction in doc.instructions.iter() {
        let (type_id, result_id, default_value) = match instruction {
            &parse::Instruction::SpecConstantTrue { result_type_id, result_id } => {
                (result_type_id, result_id, "1u32".to_string())
            },
            &parse::Instruction::SpecConstantFalse { result_type_id, result_id } => {
                (result_type_id, result_id, "0u32".to_string())
            },
            &parse::Instruction::SpecConstant { result_type_id, result_id, ref data } => {
                let data = data.iter().map(|d| d.to_string() + "u32").collect::<Vec<_>>().join(", ");
                let def_val = format!("unsafe {{ ::std::mem::transmute([{}]) }}", data);
                (result_type_id, result_id, def_val)
            },
            &parse::Instruction::SpecConstantComposite { result_type_id, result_id, ref data } => {
                let data = data.iter().map(|d| d.to_string() + "u32").collect::<Vec<_>>().join(", ");
                let def_val = format!("unsafe {{ ::std::mem::transmute([{}]) }}", data);
                (result_type_id, result_id, def_val)
            },
            _ => continue,
        };

        let (rust_ty, rust_size, rust_alignment) = spec_const_type_from_id(doc, type_id);
        let rust_size = rust_size.expect("Found runtime-sized specialization constant");

        let constant_id = doc.instructions.iter().filter_map(|i| {
            match i {
                &parse::Instruction::Decorate
                    { target_id, decoration: enums::Decoration::DecorationSpecId, ref params }
                    if target_id == result_id =>
                {
                    Some(params[0])
                },
                _ => None,
            }
        }).next().expect("Found a specialization constant with no SpecId decoration");

        spec_consts.push(SpecConst {
            name: ::name_from_id(doc, result_id),
            constant_id,
            rust_ty,
            rust_size,
            rust_alignment,
            default_value,
        });
    }

    let map_entries = {
        let mut map_entries = Vec::new();
        let mut curr_offset = 0;
        for c in &spec_consts {
            map_entries.push(format!("SpecializationMapEntry {{
                constant_id: {},
                offset: {},
                size: {},
            }}", c.constant_id, curr_offset, c.rust_size));

            assert_ne!(c.rust_size, 0);
            curr_offset += c.rust_size;
            curr_offset = c.rust_alignment * (1 + (curr_offset - 1) / c.rust_alignment);
        }
        map_entries
    };

    format!(r#"

#[derive(Debug, Copy, Clone)]
#[repr(C)]
pub struct SpecializationConstants {{
    {struct_def}
}}

impl Default for SpecializationConstants {{
    fn default() -> SpecializationConstants {{
        SpecializationConstants {{
            {def_vals}
        }}
    }}
}}

unsafe impl SpecConstsTrait for SpecializationConstants {{
    fn descriptors() -> &'static [SpecializationMapEntry] {{
        static DESCRIPTORS: [SpecializationMapEntry; {num_map_entries}] = [
            {map_entries}
        ];
        &DESCRIPTORS
    }}
}}

    "#,
        struct_def = spec_consts.iter().map(|c| format!("pub {}: {}", c.name, c.rust_ty))
                                .collect::<Vec<_>>().join(", "),
        def_vals = spec_consts.iter().map(|c| format!("{}: {}", c.name, c.default_value))
                                .collect::<Vec<_>>().join(", "),
        num_map_entries = map_entries.len(),
        map_entries = map_entries.join(", ")
    )
}

// Wrapper around `type_from_id` that also handles booleans.
fn spec_const_type_from_id(doc: &parse::Spirv, searched: u32) -> (String, Option<usize>, usize) {
    for instruction in doc.instructions.iter() {
        match instruction {
            &parse::Instruction::TypeBool { result_id } if result_id == searched => {
                return ("u32".to_owned(), Some(mem::size_of::<u32>()), mem::align_of::<u32>());
            },
            _ => ()
        }
    }

    ::structs::type_from_id(doc, searched)
}
<commit_msg>Allow non-snake-case for specialization constants (#799)<commit_after>// Copyright (c) 2017 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::mem;

use enums;
use parse;

/// Returns true if the document has specialization constants.
pub fn has_specialization_constants(doc: &parse::Spirv) -> bool {
    for instruction in doc.instructions.iter() {
        match instruction {
            &parse::Instruction::SpecConstantTrue { .. } => return true,
            &parse::Instruction::SpecConstantFalse { .. } => return true,
            &parse::Instruction::SpecConstant { .. } => return true,
            &parse::Instruction::SpecConstantComposite { .. } => return true,
            _ => (),
        }
    }

    false
}

/// Writes the `SpecializationConstants` struct that contains the specialization constants and
/// implements the `Default` and the `vulkano::pipeline::shader::SpecializationConstants` traits.
pub fn write_specialization_constants(doc: &parse::Spirv) -> String {
    struct SpecConst {
        name: String,
        constant_id: u32,
        rust_ty: String,
        rust_size: usize,
        rust_alignment: usize,
        default_value: String,
    }

    let mut spec_consts = Vec::new();

    for instruction in doc.instructions.iter() {
        let (type_id, result_id, default_value) = match instruction {
            &parse::Instruction::SpecConstantTrue { result_type_id, result_id } => {
                (result_type_id, result_id, "1u32".to_string())
            },
            &parse::Instruction::SpecConstantFalse { result_type_id, result_id } => {
                (result_type_id, result_id, "0u32".to_string())
            },
            &parse::Instruction::SpecConstant { result_type_id, result_id, ref data } => {
                let data = data.iter().map(|d| d.to_string() + "u32").collect::<Vec<_>>().join(", ");
                let def_val = format!("unsafe {{ ::std::mem::transmute([{}]) }}", data);
                (result_type_id, result_id, def_val)
            },
            &parse::Instruction::SpecConstantComposite { result_type_id, result_id, ref data } => {
                let data = data.iter().map(|d| d.to_string() + "u32").collect::<Vec<_>>().join(", ");
                let def_val = format!("unsafe {{ ::std::mem::transmute([{}]) }}", data);
                (result_type_id, result_id, def_val)
            },
            _ => continue,
        };

        let (rust_ty, rust_size, rust_alignment) = spec_const_type_from_id(doc, type_id);
        let rust_size = rust_size.expect("Found runtime-sized specialization constant");

        let constant_id = doc.instructions.iter().filter_map(|i| {
            match i {
                &parse::Instruction::Decorate
                    { target_id, decoration: enums::Decoration::DecorationSpecId, ref params }
                    if target_id == result_id =>
                {
                    Some(params[0])
                },
                _ => None,
            }
        }).next().expect("Found a specialization constant with no SpecId decoration");

        spec_consts.push(SpecConst {
            name: ::name_from_id(doc, result_id),
            constant_id,
            rust_ty,
            rust_size,
            rust_alignment,
            default_value,
        });
    }

    let map_entries = {
        let mut map_entries = Vec::new();
        let mut curr_offset = 0;
        for c in &spec_consts {
            map_entries.push(format!("SpecializationMapEntry {{
                constant_id: {},
                offset: {},
                size: {},
            }}", c.constant_id, curr_offset, c.rust_size));

            assert_ne!(c.rust_size, 0);
            curr_offset += c.rust_size;
            curr_offset = c.rust_alignment * (1 + (curr_offset - 1) / c.rust_alignment);
        }
        map_entries
    };

    format!(r#"

#[derive(Debug, Copy, Clone)]
#[allow(non_snake_case)]
#[repr(C)]
pub struct SpecializationConstants {{
    {struct_def}
}}

impl Default for SpecializationConstants {{
    fn default() -> SpecializationConstants {{
        SpecializationConstants {{
            {def_vals}
        }}
    }}
}}

unsafe impl SpecConstsTrait for SpecializationConstants {{
    fn descriptors() -> &'static [SpecializationMapEntry] {{
        static DESCRIPTORS: [SpecializationMapEntry; {num_map_entries}] = [
            {map_entries}
        ];
        &DESCRIPTORS
    }}
}}

    "#,
        struct_def = spec_consts.iter().map(|c| format!("pub {}: {}", c.name, c.rust_ty))
                                .collect::<Vec<_>>().join(", "),
        def_vals = spec_consts.iter().map(|c| format!("{}: {}", c.name, c.default_value))
                                .collect::<Vec<_>>().join(", "),
        num_map_entries = map_entries.len(),
        map_entries = map_entries.join(", ")
    )
}

// Wrapper around `type_from_id` that also handles booleans.
fn spec_const_type_from_id(doc: &parse::Spirv, searched: u32) -> (String, Option<usize>, usize) {
    for instruction in doc.instructions.iter() {
        match instruction {
            &parse::Instruction::TypeBool { result_id } if result_id == searched => {
                return ("u32".to_owned(), Some(mem::size_of::<u32>()), mem::align_of::<u32>());
            },
            _ => ()
        }
    }

    ::structs::type_from_id(doc, searched)
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::sync::Arc;

use buffer::BufferAccess;
use command_buffer::cb;
use command_buffer::commands_raw;
use command_buffer::cb::AddCommand;
use command_buffer::cb::CommandBufferBuild;
use command_buffer::cb::UnsafeCommandBuffer;
use command_buffer::CommandAddError;
use command_buffer::CommandBuffer;
use command_buffer::CommandBufferBuilder;
use command_buffer::CommandBufferExecError;
use command_buffer::pool::CommandPool;
use command_buffer::pool::StandardCommandPool;
use device::Device;
use device::DeviceOwned;
use device::Queue;
use image::ImageLayout;
use image::ImageAccess;
use instance::QueueFamily;
use sync::AccessCheckError;
use sync::AccessFlagBits;
use sync::PipelineStages;
use sync::GpuFuture;
use OomError;

type Cb
 = cb::DeviceCheckLayer<cb::QueueTyCheckLayer<cb::ContextCheckLayer<cb::StateCacheLayer<cb::SubmitSyncBuilderLayer<cb::AutoPipelineBarriersLayer<cb::AbstractStorageLayer<cb::UnsafeCommandBufferBuilder
>>>>>>>;

///
///
/// Note that command buffers allocated from the default command pool (`Arc<StandardCommandPool>`)
/// don't implement the `Send` and `Sync` traits. If you use this pool, then the
/// `AutoCommandBufferBuilder` will not implement `Send` and `Sync` either. Once a command buffer
/// is built, however, it *does* implement `Send` and `Sync`.
///
pub struct AutoCommandBufferBuilder<P = Arc<StandardCommandPool>> where P: CommandPool {
    inner: Cb

}

impl AutoCommandBufferBuilder<Arc<StandardCommandPool>> {
    pub fn new(device: Arc<Device>, queue_family: QueueFamily)
               -> Result<AutoCommandBufferBuilder<Arc<StandardCommandPool>>, OomError>
    {
        let pool = Device::standard_command_pool(&device, queue_family);

        let cmd = unsafe {
            let c = try!(cb::UnsafeCommandBufferBuilder::new(&pool, cb::Kind::primary(), cb::Flags::SimultaneousUse /* TODO: */));
            let c = cb::AbstractStorageLayer::new(c);
            let c = cb::AutoPipelineBarriersLayer::new(c);
            let c = cb::SubmitSyncBuilderLayer::new(c, cb::SubmitSyncBuilderLayerBehavior::UseLayoutHint);
            let c = cb::StateCacheLayer::new(c);
            let c = cb::ContextCheckLayer::new(c, false, true);
            let c = cb::QueueTyCheckLayer::new(c);
            let c = cb::DeviceCheckLayer::new(c);
            c
        };

        Ok(AutoCommandBufferBuilder {
            inner: cmd,
        })
    }
}

unsafe impl
 CommandBufferBuild for AutoCommandBufferBuilder

    where Cb
: CommandBufferBuild<Out = O, Err = E>,
          P: CommandPool
{
    type Out = O;
    type Err = E;

    #[inline]
    fn build(self) -> Result<O, E> {
        // TODO: wrap around?
        CommandBufferBuild::build(self.inner)
    }
}

unsafe impl
 CommandBuffer for AutoCommandBufferBuilder

    where Cb
: CommandBuffer,
          P: CommandPool
{
    type Pool = <Cb
 as CommandBuffer>::Pool;

    #[inline]
    fn inner(&self) -> &UnsafeCommandBuffer<Self::Pool> {
        self.inner.inner()
    }

    #[inline]
    fn prepare_submit(&self, future: &GpuFuture, queue: &Queue) -> Result<(), CommandBufferExecError> {
        self.inner.prepare_submit(future, queue)
    }

    #[inline]
    fn check_buffer_access(&self, buffer: &BufferAccess, exclusive: bool, queue: &Queue)
                           -> Result<Option<(PipelineStages, AccessFlagBits)>, AccessCheckError>
    {
        self.inner.check_buffer_access(buffer, exclusive, queue)
    }

    #[inline]
    fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, queue: &Queue)
                          -> Result<Option<(PipelineStages, AccessFlagBits)>, AccessCheckError>
    {
        self.inner.check_image_access(image, layout, exclusive, queue)
    }
}

unsafe impl
 DeviceOwned for AutoCommandBufferBuilder

    where Cb
: DeviceOwned,
          P: CommandPool
{
    #[inline]
    fn device(&self) -> &Arc<Device> {
        self.inner.device()
    }
}

unsafe impl
 CommandBufferBuilder for AutoCommandBufferBuilder

    where Cb
: CommandBufferBuilder,
          P: CommandPool
{
    #[inline]
    fn queue_family(&self) -> QueueFamily {
        self.inner.queue_family()
    }
}

macro_rules! pass_through {
    (($($param:ident),*), $cmd:ty) => {
        unsafe impl
 AddCommand<$cmd> for AutoCommandBufferBuilder

            where P: CommandPool,
                  Cb
: AddCommand<$cmd, Out = Cb
>
        {
            type Out = AutoCommandBufferBuilder
;

            #[inline]
            fn add(self, command: $cmd) -> Result<Self::Out, CommandAddError> {
                Ok(AutoCommandBufferBuilder {
                    inner: self.inner.add(command)?,
                })
            }
        }
    }
}

pass_through!((Rp, F), commands_raw::CmdBeginRenderPass<Rp, F>);
pass_through!((S, Pl), commands_raw::CmdBindDescriptorSets<S, Pl>);
pass_through!((B), commands_raw::CmdBindIndexBuffer);
pass_through!((Pl), commands_raw::CmdBindPipeline<Pl>);
pass_through!((V), commands_raw::CmdBindVertexBuffers<V>);
pass_through!((), commands_raw::CmdClearAttachments);
pass_through!((S, D), commands_raw::CmdCopyBuffer<S, D>);
pass_through!((S, D), commands_raw::CmdCopyBufferToImage<S, D>);
pass_through!((), commands_raw::CmdDrawRaw);
pass_through!((), commands_raw::CmdDrawIndexedRaw);
pass_through!((B), commands_raw::CmdDrawIndirectRaw);
pass_through!((), commands_raw::CmdEndRenderPass);
pass_through!((C), commands_raw::CmdExecuteCommands<C>);
pass_through!((B), commands_raw::CmdFillBuffer);
pass_through!((), commands_raw::CmdNextSubpass);
pass_through!((Pc, Pl), commands_raw::CmdPushConstants<Pc, Pl>);
pass_through!((), commands_raw::CmdSetState);
pass_through!((B, D), commands_raw::CmdUpdateBuffer);
pass_through!((), commands_raw::CmdDispatchRaw);
<commit_msg>order pass_through invocations<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::sync::Arc;

use buffer::BufferAccess;
use command_buffer::cb;
use command_buffer::commands_raw;
use command_buffer::cb::AddCommand;
use command_buffer::cb::CommandBufferBuild;
use command_buffer::cb::UnsafeCommandBuffer;
use command_buffer::CommandAddError;
use command_buffer::CommandBuffer;
use command_buffer::CommandBufferBuilder;
use command_buffer::CommandBufferExecError;
use command_buffer::pool::CommandPool;
use command_buffer::pool::StandardCommandPool;
use device::Device;
use device::DeviceOwned;
use device::Queue;
use image::ImageLayout;
use image::ImageAccess;
use instance::QueueFamily;
use sync::AccessCheckError;
use sync::AccessFlagBits;
use sync::PipelineStages;
use sync::GpuFuture;
use OomError;

type Cb
 = cb::DeviceCheckLayer<cb::QueueTyCheckLayer<cb::ContextCheckLayer<cb::StateCacheLayer<cb::SubmitSyncBuilderLayer<cb::AutoPipelineBarriersLayer<cb::AbstractStorageLayer<cb::UnsafeCommandBufferBuilder
>>>>>>>;

///
///
/// Note that command buffers allocated from the default command pool (`Arc<StandardCommandPool>`)
/// don't implement the `Send` and `Sync` traits. If you use this pool, then the
/// `AutoCommandBufferBuilder` will not implement `Send` and `Sync` either. Once a command buffer
/// is built, however, it *does* implement `Send` and `Sync`.
///
pub struct AutoCommandBufferBuilder<P = Arc<StandardCommandPool>> where P: CommandPool {
    inner: Cb

}

impl AutoCommandBufferBuilder<Arc<StandardCommandPool>> {
    pub fn new(device: Arc<Device>, queue_family: QueueFamily)
               -> Result<AutoCommandBufferBuilder<Arc<StandardCommandPool>>, OomError>
    {
        let pool = Device::standard_command_pool(&device, queue_family);

        let cmd = unsafe {
            let c = try!(cb::UnsafeCommandBufferBuilder::new(&pool, cb::Kind::primary(), cb::Flags::SimultaneousUse /* TODO: */));
            let c = cb::AbstractStorageLayer::new(c);
            let c = cb::AutoPipelineBarriersLayer::new(c);
            let c = cb::SubmitSyncBuilderLayer::new(c, cb::SubmitSyncBuilderLayerBehavior::UseLayoutHint);
            let c = cb::StateCacheLayer::new(c);
            let c = cb::ContextCheckLayer::new(c, false, true);
            let c = cb::QueueTyCheckLayer::new(c);
            let c = cb::DeviceCheckLayer::new(c);
            c
        };

        Ok(AutoCommandBufferBuilder {
            inner: cmd,
        })
    }
}

unsafe impl
 CommandBufferBuild for AutoCommandBufferBuilder

    where Cb
: CommandBufferBuild<Out = O, Err = E>,
          P: CommandPool
{
    type Out = O;
    type Err = E;

    #[inline]
    fn build(self) -> Result<O, E> {
        // TODO: wrap around?
        CommandBufferBuild::build(self.inner)
    }
}

unsafe impl
 CommandBuffer for AutoCommandBufferBuilder

    where Cb
: CommandBuffer,
          P: CommandPool
{
    type Pool = <Cb
 as CommandBuffer>::Pool;

    #[inline]
    fn inner(&self) -> &UnsafeCommandBuffer<Self::Pool> {
        self.inner.inner()
    }

    #[inline]
    fn prepare_submit(&self, future: &GpuFuture, queue: &Queue) -> Result<(), CommandBufferExecError> {
        self.inner.prepare_submit(future, queue)
    }

    #[inline]
    fn check_buffer_access(&self, buffer: &BufferAccess, exclusive: bool, queue: &Queue)
                           -> Result<Option<(PipelineStages, AccessFlagBits)>, AccessCheckError>
    {
        self.inner.check_buffer_access(buffer, exclusive, queue)
    }

    #[inline]
    fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, queue: &Queue)
                          -> Result<Option<(PipelineStages, AccessFlagBits)>, AccessCheckError>
    {
        self.inner.check_image_access(image, layout, exclusive, queue)
    }
}

unsafe impl
 DeviceOwned for AutoCommandBufferBuilder

    where Cb
: DeviceOwned,
          P: CommandPool
{
    #[inline]
    fn device(&self) -> &Arc<Device> {
        self.inner.device()
    }
}

unsafe impl
 CommandBufferBuilder for AutoCommandBufferBuilder

    where Cb
: CommandBufferBuilder,
          P: CommandPool
{
    #[inline]
    fn queue_family(&self) -> QueueFamily {
        self.inner.queue_family()
    }
}

macro_rules! pass_through {
    (($($param:ident),*), $cmd:ty) => {
        unsafe impl
 AddCommand<$cmd> for AutoCommandBufferBuilder

            where P: CommandPool,
                  Cb
: AddCommand<$cmd, Out = Cb
>
        {
            type Out = AutoCommandBufferBuilder
;

            #[inline]
            fn add(self, command: $cmd) -> Result<Self::Out, CommandAddError> {
                Ok(AutoCommandBufferBuilder {
                    inner: self.inner.add(command)?,
                })
            }
        }
    }
}

pass_through!((Rp, F), commands_raw::CmdBeginRenderPass<Rp, F>);
pass_through!((S, Pl), commands_raw::CmdBindDescriptorSets<S, Pl>);
pass_through!((B), commands_raw::CmdBindIndexBuffer);
pass_through!((Pl), commands_raw::CmdBindPipeline<Pl>);
pass_through!((V), commands_raw::CmdBindVertexBuffers<V>);
pass_through!((), commands_raw::CmdClearAttachments);
pass_through!((S, D), commands_raw::CmdCopyBuffer<S, D>);
pass_through!((S, D), commands_raw::CmdCopyBufferToImage<S, D>);
pass_through!((), commands_raw::CmdDispatchRaw);
pass_through!((), commands_raw::CmdDrawRaw);
pass_through!((), commands_raw::CmdDrawIndexedRaw);
pass_through!((B), commands_raw::CmdDrawIndirectRaw);
pass_through!((), commands_raw::CmdEndRenderPass);
pass_through!((C), commands_raw::CmdExecuteCommands<C>);
pass_through!((B), commands_raw::CmdFillBuffer);
pass_through!((), commands_raw::CmdNextSubpass);
pass_through!((Pc, Pl), commands_raw::CmdPushConstants<Pc, Pl>);
pass_through!((), commands_raw::CmdSetState);
pass_through!((B, D), commands_raw::CmdUpdateBuffer);
<|endoftext|>