<commit_before>use registry::{Enum, Registry, Cmd, Ns};
use std::io;

mod ty;
pub mod global_gen;
pub mod static_gen;
pub mod struct_gen;
pub mod static_struct_gen;

/// Trait for a bindings generator.
pub trait Generator {
    /// Builds the GL bindings.
    fn write<W>(&self, registry: &Registry, ns: Ns, dest: &mut W) -> io::Result<()> where W: io::Write;
}

/// This function generates a `const name: type = value;` item.
fn gen_enum_item<W>(enm: &Enum, types_prefix: &str, dest: &mut W) -> io::Result<()> where W: io::Write {
    // computing the name of the enum
    // if the original starts with a digit, adding an underscore prefix.
    let ident = if (enm.ident.chars().next().unwrap()).is_numeric() {
        format!("_{}", enm.ident)
    } else {
        enm.ident.clone()
    };

    // if the enum has the value of the form `((Type)Value)`, then `val_regexed` contains `(Type, Value)`
    let val_regexed = {
        if enm.value.starts_with("((") && enm.value.ends_with(")") {
            let separator = enm.value.chars().skip(2).position(|c| c == ')').unwrap();
            Some((&enm.value[2 .. separator + 2], enm.value[separator + 3 ..].trim_matches(')')))
        } else {
            None
        }
    };

    // computing the type of the enum
    let ty = {
        // some enums have a value of the form `((Type)Value)` ; if this is the case, we need to
        //  replace the type of the enum (which is GLenum by default) by the type in the expression
        if let Some((ty, _)) = val_regexed {
            // if the value is like `((Type)Value)`, then the type is `types::Type`
            format!("{}{}", types_prefix, ty)

        } else if enm.value.starts_with("\"") {
            // some values are of the form "Value" ; if this is the case, we use `&'static str`
            //  instead of `GLenum`
            "&'static str".to_string()

        } else {
            // some values are `TRUE` or `FALSE`, in which case we use `GLboolean` instead of
            //  `GLenum`
            match &ident[..] {
                "TRUE" | "FALSE" => format!("{}GLboolean", types_prefix),
                _ => match enm.ty {
                    Some(ref s) if &s[..] == "ull" => format!("{}GLuint64", types_prefix),
                    _ => format!("{}GLenum", types_prefix)
                }
            }
        }
    };

    // computing the value of the enum
    let value = {
        // similar to the type, some values are `((Type)Value)`
        // replacing "((Type)Value)" by "Value as types::Type"
        if let Some((ty, val)) = val_regexed {
            format!("{} as {}{}", val, types_prefix, ty)
        } else {
            enm.value.clone()
        }
    };

    writeln!(dest, "\
        #[stable]
        #[allow(dead_code)]
        #[allow(non_upper_case_globals)]
        pub const {}: {} = {}; \
    ", ident, ty, value)
}

/// Generates all the type aliases for a namespace.
///
/// Aliases are either `pub type = ...` or `#[repr(C)] pub struct ... { ... }` and contain all the
///  things that we can't obtain from the XML files.
pub fn gen_type_aliases<W>(namespace: &Ns, dest: &mut W) -> io::Result<()> where W: io::Write {
    match *namespace {
        Ns::Gl | Ns::Gles1 | Ns::Gles2 => {
            try!(ty::build_gl_aliases(dest));
        }

        Ns::Glx => {
            try!(ty::build_gl_aliases(dest));
            try!(ty::build_x_aliases(dest));
            try!(ty::build_glx_aliases(dest));
        }

        Ns::Wgl => {
            try!(ty::build_gl_aliases(dest));
            try!(ty::build_win_aliases(dest));
            try!(ty::build_wgl_aliases(dest));
        }

        Ns::Egl => {
            try!(ty::build_gl_aliases(dest));
            try!(ty::build_egl_aliases(dest));
        }
    }

    Ok(())
}

/// Generates the list of Rust `Arg`s that a `Cmd` requires.
pub fn gen_parameters(cmd: &Cmd, with_idents: bool, with_types: bool) -> Vec<String> {
    cmd.params.iter()
        .map(|binding| {
            // variable name of the binding
            let ident = match &binding.ident[..] {
                "in" => "in_",
                "ref" => "ref_",
                "type" => "type_",
                ident => ident,
            };

            // rust type of the binding
            let ty = ty::to_rust_ty(&binding.ty[..]);

            // returning
            if with_idents && with_types {
                format!("{}: {}", ident, ty)
            } else if with_types {
                format!("{}", ty)
            } else if with_idents {
                format!("{}", ident)
            } else {
                panic!()
            }
        })
        .collect()
}

/// Generates the Rust return type of a `Cmd`.
pub fn gen_return_type(cmd: &Cmd) -> String {
    // turn the return type into a Rust type
    let ty = ty::to_rust_ty(&cmd.proto.ty);

    // ... but there is one more step: if the Rust type is `c_void`, we replace it with `()`
    if ty == "__gl_imports::libc::c_void" {
        return "()".to_string();
    }

    ty.to_string()
}

/// Generates the native symbol name of a `Cmd`.
///
/// Example results: `"glClear"`, `"wglCreateContext"`, etc.
pub fn gen_symbol_name(ns: &Ns, cmd: &str) -> String {
    (match *ns {
        Ns::Gl | Ns::Gles1 | Ns::Gles2 => "gl",
        Ns::Glx => "glX",
        Ns::Wgl => "wgl",
        Ns::Egl => "egl",
    }).to_string() + cmd
}
<commit_msg>Make gen_enum_item public<commit_after>use registry::{Enum, Registry, Cmd, Ns};
use std::io;

mod ty;
pub mod global_gen;
pub mod static_gen;
pub mod struct_gen;
pub mod static_struct_gen;

/// Trait for a bindings generator.
pub trait Generator {
    /// Builds the GL bindings.
    fn write<W>(&self, registry: &Registry, ns: Ns, dest: &mut W) -> io::Result<()> where W: io::Write;
}

/// This function generates a `const name: type = value;` item.
pub fn gen_enum_item<W>(enm: &Enum, types_prefix: &str, dest: &mut W) -> io::Result<()> where W: io::Write {
    // computing the name of the enum
    // if the original starts with a digit, adding an underscore prefix.
    let ident = if (enm.ident.chars().next().unwrap()).is_numeric() {
        format!("_{}", enm.ident)
    } else {
        enm.ident.clone()
    };

    // if the enum has the value of the form `((Type)Value)`, then `val_regexed` contains `(Type, Value)`
    let val_regexed = {
        if enm.value.starts_with("((") && enm.value.ends_with(")") {
            let separator = enm.value.chars().skip(2).position(|c| c == ')').unwrap();
            Some((&enm.value[2 .. separator + 2], enm.value[separator + 3 ..].trim_matches(')')))
        } else {
            None
        }
    };

    // computing the type of the enum
    let ty = {
        // some enums have a value of the form `((Type)Value)` ; if this is the case, we need to
        //  replace the type of the enum (which is GLenum by default) by the type in the expression
        if let Some((ty, _)) = val_regexed {
            // if the value is like `((Type)Value)`, then the type is `types::Type`
            format!("{}{}", types_prefix, ty)

        } else if enm.value.starts_with("\"") {
            // some values are of the form "Value" ; if this is the case, we use `&'static str`
            //  instead of `GLenum`
            "&'static str".to_string()

        } else {
            // some values are `TRUE` or `FALSE`, in which case we use `GLboolean` instead of
            //  `GLenum`
            match &ident[..] {
                "TRUE" | "FALSE" => format!("{}GLboolean", types_prefix),
                _ => match enm.ty {
                    Some(ref s) if &s[..] == "ull" => format!("{}GLuint64", types_prefix),
                    _ => format!("{}GLenum", types_prefix)
                }
            }
        }
    };

    // computing the value of the enum
    let value = {
        // similar to the type, some values are `((Type)Value)`
        // replacing "((Type)Value)" by "Value as types::Type"
        if let Some((ty, val)) = val_regexed {
            format!("{} as {}{}", val, types_prefix, ty)
        } else {
            enm.value.clone()
        }
    };

    writeln!(dest, "\
        #[stable]
        #[allow(dead_code)]
        #[allow(non_upper_case_globals)]
        pub const {}: {} = {}; \
    ", ident, ty, value)
}

/// Generates all the type aliases for a namespace.
///
/// Aliases are either `pub type = ...` or `#[repr(C)] pub struct ... { ... }` and contain all the
///  things that we can't obtain from the XML files.
pub fn gen_type_aliases<W>(namespace: &Ns, dest: &mut W) -> io::Result<()> where W: io::Write {
    match *namespace {
        Ns::Gl | Ns::Gles1 | Ns::Gles2 => {
            try!(ty::build_gl_aliases(dest));
        }

        Ns::Glx => {
            try!(ty::build_gl_aliases(dest));
            try!(ty::build_x_aliases(dest));
            try!(ty::build_glx_aliases(dest));
        }

        Ns::Wgl => {
            try!(ty::build_gl_aliases(dest));
            try!(ty::build_win_aliases(dest));
            try!(ty::build_wgl_aliases(dest));
        }

        Ns::Egl => {
            try!(ty::build_gl_aliases(dest));
            try!(ty::build_egl_aliases(dest));
        }
    }

    Ok(())
}

/// Generates the list of Rust `Arg`s that a `Cmd` requires.
pub fn gen_parameters(cmd: &Cmd, with_idents: bool, with_types: bool) -> Vec<String> {
    cmd.params.iter()
        .map(|binding| {
            // variable name of the binding
            let ident = match &binding.ident[..] {
                "in" => "in_",
                "ref" => "ref_",
                "type" => "type_",
                ident => ident,
            };

            // rust type of the binding
            let ty = ty::to_rust_ty(&binding.ty[..]);

            // returning
            if with_idents && with_types {
                format!("{}: {}", ident, ty)
            } else if with_types {
                format!("{}", ty)
            } else if with_idents {
                format!("{}", ident)
            } else {
                panic!()
            }
        })
        .collect()
}

/// Generates the Rust return type of a `Cmd`.
pub fn gen_return_type(cmd: &Cmd) -> String {
    // turn the return type into a Rust type
    let ty = ty::to_rust_ty(&cmd.proto.ty);

    // ... but there is one more step: if the Rust type is `c_void`, we replace it with `()`
    if ty == "__gl_imports::libc::c_void" {
        return "()".to_string();
    }

    ty.to_string()
}

/// Generates the native symbol name of a `Cmd`.
///
/// Example results: `"glClear"`, `"wglCreateContext"`, etc.
pub fn gen_symbol_name(ns: &Ns, cmd: &str) -> String {
    (match *ns {
        Ns::Gl | Ns::Gles1 | Ns::Gles2 => "gl",
        Ns::Glx => "glX",
        Ns::Wgl => "wgl",
        Ns::Egl => "egl",
    }).to_string() + cmd
}
<|endoftext|>


<commit_before>#![allow(unstable)]

#[macro_use]
extern crate objc;

use objc::{encode, Id, ToMessage, WeakId};
use objc::runtime::{Class, Object, Sel};

fn main() {
    // Get a class
    let cls = Class::get("NSObject").unwrap();
    println!("NSObject size: {}", cls.instance_size());

    // Inspect its ivars
    println!("NSObject ivars:");
    for ivar in cls.instance_variables().as_slice().iter() {
        println!("{}", ivar.name());
    }

    // Allocate an instance
    let obj: Id<Object> = unsafe {
        let obj = msg_send![cls, alloc];
        let obj = msg_send![obj, init];
        Id::from_retained_ptr(obj)
    };
    println!("NSObject address: {:?}", obj.as_ptr());

    // Access an ivar of the object
    let isa: *const Class = unsafe {
        *obj.get_ivar("isa")
    };
    println!("NSObject isa: {:?}", isa);

    // Inspect a method of the class
    let hash_sel = Sel::register("hash");
    let hash_method = cls.instance_method(hash_sel).unwrap();
    let hash_return = hash_method.return_type();
    println!("-[NSObject hash] return type: {}", hash_return.as_slice());
    assert!(encode::<usize>() == hash_return.as_slice());

    // Invoke a method on the object
    let hash = unsafe {
        (msg_send![obj, hash]) as usize
    };
    println!("NSObject hash: {}", hash);

    // Take a weak reference to the object
    let obj = obj.share();
    let weak = WeakId::new(&obj);
    println!("Weak reference is nil? {}", weak.load().is_none());

    println!("Releasing object");
    drop(obj);
    println!("Weak reference is nil? {}", weak.load().is_none());
}
<commit_msg>Updated core example.<commit_after>#![allow(unstable)]

#[macro_use]
extern crate objc;

use objc::{encode, Id, WeakId};
use objc::runtime::{Class, Object};

fn main() {
    // Get a class
    let cls = Class::get("NSObject").unwrap();
    println!("NSObject size: {}", cls.instance_size());

    // Inspect its ivars
    println!("NSObject ivars:");
    for ivar in cls.instance_variables().as_slice().iter() {
        println!("{}", ivar.name());
    }

    // Allocate an instance
    let obj: Id<Object> = unsafe {
        let obj = msg_send![cls, alloc];
        let obj = msg_send![obj, init];
        Id::from_retained_ptr(obj)
    };
    println!("NSObject address: {:?}", &*obj as *const Object);

    // Access an ivar of the object
    let isa: *const Class = unsafe {
        *obj.get_ivar("isa")
    };
    println!("NSObject isa: {:?}", isa);

    // Inspect a method of the class
    let hash_sel = sel!(hash);
    let hash_method = cls.instance_method(hash_sel).unwrap();
    let hash_return = hash_method.return_type();
    println!("-[NSObject hash] return type: {}", hash_return.as_slice());
    assert!(encode::<usize>() == hash_return.as_slice());

    // Invoke a method on the object
    let hash = unsafe {
        msg_send![obj, hash] as usize
    };
    println!("NSObject hash: {}", hash);

    // Take a weak reference to the object
    let obj = obj.share();
    let weak = WeakId::new(&obj);
    println!("Weak reference is nil? {}", weak.load().is_none());

    println!("Releasing object");
    drop(obj);
    println!("Weak reference is nil? {}", weak.load().is_none());
}
<|endoftext|>


<commit_before>//! Tests of the interactive console installer

pub mod mock;

use crate::mock::clitools::{self, expect_stdout_ok, Config, SanitizedOutput, Scenario};
use crate::mock::{get_path, restore_path};
use lazy_static::lazy_static;
use std::io::Write;
use std::process::Stdio;
use std::sync::Mutex;

pub fn setup(f: &dyn Fn(&Config)) {
    clitools::setup(Scenario::SimpleV2, &|config| {
        // Lock protects environment variables
        lazy_static! {
            static ref LOCK: Mutex<()> = Mutex::new(());
        }
        let _g = LOCK.lock();

        // An windows these tests mess with the user's PATH. Save
        // and restore them here to keep from trashing things.
        let saved_path = get_path();
        let _g = scopeguard::guard(saved_path, restore_path);

        f(config);
    });
}

fn run_input(config: &Config, args: &[&str], input: &str) -> SanitizedOutput {
    let mut cmd = clitools::cmd(config, args[0], &args[1..]);
    clitools::env(config, &mut cmd);

    cmd.stdin(Stdio::piped());
    cmd.stdout(Stdio::piped());
    cmd.stderr(Stdio::piped());
    let mut child = cmd.spawn().unwrap();

    child
        .stdin
        .as_mut()
        .unwrap()
        .write_all(input.as_bytes())
        .unwrap();
    let out = child.wait_with_output().unwrap();

    SanitizedOutput {
        ok: out.status.success(),
        stdout: String::from_utf8(out.stdout).unwrap(),
        stderr: String::from_utf8(out.stderr).unwrap(),
    }
}

#[test]
fn smoke_test() {
    setup(&|config| {
        let out = run_input(config, &["rustup-init"], "\n\n");
        assert!(out.ok);
    });
}

#[test]
fn update() {
    setup(&|config| {
        run_input(config, &["rustup-init"], "\n\n");
        let out = run_input(config, &["rustup-init"], "\n\n");
        assert!(out.ok, "stdout:\n{}\nstderr:\n{}", out.stdout, out.stderr);
    });
}

// Testing that the right number of blank lines are printed after the
// 'pre-install' message and before the 'post-install' message.
#[test]
fn blank_lines_around_stderr_log_output_install() {
    setup(&|config| {
        let out = run_input(config, &["rustup-init"], "\n\n");

        // During an interactive session, after "Press the Enter
        // key..."  the UI emits a blank line, then there is a blank
        // line that comes from the user pressing enter, then log
        // output on stderr, then an explicit blank line on stdout
        // before printing $toolchain installed
        assert!(out.stdout.contains(
            r"
3) Cancel installation
>

  stable installed - 1.1.0 (hash-stable-1.1.0)

Rust is installed now. Great!
"
        ));
    });
}

#[test]
fn blank_lines_around_stderr_log_output_update() {
    setup(&|config| {
        run_input(config, &["rustup-init"], "\n\n");
        let out = run_input(config, &["rustup-init"], "\n\n");
        println!("-- stdout --\n {}", out.stdout);
        println!("-- stderr --\n {}", out.stderr);

        assert!(out.stdout.contains(
            r"
3) Cancel installation
>

Rust is installed now. Great!
"
        ));
    });
}

#[test]
fn user_says_nope() {
    setup(&|config| {
        let out = run_input(config, &["rustup-init"], "n\n\n");
        assert!(out.ok);
        assert!(!config.cargodir.join("bin").exists());
    });
}

#[test]
fn with_no_modify_path() {
    setup(&|config| {
        let out = run_input(config, &["rustup-init", "--no-modify-path"], "\n\n");
        assert!(out.ok);
        assert!(out
            .stdout
            .contains("This path needs to be in your PATH environment variable"));

        if cfg!(unix) {
            assert!(!config.homedir.join(".profile").exists());
        }
    });
}

#[test]
fn with_no_toolchain() {
    setup(&|config| {
        let out = run_input(config, &["rustup-init", "--default-toolchain=none"], "\n\n");
        assert!(out.ok);

        expect_stdout_ok(config, &["rustup", "show"], "no active toolchain");
    });
}

#[test]
fn with_non_default_toolchain() {
    setup(&|config| {
        let out = run_input(
            config,
            &["rustup-init", "--default-toolchain=nightly"],
            "\n\n",
        );
        assert!(out.ok);

        expect_stdout_ok(config, &["rustup", "show"], "nightly");
    });
}

#[test]
fn with_non_release_channel_non_default_toolchain() {
    setup(&|config| {
        let out = run_input(
            config,
            &["rustup-init", "--default-toolchain=nightly-2015-01-02"],
            "\n\n",
        );
        assert!(out.ok);

        expect_stdout_ok(config, &["rustup", "show"], "nightly");
        expect_stdout_ok(config, &["rustup", "show"], "2015-01-02");
    });
}

#[test]
fn set_nightly_toolchain() {
    setup(&|config| {
        let out = run_input(config, &["rustup-init"], "2\n\nnightly\n\n\n\n\n");
        assert!(out.ok);

        expect_stdout_ok(config, &["rustup", "show"], "nightly");
    });
}

#[test]
fn set_no_modify_path() {
    setup(&|config| {
        let out = run_input(config, &["rustup-init"], "2\n\n\n\nno\n\n\n");
        assert!(out.ok);

        if cfg!(unix) {
            assert!(!config.homedir.join(".profile").exists());
        }
    });
}

#[test]
fn set_nightly_toolchain_and_unset() {
    setup(&|config| {
        let out = run_input(
            config,
            &["rustup-init"],
            "2\n\nnightly\n\n\n2\n\nbeta\n\n\n\n\n",
        );
        assert!(out.ok);

        expect_stdout_ok(config, &["rustup", "show"], "beta");
    });
}

#[test]
fn user_says_nope_after_advanced_install() {
    setup(&|config| {
        let out = run_input(config, &["rustup-init"], "2\n\n\n\n\nn\n\n\n");
        assert!(out.ok);
        assert!(!config.cargodir.join("bin").exists());
    });
}
<commit_msg>Test that toolchain installs skip missing components on rustup install<commit_after>//! Tests of the interactive console installer

pub mod mock;

use crate::mock::clitools::{
    self, expect_stdout_ok, set_current_dist_date, Config, SanitizedOutput, Scenario,
};
use crate::mock::{get_path, restore_path};
use lazy_static::lazy_static;
use std::io::Write;
use std::process::Stdio;
use std::sync::Mutex;

pub fn setup_(complex: bool, f: &dyn Fn(&Config)) {
    let scenario = if complex {
        Scenario::UnavailableRls
    } else {
        Scenario::SimpleV2
    };
    clitools::setup(scenario, &|config| {
        // Lock protects environment variables
        lazy_static! {
            static ref LOCK: Mutex<()> = Mutex::new(());
        }
        let _g = LOCK.lock();

        // An windows these tests mess with the user's PATH. Save
        // and restore them here to keep from trashing things.
        let saved_path = get_path();
        let _g = scopeguard::guard(saved_path, restore_path);

        f(config);
    });
}

pub fn setup(f: &dyn Fn(&Config)) {
    setup_(false, f)
}

fn run_input(config: &Config, args: &[&str], input: &str) -> SanitizedOutput {
    let mut cmd = clitools::cmd(config, args[0], &args[1..]);
    clitools::env(config, &mut cmd);

    cmd.stdin(Stdio::piped());
    cmd.stdout(Stdio::piped());
    cmd.stderr(Stdio::piped());
    let mut child = cmd.spawn().unwrap();

    child
        .stdin
        .as_mut()
        .unwrap()
        .write_all(input.as_bytes())
        .unwrap();
    let out = child.wait_with_output().unwrap();

    SanitizedOutput {
        ok: out.status.success(),
        stdout: String::from_utf8(out.stdout).unwrap(),
        stderr: String::from_utf8(out.stderr).unwrap(),
    }
}

#[test]
fn smoke_test() {
    setup(&|config| {
        let out = run_input(config, &["rustup-init"], "\n\n");
        assert!(out.ok);
    });
}

#[test]
fn update() {
    setup(&|config| {
        run_input(config, &["rustup-init"], "\n\n");
        let out = run_input(config, &["rustup-init"], "\n\n");
        assert!(out.ok, "stdout:\n{}\nstderr:\n{}", out.stdout, out.stderr);
    });
}

// Testing that the right number of blank lines are printed after the
// 'pre-install' message and before the 'post-install' message.
#[test]
fn blank_lines_around_stderr_log_output_install() {
    setup(&|config| {
        let out = run_input(config, &["rustup-init"], "\n\n");

        // During an interactive session, after "Press the Enter
        // key..."  the UI emits a blank line, then there is a blank
        // line that comes from the user pressing enter, then log
        // output on stderr, then an explicit blank line on stdout
        // before printing $toolchain installed
        assert!(out.stdout.contains(
            r"
3) Cancel installation
>

  stable installed - 1.1.0 (hash-stable-1.1.0)

Rust is installed now. Great!
"
        ));
    });
}

#[test]
fn blank_lines_around_stderr_log_output_update() {
    setup(&|config| {
        run_input(config, &["rustup-init"], "\n\n");
        let out = run_input(config, &["rustup-init"], "\n\n");
        println!("-- stdout --\n {}", out.stdout);
        println!("-- stderr --\n {}", out.stderr);

        assert!(out.stdout.contains(
            r"
3) Cancel installation
>

Rust is installed now. Great!
"
        ));
    });
}

#[test]
fn user_says_nope() {
    setup(&|config| {
        let out = run_input(config, &["rustup-init"], "n\n\n");
        assert!(out.ok);
        assert!(!config.cargodir.join("bin").exists());
    });
}

#[test]
fn with_no_modify_path() {
    setup(&|config| {
        let out = run_input(config, &["rustup-init", "--no-modify-path"], "\n\n");
        assert!(out.ok);
        assert!(out
            .stdout
            .contains("This path needs to be in your PATH environment variable"));

        if cfg!(unix) {
            assert!(!config.homedir.join(".profile").exists());
        }
    });
}

#[test]
fn with_no_toolchain() {
    setup(&|config| {
        let out = run_input(config, &["rustup-init", "--default-toolchain=none"], "\n\n");
        assert!(out.ok);

        expect_stdout_ok(config, &["rustup", "show"], "no active toolchain");
    });
}

#[test]
fn with_non_default_toolchain() {
    setup(&|config| {
        let out = run_input(
            config,
            &["rustup-init", "--default-toolchain=nightly"],
            "\n\n",
        );
        assert!(out.ok);

        expect_stdout_ok(config, &["rustup", "show"], "nightly");
    });
}

#[test]
fn with_non_release_channel_non_default_toolchain() {
    setup(&|config| {
        let out = run_input(
            config,
            &["rustup-init", "--default-toolchain=nightly-2015-01-02"],
            "\n\n",
        );
        assert!(out.ok);

        expect_stdout_ok(config, &["rustup", "show"], "nightly");
        expect_stdout_ok(config, &["rustup", "show"], "2015-01-02");
    });
}

#[test]
fn set_nightly_toolchain() {
    setup(&|config| {
        let out = run_input(config, &["rustup-init"], "2\n\nnightly\n\n\n\n\n");
        assert!(out.ok);

        expect_stdout_ok(config, &["rustup", "show"], "nightly");
    });
}

#[test]
fn set_no_modify_path() {
    setup(&|config| {
        let out = run_input(config, &["rustup-init"], "2\n\n\n\nno\n\n\n");
        assert!(out.ok);

        if cfg!(unix) {
            assert!(!config.homedir.join(".profile").exists());
        }
    });
}

#[test]
fn set_nightly_toolchain_and_unset() {
    setup(&|config| {
        let out = run_input(
            config,
            &["rustup-init"],
            "2\n\nnightly\n\n\n2\n\nbeta\n\n\n\n\n",
        );
        assert!(out.ok);

        expect_stdout_ok(config, &["rustup", "show"], "beta");
    });
}

#[test]
fn user_says_nope_after_advanced_install() {
    setup(&|config| {
        let out = run_input(config, &["rustup-init"], "2\n\n\n\n\nn\n\n\n");
        assert!(out.ok);
        assert!(!config.cargodir.join("bin").exists());
    });
}

#[test]
fn install_forces_and_skips_rls() {
    setup_(true, &|config| {
        set_current_dist_date(config, "2015-01-01");

        let out = run_input(
            config,
            &[
                "rustup-init",
                "--profile",
                "complete",
                "--default-toolchain",
                "nightly",
            ],
            "\n\n",
        );
        assert!(out.ok);
        assert!(out
            .stderr
            .contains("warning: Force-skipping unavailable component"));
    });
}
<|endoftext|>


<commit_before>use State;
use GLOBALSINDEX;
use Type;
use raw;

use libc;
use std::task;
use std::any::AnyRefExt;

#[test]
fn test_state_init() {
    let mut _s = State::new();
}

#[test]
#[should_fail]
fn test_error() {
    let mut s = State::new();
    s.pushinteger(42);
    s.error()
}

#[test]
fn test_errorstr() {
    let res = task::try::<()>(proc() {
        let mut s = State::new();
        s.errorstr("some err");
    });
    let err = res.unwrap_err();
    let expected = "unprotected error in call to Lua API (some err)";
    let s = err.as_ref::<String>();
    if s.is_some() {
        assert_eq!(s.unwrap().as_slice(), expected);
    } else {
        let s = err.as_ref::<&'static str>();
        if s.is_some() {
            assert_eq!(*s.unwrap(), expected);
        } else {
            fail!("unexpected failure result");
        }
    }
}

#[test]
fn test_describe() {
    let mut s = State::new();

    assert_eq!(s.typename(1), "no value");
    s.pushnil();
    assert_eq!(s.typename(-1), "nil");
    s.pushinteger(42);
    assert_eq!(s.typename(-1), "number");
    s.pushstring("test");
    assert_eq!(s.typename(-1), "string");
    s.pushboolean(true);
    assert_eq!(s.typename(-1), "boolean");
    s.pushcfunction(dummy);
    assert_eq!(s.typename(-1), "function");

    extern "C" fn dummy(_L: *mut ::raw::lua_State) -> ::libc::c_int {
        0
    }
}

#[test]
fn test_openlibs() {
    let mut s = State::new();

    s.openlibs();
    s.getfield(GLOBALSINDEX, "table");
    assert_eq!(s.type_(-1), Some(Type::Table));
}

#[deriving(PartialEq,Eq,Show)]
enum CheckOptionEnum {
    COEOne,
    COETwo,
    COEThree
}

#[test]
fn test_checkoption() {
    let lst = [("one", COEOne), ("two", COETwo), ("three", COEThree)];

    let mut s = State::new();

    for &(k,ref v) in lst.iter() {
        s.pushstring(k);
        assert_eq!(*s.checkoption(1, None, lst), *v);
        s.pop(1);
    }
    assert_eq!(*s.checkoption(1, Some("three"), lst), COEThree);

    let res = task::try(proc() {
        let mut s = State::new();
        s.checkoption(1, None, lst);
    });
    assert!(res.is_err(), "expected error from checkoption");

    let res = task::try(proc() {
        let mut s = State::new();
        s.checkoption(1, Some("four"), lst);
    });
    assert!(res.is_err(), "expected error from checkoption");
}

#[test]
fn test_tocfunction() {
    let mut s = State::new();

    // extern "C" fns don't implement Eq, so cast them to a pointer instead

    s.pushstring("foo");
    assert_eq!(s.tocfunction(1).map(|f| f as *()), None);

    s.pushcfunction(cfunc);
    assert_eq!(s.tocfunction(2).map(|f| f as *()), Some(cfunc as *()));

    extern "C" fn cfunc(_L: *mut raw::lua_State) -> libc::c_int { 0 }
}

#[test]
fn test_gsub() {
    // do some pretty basic gsub tests
    let mut L = State::new();

    assert_eq!(L.gsub("foobar", "bar", "quux"), "fooquux");
    assert_eq!(L.gsub("foo", "o", "ö"), "föö");
    assert_eq!(L.gsub("test", "a", "b"), "test");
    assert_eq!(L.gsub("a b c d e", " ", "."), "a.b.c.d.e");
}
<commit_msg>Fix tests for rust nightly<commit_after>use State;
use GLOBALSINDEX;
use Type;
use raw;

use libc;
use std::task;
use std::any::AnyRefExt;

#[test]
fn test_state_init() {
    let mut _s = State::new();
}

#[test]
#[should_fail]
fn test_error() {
    let mut s = State::new();
    s.pushinteger(42);
    s.error()
}

#[test]
fn test_errorstr() {
    let res = task::try::<()>(proc() {
        let mut s = State::new();
        s.errorstr("some err");
    });
    let err = res.unwrap_err();
    let expected = "unprotected error in call to Lua API (some err)";
    let s = err.downcast_ref::<String>();
    if s.is_some() {
        assert_eq!(s.unwrap().as_slice(), expected);
    } else {
        let s = err.downcast_ref::<&'static str>();
        if s.is_some() {
            assert_eq!(*s.unwrap(), expected);
        } else {
            fail!("unexpected failure result");
        }
    }
}

#[test]
fn test_describe() {
    let mut s = State::new();

    assert_eq!(s.typename(1), "no value");
    s.pushnil();
    assert_eq!(s.typename(-1), "nil");
    s.pushinteger(42);
    assert_eq!(s.typename(-1), "number");
    s.pushstring("test");
    assert_eq!(s.typename(-1), "string");
    s.pushboolean(true);
    assert_eq!(s.typename(-1), "boolean");
    s.pushcfunction(dummy);
    assert_eq!(s.typename(-1), "function");

    extern "C" fn dummy(_L: *mut ::raw::lua_State) -> ::libc::c_int {
        0
    }
}

#[test]
fn test_openlibs() {
    let mut s = State::new();

    s.openlibs();
    s.getfield(GLOBALSINDEX, "table");
    assert_eq!(s.type_(-1), Some(Type::Table));
}

#[deriving(PartialEq,Eq,Show)]
enum CheckOptionEnum {
    COEOne,
    COETwo,
    COEThree
}

#[test]
fn test_checkoption() {
    let lst = [("one", COEOne), ("two", COETwo), ("three", COEThree)];

    let mut s = State::new();

    for &(k,ref v) in lst.iter() {
        s.pushstring(k);
        assert_eq!(*s.checkoption(1, None, lst), *v);
        s.pop(1);
    }
    assert_eq!(*s.checkoption(1, Some("three"), lst), COEThree);

    let res = task::try(proc() {
        let mut s = State::new();
        s.checkoption(1, None, lst);
    });
    assert!(res.is_err(), "expected error from checkoption");

    let res = task::try(proc() {
        let mut s = State::new();
        s.checkoption(1, Some("four"), lst);
    });
    assert!(res.is_err(), "expected error from checkoption");
}

#[test]
fn test_tocfunction() {
    let mut s = State::new();

    // extern "C" fns don't implement Eq, so cast them to a pointer instead

    s.pushstring("foo");
    assert_eq!(s.tocfunction(1).map(|f| f as *const ()), None);

    s.pushcfunction(cfunc);
    assert_eq!(s.tocfunction(2).map(|f| f as *const ()), Some(cfunc as *const ()));

    extern "C" fn cfunc(_L: *mut raw::lua_State) -> libc::c_int { 0 }
}

#[test]
fn test_gsub() {
    // do some pretty basic gsub tests
    let mut L = State::new();

    assert_eq!(L.gsub("foobar", "bar", "quux"), "fooquux");
    assert_eq!(L.gsub("foo", "o", "ö"), "föö");
    assert_eq!(L.gsub("test", "a", "b"), "test");
    assert_eq!(L.gsub("a b c d e", " ", "."), "a.b.c.d.e");
}
<|endoftext|>


<commit_before>use std::{
    collections::HashMap,
    fs,
    path::{Path, PathBuf},
};

use clap::{App, Arg, SubCommand};
use failure::bail;

use tools::{
    collect_tests, generate,install_format_hook, run, run_rustfmt,
    Mode, Overwrite, Result, Test, Verify, project_root, run_fuzzer
};

const GRAMMAR_DIR: &str = "crates/ra_syntax/src/grammar";
const OK_INLINE_TESTS_DIR: &str = "crates/ra_syntax/tests/data/parser/inline/ok";
const ERR_INLINE_TESTS_DIR: &str = "crates/ra_syntax/tests/data/parser/inline/err";

fn main() -> Result<()> {
    let matches = App::new("tasks")
        .setting(clap::AppSettings::SubcommandRequiredElseHelp)
        .arg(
            Arg::with_name("verify")
                .long("--verify")
                .help("Verify that generated code is up-to-date")
                .global(true),
        )
        .subcommand(SubCommand::with_name("gen-syntax"))
        .subcommand(SubCommand::with_name("gen-tests"))
        .subcommand(SubCommand::with_name("install-code"))
        .subcommand(SubCommand::with_name("format"))
        .subcommand(SubCommand::with_name("format-hook"))
        .subcommand(SubCommand::with_name("fuzz-tests"))
        .get_matches();
    let mode = if matches.is_present("verify") {
        Verify
    } else {
        Overwrite
    };
    match matches
        .subcommand_name()
        .expect("Subcommand must be specified")
    {
        "install-code" => install_code_extension()?,
        "gen-tests" => gen_tests(mode)?,
        "gen-syntax" => generate(Overwrite)?,
        "format" => run_rustfmt(mode)?,
        "format-hook" => install_format_hook()?,
        "fuzz-tests" => run_fuzzer()?,
        _ => unreachable!(),
    }
    Ok(())
}

fn gen_tests(mode: Mode) -> Result<()> {
    let tests = tests_from_dir(Path::new(GRAMMAR_DIR))?;
    fn install_tests(tests: &HashMap<String, Test>, into: &str, mode: Mode) -> Result<()> {
        let tests_dir = project_root().join(into);
        if !tests_dir.is_dir() {
            fs::create_dir_all(&tests_dir)?;
        }
        // ok is never actually read, but it needs to be specified to create a Test in existing_tests
        let existing = existing_tests(&tests_dir, true)?;
        for t in existing.keys().filter(|&t| !tests.contains_key(t)) {
            panic!("Test is deleted: {}", t);
        }

        let mut new_idx = existing.len() + 1;
        for (name, test) in tests {
            let path = match existing.get(name) {
                Some((path, _test)) => path.clone(),
                None => {
                    let file_name = format!("{:04}_{}.rs", new_idx, name);
                    new_idx += 1;
                    tests_dir.join(file_name)
                }
            };
            teraron::update(&path, &test.text, mode)?;
        }
        Ok(())
    }
    install_tests(&tests.ok, OK_INLINE_TESTS_DIR, mode)?;
    install_tests(&tests.err, ERR_INLINE_TESTS_DIR, mode)
}

#[derive(Default, Debug)]
struct Tests {
    pub ok: HashMap<String, Test>,
    pub err: HashMap<String, Test>,
}

fn tests_from_dir(dir: &Path) -> Result<Tests> {
    let mut res = Tests::default();
    for entry in ::walkdir::WalkDir::new(dir) {
        let entry = entry.unwrap();
        if !entry.file_type().is_file() {
            continue;
        }
        if entry.path().extension().unwrap_or_default() != "rs" {
            continue;
        }
        process_file(&mut res, entry.path())?;
    }
    let grammar_rs = dir.parent().unwrap().join("grammar.rs");
    process_file(&mut res, &grammar_rs)?;
    return Ok(res);
    fn process_file(res: &mut Tests, path: &Path) -> Result<()> {
        let text = fs::read_to_string(path)?;

        for (_, test) in collect_tests(&text) {
            if test.ok {
                if let Some(old_test) = res.ok.insert(test.name.clone(), test) {
                    bail!("Duplicate test: {}", old_test.name)
                }
            } else {
                if let Some(old_test) = res.err.insert(test.name.clone(), test) {
                    bail!("Duplicate test: {}", old_test.name)
                }
            }
        }
        Ok(())
    }
}

fn existing_tests(dir: &Path, ok: bool) -> Result<HashMap<String, (PathBuf, Test)>> {
    let mut res = HashMap::new();
    for file in fs::read_dir(dir)? {
        let file = file?;
        let path = file.path();
        if path.extension().unwrap_or_default() != "rs" {
            continue;
        }
        let name = {
            let file_name = path.file_name().unwrap().to_str().unwrap();
            file_name[5..file_name.len() - 3].to_string()
        };
        let text = fs::read_to_string(&path)?;
        let test = Test {
            name: name.clone(),
            text,
            ok,
        };
        if let Some(old) = res.insert(name, (path, test)) {
            println!("Duplicate test: {:?}", old);
        }
    }
    Ok(res)
}

fn install_code_extension() -> Result<()> {
    run("cargo install --path crates/ra_lsp_server --force", ".")?;
    if cfg!(windows) {
        run(r"cmd.exe /c npm.cmd install", "./editors/code")?;
        run(r"cmd.exe /c npm.cmd run package", "./editors/code")?;
    } else {
        run(r"npm install", "./editors/code")?;
        run(r"npm run package", "./editors/code")?;
    }
    if cfg!(windows) {
        run(
            r"cmd.exe /c code.cmd --install-extension ./ra-lsp-0.0.1.vsix",
            "./editors/code",
        )?;
    } else {
        run(
            r"code --install-extension ./ra-lsp-0.0.1.vsix",
            "./editors/code",
        )?;
    }
    Ok(())
}
<commit_msg>Use --force when installing the VSIX.<commit_after>use std::{
    collections::HashMap,
    fs,
    path::{Path, PathBuf},
};

use clap::{App, Arg, SubCommand};
use failure::bail;

use tools::{
    collect_tests, generate,install_format_hook, run, run_rustfmt,
    Mode, Overwrite, Result, Test, Verify, project_root, run_fuzzer
};

const GRAMMAR_DIR: &str = "crates/ra_syntax/src/grammar";
const OK_INLINE_TESTS_DIR: &str = "crates/ra_syntax/tests/data/parser/inline/ok";
const ERR_INLINE_TESTS_DIR: &str = "crates/ra_syntax/tests/data/parser/inline/err";

fn main() -> Result<()> {
    let matches = App::new("tasks")
        .setting(clap::AppSettings::SubcommandRequiredElseHelp)
        .arg(
            Arg::with_name("verify")
                .long("--verify")
                .help("Verify that generated code is up-to-date")
                .global(true),
        )
        .subcommand(SubCommand::with_name("gen-syntax"))
        .subcommand(SubCommand::with_name("gen-tests"))
        .subcommand(SubCommand::with_name("install-code"))
        .subcommand(SubCommand::with_name("format"))
        .subcommand(SubCommand::with_name("format-hook"))
        .subcommand(SubCommand::with_name("fuzz-tests"))
        .get_matches();
    let mode = if matches.is_present("verify") {
        Verify
    } else {
        Overwrite
    };
    match matches
        .subcommand_name()
        .expect("Subcommand must be specified")
    {
        "install-code" => install_code_extension()?,
        "gen-tests" => gen_tests(mode)?,
        "gen-syntax" => generate(Overwrite)?,
        "format" => run_rustfmt(mode)?,
        "format-hook" => install_format_hook()?,
        "fuzz-tests" => run_fuzzer()?,
        _ => unreachable!(),
    }
    Ok(())
}

fn gen_tests(mode: Mode) -> Result<()> {
    let tests = tests_from_dir(Path::new(GRAMMAR_DIR))?;
    fn install_tests(tests: &HashMap<String, Test>, into: &str, mode: Mode) -> Result<()> {
        let tests_dir = project_root().join(into);
        if !tests_dir.is_dir() {
            fs::create_dir_all(&tests_dir)?;
        }
        // ok is never actually read, but it needs to be specified to create a Test in existing_tests
        let existing = existing_tests(&tests_dir, true)?;
        for t in existing.keys().filter(|&t| !tests.contains_key(t)) {
            panic!("Test is deleted: {}", t);
        }

        let mut new_idx = existing.len() + 1;
        for (name, test) in tests {
            let path = match existing.get(name) {
                Some((path, _test)) => path.clone(),
                None => {
                    let file_name = format!("{:04}_{}.rs", new_idx, name);
                    new_idx += 1;
                    tests_dir.join(file_name)
                }
            };
            teraron::update(&path, &test.text, mode)?;
        }
        Ok(())
    }
    install_tests(&tests.ok, OK_INLINE_TESTS_DIR, mode)?;
    install_tests(&tests.err, ERR_INLINE_TESTS_DIR, mode)
}

#[derive(Default, Debug)]
struct Tests {
    pub ok: HashMap<String, Test>,
    pub err: HashMap<String, Test>,
}

fn tests_from_dir(dir: &Path) -> Result<Tests> {
    let mut res = Tests::default();
    for entry in ::walkdir::WalkDir::new(dir) {
        let entry = entry.unwrap();
        if !entry.file_type().is_file() {
            continue;
        }
        if entry.path().extension().unwrap_or_default() != "rs" {
            continue;
        }
        process_file(&mut res, entry.path())?;
    }
    let grammar_rs = dir.parent().unwrap().join("grammar.rs");
    process_file(&mut res, &grammar_rs)?;
    return Ok(res);
    fn process_file(res: &mut Tests, path: &Path) -> Result<()> {
        let text = fs::read_to_string(path)?;

        for (_, test) in collect_tests(&text) {
            if test.ok {
                if let Some(old_test) = res.ok.insert(test.name.clone(), test) {
                    bail!("Duplicate test: {}", old_test.name)
                }
            } else {
                if let Some(old_test) = res.err.insert(test.name.clone(), test) {
                    bail!("Duplicate test: {}", old_test.name)
                }
            }
        }
        Ok(())
    }
}

fn existing_tests(dir: &Path, ok: bool) -> Result<HashMap<String, (PathBuf, Test)>> {
    let mut res = HashMap::new();
    for file in fs::read_dir(dir)? {
        let file = file?;
        let path = file.path();
        if path.extension().unwrap_or_default() != "rs" {
            continue;
        }
        let name = {
            let file_name = path.file_name().unwrap().to_str().unwrap();
            file_name[5..file_name.len() - 3].to_string()
        };
        let text = fs::read_to_string(&path)?;
        let test = Test {
            name: name.clone(),
            text,
            ok,
        };
        if let Some(old) = res.insert(name, (path, test)) {
            println!("Duplicate test: {:?}", old);
        }
    }
    Ok(res)
}

fn install_code_extension() -> Result<()> {
    run("cargo install --path crates/ra_lsp_server --force", ".")?;
    if cfg!(windows) {
        run(r"cmd.exe /c npm.cmd install", "./editors/code")?;
        run(r"cmd.exe /c npm.cmd run package", "./editors/code")?;
    } else {
        run(r"npm install", "./editors/code")?;
        run(r"npm run package", "./editors/code")?;
    }
    if cfg!(windows) {
        run(
            r"cmd.exe /c code.cmd --install-extension ./ra-lsp-0.0.1.vsix --force",
            "./editors/code",
        )?;
    } else {
        run(
            r"code --install-extension ./ra-lsp-0.0.1.vsix --force",
            "./editors/code",
        )?;
    }
    Ok(())
}
<|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::cmp;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use std::error::Error;
use std::mem;
use std::sync::Arc;
use smallvec::SmallVec;

use buffer::Buffer;
use command_buffer::cb::CommandsListBuildPrimaryPool;
use command_buffer::cb::Flags;
use command_buffer::cb::Kind;
use command_buffer::cb::UnsyncedCommandBuffer;
use command_buffer::pool::CommandPool;
use command_buffer::submit::Submit;
use command_buffer::submit::SubmitBuilder;
use command_buffer::CommandsList;
use command_buffer::CommandsListSink;
use command_buffer::CommandsListSinkCaller;
use command_buffer::PipelineBarrierBuilder;
use command_buffer::SecondaryCommandBuffer;
use device::Device;
use device::Queue;
use image::Layout;
use image::Image;
use sync::AccessFlagBits;
use sync::PipelineStages;
use VulkanObject;
use vk;

use OomError;

pub struct AutobarriersCommandBuffer<L, P> where P: CommandPool {
    // The actual command buffer.
    inner: UnsyncedCommandBuffer<WrappedCommandsList<L>, P>
}

impl<L, P> CommandsListBuildPrimaryPool<L, P> for AutobarriersCommandBuffer<L, P>
    where L: CommandsList, P: CommandPool
{
    fn build_primary_with_pool(pool: P, list: L)
                               -> Result<AutobarriersCommandBuffer<L, P>, OomError>
        where Self: Sized
    {
        let kind = Kind::primary();
        let flags = Flags::SimultaneousUse;

        let cmd = unsafe {
            let device = pool.device().clone();
            try!(UnsyncedCommandBuffer::new(WrappedCommandsList(list, device), pool, kind, flags))
        };

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

unsafe impl<L, P> Submit for AutobarriersCommandBuffer<L, P>
    where L: CommandsList, P: CommandPool
{
    #[inline]
    fn device(&self) -> &Arc<Device> {
        self.inner.device()
    }

    unsafe fn append_submission<'a>(&'a self, base: SubmitBuilder<'a>, queue: &Arc<Queue>)
                                    -> Result<SubmitBuilder<'a>, Box<Error>>
    {
        // FIXME: totally unsynchronized here
        Ok(base.add_command_buffer(&self.inner))
    }
}

// TODO: we're not necessarily a secondary command buffer
unsafe impl<L, P> SecondaryCommandBuffer for AutobarriersCommandBuffer<L, P>
    where L: CommandsList, P: CommandPool
{
    #[inline]
    fn inner(&self) -> vk::CommandBuffer {
        self.inner.internal_object()
    }

    #[inline]
    fn device(&self) -> &Arc<Device> {
        self.inner.device()
    }

    #[inline]
    fn append<'a>(&'a self, builder: &mut CommandsListSink<'a>) {
        self.inner.commands_list().append(builder);
    }
}

struct WrappedCommandsList<L>(L, Arc<Device>);
unsafe impl<L> CommandsList for WrappedCommandsList<L> where L: CommandsList {
    #[inline]
    fn append<'a>(&'a self, builder: &mut CommandsListSink<'a>) {
        let mut sink = Sink {
            output: builder,
            device: &self.1,
            accesses: HashMap::new(),
            pending_accesses: HashMap::new(),
            pending_commands: Vec::new(),
        };

        self.0.append(&mut sink);
        sink.flush();
    }
}

// Helper object for AutobarriersCommandBuffer. Implementation detail.
//
// This object is created in a local scope when the command is built, and destroyed after all the
// commands have been passed through.
struct Sink<'c: 'o, 'o> {
    output: &'o mut CommandsListSink<'c>,
    device: &'o Arc<Device>,
    accesses: HashMap<u64, SmallVec<[Element<'c>; 2]>>,
    pending_accesses: HashMap<u64, SmallVec<[Element<'c>; 2]>>,
    pending_commands: Vec<Box<CommandsListSinkCaller<'c> + 'c>>,
}

impl<'c: 'o, 'o> Sink<'c, 'o> {
    fn flush(&mut self) {
        let mut pipeline_barrier = PipelineBarrierBuilder::new();

        for (key, accesses) in self.pending_accesses.drain() {
            let prev_accesses = match self.accesses.entry(key) {
                Entry::Occupied(e) => e.into_mut(),     // TODO: for images, need to transition from initial layout
                Entry::Vacant(e) => { e.insert(accesses); continue; }
            };

            for prev_access in mem::replace(prev_accesses, SmallVec::new()).into_iter() {
                let mut found_conflict = false;

                for access in accesses.iter() {
                    match (&prev_access.inner, &access.inner) {
                        (&ElementInner::Buffer { buffer: old_buffer, offset: old_offset,
                                                 size: old_size, write: old_write },
                         &ElementInner::Buffer { buffer: new_buffer, offset: new_offset,
                                                 size: new_size, write: new_write }) =>
                        {
                            if !old_buffer.conflicts_buffer(old_offset, old_size, old_write,
                                                            new_buffer, new_offset, new_size,
                                                            new_write)
                            {
                                continue;
                            }

                            found_conflict = true;

                            if !old_write {
                                unsafe {
                                    pipeline_barrier.add_execution_dependency(prev_access.stages,
                                                                              access.stages, true);
                                }
                            } else {
                                let real_offset = cmp::min(old_offset, new_offset);
                                let real_size = if old_offset < new_offset {
                                    cmp::max(old_size, new_size + (new_offset - old_offset))
                                } else {
                                    cmp::max(new_size, old_size + (old_offset - new_offset))
                                };

                                unsafe {
                                    pipeline_barrier.add_buffer_memory_barrier(old_buffer, prev_access.stages,
                                                                               prev_access.access, access.stages,
                                                                               access.access, true, None,
                                                                               real_offset, real_size);
                                }
                            }
                        },
                    }
                }

                if !found_conflict {
                    prev_accesses.push(prev_access);
                }
            }

            for access in accesses.into_iter() {
                prev_accesses.push(access);
            }
        }

        pipeline_barrier.append_to(self.output);
        for cmd in self.pending_commands.drain(..) {
            self.output.add_command(cmd);
        }
    }
}

impl<'c: 'o, 'o> CommandsListSink<'c> for Sink<'c, 'o> {
    #[inline]
    fn device(&self) -> &Arc<Device> {
        self.device
    }

    #[inline]
    fn add_command(&mut self, f: Box<CommandsListSinkCaller<'c> + 'c>) {
        self.pending_commands.push(f);
    }

    #[inline]
    fn add_buffer_transition(&mut self, buffer: &'c Buffer, offset: usize, size: usize, write: bool,
                             stages: PipelineStages, access: AccessFlagBits)
    {
        let key = buffer.conflict_key(offset, size, write);

        let element = Element {
            stages: stages,
            access: access,
            inner: ElementInner::Buffer {
                buffer: buffer,
                offset: offset,
                size: size,
                write: write,
            },
        };

        if self.pending_accesses.get(&key).map(|l| l.iter().any(|e| e.conflicts(&element))).unwrap_or(false) {
            self.flush();
        }

        self.pending_accesses.entry(key).or_insert_with(|| SmallVec::new()).push(element);
    }

    #[inline]
    fn add_image_transition(&mut self, _: &Image, _: u32, _: u32, _: u32, _: u32,
                            _: bool, _: Layout, _: PipelineStages, _: AccessFlagBits)
    {
        // FIXME: unimplemented
    }

    #[inline]
    fn add_image_transition_notification(&mut self, _: &Image, _: u32, _: u32, _: u32,
                                         _: u32, _: Layout, _: PipelineStages, _: AccessFlagBits)
    {
        // FIXME: unimplemented
    }
}

#[derive(Clone)]
struct Element<'a> {
    stages: PipelineStages,
    access: AccessFlagBits,
    inner: ElementInner<'a>,
}

impl<'a> Element<'a> {
    fn conflicts(&self, other: &Element<'a>) -> bool {
        match (&self.inner, &other.inner) {
            (&ElementInner::Buffer { buffer: self_buffer, offset: self_offset, size: self_size,
                                     write: self_write },
             &ElementInner::Buffer { buffer: other_buffer, offset: other_offset, size: other_size,
                                     write: other_write }) =>
            {
                 self_buffer.conflicts_buffer(self_offset, self_size, self_write, other_buffer,
                                              other_offset, other_size, other_write)
            },
        }
    }
}

#[derive(Clone)]
enum ElementInner<'a> {
    Buffer {
        buffer: &'a Buffer,
        offset: usize,
        size: usize,
        write: bool,
    },
    // Image { .. }
}
<commit_msg>Add images to the autobarrier<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::cmp;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use std::error::Error;
use std::mem;
use std::sync::Arc;
use smallvec::SmallVec;

use buffer::Buffer;
use command_buffer::cb::CommandsListBuildPrimaryPool;
use command_buffer::cb::Flags;
use command_buffer::cb::Kind;
use command_buffer::cb::UnsyncedCommandBuffer;
use command_buffer::pool::CommandPool;
use command_buffer::submit::Submit;
use command_buffer::submit::SubmitBuilder;
use command_buffer::CommandsList;
use command_buffer::CommandsListSink;
use command_buffer::CommandsListSinkCaller;
use command_buffer::PipelineBarrierBuilder;
use command_buffer::SecondaryCommandBuffer;
use device::Device;
use device::Queue;
use image::Layout;
use image::Image;
use sync::AccessFlagBits;
use sync::PipelineStages;
use VulkanObject;
use vk;

use OomError;

pub struct AutobarriersCommandBuffer<L, P> where P: CommandPool {
    // The actual command buffer.
    inner: UnsyncedCommandBuffer<WrappedCommandsList<L>, P>
}

impl<L, P> CommandsListBuildPrimaryPool<L, P> for AutobarriersCommandBuffer<L, P>
    where L: CommandsList, P: CommandPool
{
    fn build_primary_with_pool(pool: P, list: L)
                               -> Result<AutobarriersCommandBuffer<L, P>, OomError>
        where Self: Sized
    {
        let kind = Kind::primary();
        let flags = Flags::SimultaneousUse;

        let cmd = unsafe {
            let device = pool.device().clone();
            try!(UnsyncedCommandBuffer::new(WrappedCommandsList(list, device), pool, kind, flags))
        };

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

unsafe impl<L, P> Submit for AutobarriersCommandBuffer<L, P>
    where L: CommandsList, P: CommandPool
{
    #[inline]
    fn device(&self) -> &Arc<Device> {
        self.inner.device()
    }

    unsafe fn append_submission<'a>(&'a self, base: SubmitBuilder<'a>, queue: &Arc<Queue>)
                                    -> Result<SubmitBuilder<'a>, Box<Error>>
    {
        // FIXME: totally unsynchronized here
        Ok(base.add_command_buffer(&self.inner))
    }
}

// TODO: we're not necessarily a secondary command buffer
unsafe impl<L, P> SecondaryCommandBuffer for AutobarriersCommandBuffer<L, P>
    where L: CommandsList, P: CommandPool
{
    #[inline]
    fn inner(&self) -> vk::CommandBuffer {
        self.inner.internal_object()
    }

    #[inline]
    fn device(&self) -> &Arc<Device> {
        self.inner.device()
    }

    #[inline]
    fn append<'a>(&'a self, builder: &mut CommandsListSink<'a>) {
        self.inner.commands_list().append(builder);
    }
}

struct WrappedCommandsList<L>(L, Arc<Device>);
unsafe impl<L> CommandsList for WrappedCommandsList<L> where L: CommandsList {
    #[inline]
    fn append<'a>(&'a self, builder: &mut CommandsListSink<'a>) {
        let mut sink = Sink {
            output: builder,
            device: &self.1,
            accesses: HashMap::new(),
            pending_accesses: HashMap::new(),
            pending_commands: Vec::new(),
        };

        self.0.append(&mut sink);
        sink.flush();
    }
}

// Helper object for AutobarriersCommandBuffer. Implementation detail.
//
// This object is created in a local scope when the command is built, and destroyed after all the
// commands have been passed through.
struct Sink<'c: 'o, 'o> {
    output: &'o mut CommandsListSink<'c>,
    device: &'o Arc<Device>,
    accesses: HashMap<u64, SmallVec<[Element<'c>; 2]>>,
    pending_accesses: HashMap<u64, SmallVec<[Element<'c>; 2]>>,
    pending_commands: Vec<Box<CommandsListSinkCaller<'c> + 'c>>,
}

impl<'c: 'o, 'o> Sink<'c, 'o> {
    fn flush(&mut self) {
        let mut pipeline_barrier = PipelineBarrierBuilder::new();

        for (key, accesses) in self.pending_accesses.drain() {
            let prev_accesses = match self.accesses.entry(key) {
                Entry::Occupied(e) => e.into_mut(),     // TODO: for images, need to transition from initial layout
                Entry::Vacant(e) => { e.insert(accesses); continue; }
            };

            for prev_access in mem::replace(prev_accesses, SmallVec::new()).into_iter() {
                let mut found_conflict = false;

                for access in accesses.iter() {
                    match (&prev_access.inner, &access.inner) {
                        (&ElementInner::Buffer { buffer: old_buffer, offset: old_offset,
                                                 size: old_size, write: old_write },
                         &ElementInner::Buffer { buffer: new_buffer, offset: new_offset,
                                                 size: new_size, write: new_write }) =>
                        {
                            if !old_buffer.conflicts_buffer(old_offset, old_size, old_write,
                                                            new_buffer, new_offset, new_size,
                                                            new_write)
                            {
                                continue;
                            }

                            found_conflict = true;

                            if !old_write {
                                unsafe {
                                    pipeline_barrier.add_execution_dependency(prev_access.stages,
                                                                              access.stages, true);
                                }
                            } else {
                                let real_offset = cmp::min(old_offset, new_offset);
                                let real_size = if old_offset < new_offset {
                                    cmp::max(old_size, new_size + (new_offset - old_offset))
                                } else {
                                    cmp::max(new_size, old_size + (old_offset - new_offset))
                                };

                                unsafe {
                                    pipeline_barrier.add_buffer_memory_barrier(old_buffer, prev_access.stages,
                                                                               prev_access.access, access.stages,
                                                                               access.access, true, None,
                                                                               real_offset, real_size);
                                }
                            }
                        },

                        (&ElementInner::Image { image: self_image, first_layer: self_fl, num_layers: self_nl,
                                                first_mipmap: self_fm, num_mipmaps: self_nm,
                                                write: self_write, layout: self_layout },
                         &ElementInner::Image { image: other_image, first_layer: other_fl, num_layers: other_nl,
                                                first_mipmap: other_fm, num_mipmaps: other_nm,
                                                write: other_write, layout: other_layout }) =>
                        {
                            if self_layout == other_layout &&
                                !self_image.conflicts_image(self_fl, self_nl, self_fm, self_nm, self_write,
                                                            other_image, other_fl, other_nl, other_fm, other_nm,
                                                            other_write)
                            {
                                continue;
                            }

                            found_conflict = true;

                            if !self_write && self_layout == other_layout {
                                unsafe {
                                    pipeline_barrier.add_execution_dependency(prev_access.stages,
                                                                              access.stages, true);
                                }
                            } else {
                                let real_first_layer = cmp::min(self_fl, other_fl);
                                let real_num_layers = if self_fl < other_fl {
                                    cmp::max(self_nl, other_nl + (other_fl - self_fl))
                                } else {
                                    cmp::max(other_nl, self_nl + (self_fl - other_fl))
                                };

                                let real_first_mipmap = cmp::min(self_fm, other_fm);
                                let real_num_mipmaps = if self_fm < other_fm {
                                    cmp::max(self_nm, other_nm + (other_fm - self_fm))
                                } else {
                                    cmp::max(other_nm, self_nm + (self_fm - other_fm))
                                };

                                unsafe {
                                    pipeline_barrier.add_image_memory_barrier(self_image, real_first_layer .. real_first_layer + real_num_layers,
                                                                              real_first_mipmap .. real_first_mipmap + real_num_mipmaps, prev_access.stages,
                                                                              prev_access.access, access.stages,
                                                                              access.access, true, None,
                                                                              self_layout, other_layout);
                                }
                            }
                        },

                        (&ElementInner::Buffer { buffer, offset, size, write: self_write },
                         &ElementInner::Image { image, first_layer, num_layers, first_mipmap, num_mipmaps,
                                                write: other_write, .. }) |
                        (&ElementInner::Image { image, first_layer, num_layers, first_mipmap, num_mipmaps,
                                                write: other_write, .. },
                         &ElementInner::Buffer { buffer, offset, size, write: self_write }) =>
                        {
                            if !buffer.conflicts_image(offset, size, self_write, image, first_layer, num_layers,
                                                       first_mipmap, num_mipmaps, other_write)
                            {
                                continue;
                            }

                            //found_conflict = true;    // there's a warning if we uncomment that
                            unimplemented!()        // TODO:
                        },
                    }
                }

                if !found_conflict {
                    prev_accesses.push(prev_access);
                }
            }

            for access in accesses.into_iter() {
                prev_accesses.push(access);
            }
        }

        pipeline_barrier.append_to(self.output);
        for cmd in self.pending_commands.drain(..) {
            self.output.add_command(cmd);
        }
    }
}

impl<'c: 'o, 'o> CommandsListSink<'c> for Sink<'c, 'o> {
    #[inline]
    fn device(&self) -> &Arc<Device> {
        self.device
    }

    #[inline]
    fn add_command(&mut self, f: Box<CommandsListSinkCaller<'c> + 'c>) {
        self.pending_commands.push(f);
    }

    #[inline]
    fn add_buffer_transition(&mut self, buffer: &'c Buffer, offset: usize, size: usize, write: bool,
                             stages: PipelineStages, access: AccessFlagBits)
    {
        let key = buffer.conflict_key(offset, size, write);

        let element = Element {
            stages: stages,
            access: access,
            inner: ElementInner::Buffer {
                buffer: buffer,
                offset: offset,
                size: size,
                write: write,
            },
        };

        if self.pending_accesses.get(&key).map(|l| l.iter().any(|e| e.conflicts(&element))).unwrap_or(false) {
            self.flush();
        }

        self.pending_accesses.entry(key).or_insert_with(|| SmallVec::new()).push(element);
    }

    #[inline]
    fn add_image_transition(&mut self, image: &'c Image, first_layer: u32, num_layers: u32,
                            first_mipmap: u32, num_mipmaps: u32, write: bool, layout: Layout,
                            stages: PipelineStages, access: AccessFlagBits)
    {
        let key = image.conflict_key(first_layer, num_layers, first_mipmap, num_mipmaps, write);

        let element = Element {
            stages: stages,
            access: access,
            inner: ElementInner::Image {
                image: image,
                first_layer: first_layer,
                num_layers: num_layers,
                first_mipmap: first_mipmap,
                num_mipmaps: num_mipmaps,
                write: write,
                layout: layout,
            },
        };

        if self.pending_accesses.get(&key).map(|l| l.iter().any(|e| e.conflicts(&element))).unwrap_or(false) {
            self.flush();
        }

        self.pending_accesses.entry(key).or_insert_with(|| SmallVec::new()).push(element);
    }

    #[inline]
    fn add_image_transition_notification(&mut self, _: &Image, _: u32, _: u32, _: u32,
                                         _: u32, _: Layout, _: PipelineStages, _: AccessFlagBits)
    {
        // FIXME: unimplemented
    }
}

#[derive(Clone)]
struct Element<'a> {
    stages: PipelineStages,
    access: AccessFlagBits,
    inner: ElementInner<'a>,
}

impl<'a> Element<'a> {
    fn conflicts(&self, other: &Element<'a>) -> bool {
        match (&self.inner, &other.inner) {
            (&ElementInner::Buffer { buffer: self_buffer, offset: self_offset, size: self_size,
                                     write: self_write },
             &ElementInner::Buffer { buffer: other_buffer, offset: other_offset, size: other_size,
                                     write: other_write }) =>
            {
                self_buffer.conflicts_buffer(self_offset, self_size, self_write, other_buffer,
                                             other_offset, other_size, other_write)
            },

            (&ElementInner::Buffer { buffer, offset, size, write: self_write },
             &ElementInner::Image { image, first_layer, num_layers, first_mipmap, num_mipmaps,
                                    write: other_write, .. }) |
            (&ElementInner::Image { image, first_layer, num_layers, first_mipmap, num_mipmaps,
                                    write: other_write, .. },
             &ElementInner::Buffer { buffer, offset, size, write: self_write }) =>
            {
                buffer.conflicts_image(offset, size, self_write, image, first_layer, num_layers,
                                       first_mipmap, num_mipmaps, other_write)
            },

            (&ElementInner::Image { image: self_image, first_layer: self_fl, num_layers: self_nl,
                                    first_mipmap: self_fm, num_mipmaps: self_nm,
                                    write: self_write, layout: self_layout },
             &ElementInner::Image { image: other_image, first_layer: other_fl, num_layers: other_nl,
                                    first_mipmap: other_fm, num_mipmaps: other_nm,
                                    write: other_write, layout: other_layout }) =>
            {
                self_layout != other_layout ||
                    self_image.conflicts_image(self_fl, self_nl, self_fm, self_nm, self_write,
                                               other_image, other_fl, other_nl, other_fm, other_nm,
                                               other_write)
            },
        }
    }
}

#[derive(Clone)]
enum ElementInner<'a> {
    Buffer {
        buffer: &'a Buffer,
        offset: usize,
        size: usize,
        write: bool,
    },
    Image {
        image: &'a Image,
        first_layer: u32,
        num_layers: u32,
        first_mipmap: u32,
        num_mipmaps: u32,
        write: bool,
        layout: Layout,
    },
}
<|endoftext|>


<commit_before>pub use std::libc::*;
pub use std::libc::types::os::arch::extra::*;

pub type ATOM = WORD;
pub type UINT = c_uint;
pub type LONG = c_long;

// 32-bit specific
pub type UINT_PTR = c_uint;
pub type LONG_PTR = c_long;

pub type HANDLE = PVOID;

pub type HBRUSH = HANDLE;
pub type HCURSOR = HICON;
pub type HMENU = HANDLE;
pub type HICON = HANDLE;
pub type HINSTANCE = HANDLE;
pub type HWND = HANDLE;
pub type HDC = HANDLE;

pub type WPARAM = UINT_PTR;
pub type LPARAM = LONG_PTR;

pub type PVOID = *c_void;

// extern fn(HWND, UINT, WPARAM, LPARAM) -> LRESULT
pub type WNDPROC = *u8;

pub struct WNDCLASSEX {
    cbSize: UINT,
    style: UINT,
    lpfnWndProc: WNDPROC,
    cbClsExtra: c_int,
    cbWndExtra: c_int,
    hInstance: HINSTANCE,
    hIcon: HICON,
    hCursor: HCURSOR,
    hbrBackground: HBRUSH,
    lpszMenuName: LPCWSTR,
    lpszClassName: LPCWSTR,
    hIconSm: HICON,
}

pub struct POINT {
    x: LONG,
    y: LONG,
}

pub struct MSG {
    hwnd: HWND,
    message: UINT,
    wParam: WPARAM,
    lParam: LPARAM,
    time: DWORD,
    pt: POINT,
}

pub struct RECT {
    left: LONG,
    top: LONG,
    right: LONG,
    bottom: LONG,
}

pub struct PAINTSTRUCT {
    hdc: HDC,
    fErase: BOOL,
    rcPaint: RECT,
    fRestore: BOOL,
    fIncUpdate: BOOL,
    rgbReserved: *[BYTE, ..32],
}

pub mod user32 {
    use ll::*;
    extern "stdcall" {
        unsafe fn CreateWindowExW(extrastyle: DWORD, classname: LPCWSTR,
                windowname: LPCWSTR, style: DWORD,
                x: c_int, y: c_int, width: c_int, height: c_int,
                parent: HWND, menu: HMENU, instance: HINSTANCE, param: LPVOID
        ) -> HWND;

        unsafe fn ShowWindow(hwnd: HWND, nCmdShow: c_int) -> BOOL;

        unsafe fn UpdateWindow(hwnd: HWND) -> BOOL;

        unsafe fn BeginPaint(hwnd: HWND, lpPaint: *PAINTSTRUCT) -> HDC;

        unsafe fn EndPaint(hwnd: HWND, lpPaint: *PAINTSTRUCT) -> BOOL;

        unsafe fn MessageBoxW(
                hWnd: HWND, lpText: LPCWSTR, lpCaption: LPCWSTR, uType: UINT
        ) -> c_int;

        unsafe fn RegisterClassExW(lpwcx: *WNDCLASSEX) -> ATOM;

        unsafe fn DefWindowProcW(
                hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM
        ) -> LRESULT;

        unsafe fn GetMessageW(
                lpMsg: *MSG, hWnd: HWND,
                wMsgFilterMin: UINT, wMsgFilterMAx: UINT
        ) -> BOOL;

        unsafe fn PeekMessageW(
                lpMsg: *MSG, hWnd: HWND,
                wMsgFilterMin: UINT, wMsgFilterMAx: UINT, wRemoveMsg: UINT
        ) -> BOOL;

        unsafe fn TranslateMessage(lpMsg: *MSG) -> BOOL;

        unsafe fn DispatchMessageW(lpMsg: *MSG) -> LRESULT;
    }
}
<commit_msg>ll: add {G,S}etClassLongW<commit_after>pub use std::libc::*;
pub use std::libc::types::os::arch::extra::*;

pub type ATOM = WORD;
pub type UINT = c_uint;
pub type LONG = c_long;

// 32-bit specific
pub type UINT_PTR = c_uint;
pub type LONG_PTR = c_long;
pub type ULONG_PTR = c_ulong;

pub type HANDLE = PVOID;

pub type HBRUSH = HANDLE;
pub type HCURSOR = HICON;
pub type HMENU = HANDLE;
pub type HICON = HANDLE;
pub type HINSTANCE = HANDLE;
pub type HWND = HANDLE;
pub type HDC = HANDLE;

pub type WPARAM = UINT_PTR;
pub type LPARAM = LONG_PTR;

pub type PVOID = *c_void;

// extern fn(HWND, UINT, WPARAM, LPARAM) -> LRESULT
pub type WNDPROC = *u8;

pub struct WNDCLASSEX {
    cbSize: UINT,
    style: UINT,
    lpfnWndProc: WNDPROC,
    cbClsExtra: c_int,
    cbWndExtra: c_int,
    hInstance: HINSTANCE,
    hIcon: HICON,
    hCursor: HCURSOR,
    hbrBackground: HBRUSH,
    lpszMenuName: LPCWSTR,
    lpszClassName: LPCWSTR,
    hIconSm: HICON,
}

pub struct POINT {
    x: LONG,
    y: LONG,
}

pub struct MSG {
    hwnd: HWND,
    message: UINT,
    wParam: WPARAM,
    lParam: LPARAM,
    time: DWORD,
    pt: POINT,
}

pub struct RECT {
    left: LONG,
    top: LONG,
    right: LONG,
    bottom: LONG,
}

pub struct PAINTSTRUCT {
    hdc: HDC,
    fErase: BOOL,
    rcPaint: RECT,
    fRestore: BOOL,
    fIncUpdate: BOOL,
    rgbReserved: *[BYTE, ..32],
}

pub mod user32 {
    use ll::*;
    extern "stdcall" {
        unsafe fn CreateWindowExW(extrastyle: DWORD, classname: LPCWSTR,
                windowname: LPCWSTR, style: DWORD,
                x: c_int, y: c_int, width: c_int, height: c_int,
                parent: HWND, menu: HMENU, instance: HINSTANCE, param: LPVOID
        ) -> HWND;

        unsafe fn ShowWindow(hwnd: HWND, nCmdShow: c_int) -> BOOL;

        unsafe fn UpdateWindow(hwnd: HWND) -> BOOL;

        unsafe fn BeginPaint(hwnd: HWND, lpPaint: *PAINTSTRUCT) -> HDC;

        unsafe fn EndPaint(hwnd: HWND, lpPaint: *PAINTSTRUCT) -> BOOL;

        unsafe fn MessageBoxW(
                hWnd: HWND, lpText: LPCWSTR, lpCaption: LPCWSTR, uType: UINT
        ) -> c_int;

        unsafe fn RegisterClassExW(lpwcx: *WNDCLASSEX) -> ATOM;

        unsafe fn DefWindowProcW(
                hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM
        ) -> LRESULT;

        unsafe fn GetMessageW(
                lpMsg: *MSG, hWnd: HWND,
                wMsgFilterMin: UINT, wMsgFilterMAx: UINT
        ) -> BOOL;

        unsafe fn PeekMessageW(
                lpMsg: *MSG, hWnd: HWND,
                wMsgFilterMin: UINT, wMsgFilterMAx: UINT, wRemoveMsg: UINT
        ) -> BOOL;

        unsafe fn TranslateMessage(lpMsg: *MSG) -> BOOL;

        unsafe fn DispatchMessageW(lpMsg: *MSG) -> LRESULT;

        // 32-bit only
        unsafe fn GetClassLongW(hwnd: HWND, nIndex: c_int) -> DWORD;

        // 32-bit only
        unsafe fn SetClassLongW(
                hwnd: HWND, nIndex: c_int, dwNewLong: LONG
        ) -> DWORD;
    }
}
<|endoftext|>


<commit_before>#[doc="Constructs a DOM tree from an incoming token stream."]

import dom::base::{Attr, Element, ElementData, ElementKind, HTMLDivElement, HTMLHeadElement};
import dom::base::{HTMLImageElement, Node, NodeScope, Text, TreeReadMethods, TreeWriteMethods};
import dom::base::{UnknownElement};
import dom::rcu::WriterMethods;
import geom::size::Size2D;
import gfx::geometry;
import gfx::geometry::au;
import parser = parser::html_lexer;
import parser::Token;

import dvec::extensions;

#[warn(no_non_implicitly_copyable_typarams)]
fn link_up_attribute(scope: NodeScope, node: Node, -key: str, -value: str) {
    // TODO: Implement atoms so that we don't always perform string comparisons.
    scope.read(node) {
        |node_contents|
        alt *node_contents.kind {
            Element(element) {
                element.attrs.push(~Attr(copy key, copy value));
                alt *element.kind {
                    HTMLImageElement(img) if key == "width" {
                        alt int::from_str(value) {
                            none {
                                // Drop on the floor.
                            }
                            some(s) { img.size.width = geometry::px_to_au(s); }
                        }
                    }
                    HTMLImageElement(img) if key == "height" {
                        alt int::from_str(value) {
                            none {
                                // Drop on the floor.
                            }
                            some(s) {
                                img.size.height = geometry::px_to_au(s);
                            }
                        }
                    }
                    HTMLDivElement | HTMLImageElement(*) | HTMLHeadElement | UnknownElement {
                        // Drop on the floor.
                    }
                }
            }

            Text(*) {
                fail "attempt to link up an attribute to a text node"
            }
        }
    }
}

fn build_element_kind(tag_name: str) -> ~ElementKind {
    alt tag_name {
        "div"   { ~HTMLDivElement }
        "img"   {
            ~HTMLImageElement({
                mut size: Size2D(geometry::px_to_au(100),
                                 geometry::px_to_au(100))
            })
        }
        "head"  { ~HTMLHeadElement }
        _       { ~UnknownElement  }
    }
}

fn build_dom(scope: NodeScope, stream: port<Token>) -> Node {
    // The current reference node.
    let mut cur = scope.new_node(Element(ElementData("html", ~HTMLDivElement)));
    loop {
        let token = stream.recv();
        alt token {
            parser::Eof { break; }
            parser::StartOpeningTag(tag_name) {
                #debug["starting tag %s", tag_name];
                let element_kind = build_element_kind(tag_name);
                let new_node = scope.new_node(Element(ElementData(copy tag_name, element_kind)));
                scope.add_child(cur, new_node);
                cur = new_node;
            }
            parser::Attr(key, value) {
                #debug["attr: %? = %?", key, value];
                link_up_attribute(scope, cur, copy key, copy value);
            }
            parser::EndOpeningTag {
                #debug("end opening tag");
            }
            parser::EndTag(_) | parser::SelfCloseTag {
                // TODO: Assert that the closing tag has the right name.
                // TODO: Fail more gracefully (i.e. according to the HTML5
                //       spec) if we close more tags than we open.
                cur = scope.get_parent(cur).get();
            }
            parser::Text(s) if !s.is_whitespace() {
                let new_node = scope.new_node(Text(copy s));
                scope.add_child(cur, new_node);
            }
            parser::Text(_) {
                // FIXME: Whitespace should not be ignored.
            }
            parser::Doctype {
                // TODO: Do something here...
            }
        }
    }
    ret cur;
}

<commit_msg>reindent html_builder loops<commit_after>#[doc="Constructs a DOM tree from an incoming token stream."]

import dom::base::{Attr, Element, ElementData, ElementKind, HTMLDivElement, HTMLHeadElement};
import dom::base::{HTMLImageElement, Node, NodeScope, Text, TreeReadMethods, TreeWriteMethods};
import dom::base::{UnknownElement};
import dom::rcu::WriterMethods;
import geom::size::Size2D;
import gfx::geometry;
import gfx::geometry::au;
import parser = parser::html_lexer;
import parser::Token;

import dvec::extensions;

#[warn(no_non_implicitly_copyable_typarams)]
fn link_up_attribute(scope: NodeScope, node: Node, -key: str, -value: str) {
    // TODO: Implement atoms so that we don't always perform string comparisons.
    scope.read(node) {
        |node_contents|
        alt *node_contents.kind {
          Element(element) {
            element.attrs.push(~Attr(copy key, copy value));
            alt *element.kind {
              HTMLImageElement(img) if key == "width" {
                alt int::from_str(value) {
                  none {
                    // Drop on the floor.
                  }
                  some(s) { img.size.width = geometry::px_to_au(s); }
                }
              }
              HTMLImageElement(img) if key == "height" {
                alt int::from_str(value) {
                  none {
                    // Drop on the floor.
                  }
                  some(s) {
                    img.size.height = geometry::px_to_au(s);
                  }
                }
              }
              HTMLDivElement | HTMLImageElement(*) | HTMLHeadElement | UnknownElement {
                // Drop on the floor.
              }
            }
          }

          Text(*) {
            fail "attempt to link up an attribute to a text node"
          }
        }
    }
}

fn build_element_kind(tag_name: str) -> ~ElementKind {
    alt tag_name {
        "div"   { ~HTMLDivElement }
        "img"   {
            ~HTMLImageElement({
                mut size: Size2D(geometry::px_to_au(100),
                                 geometry::px_to_au(100))
            })
        }
        "head"  { ~HTMLHeadElement }
        _       { ~UnknownElement  }
    }
}

fn build_dom(scope: NodeScope, stream: port<Token>) -> Node {
    // The current reference node.
    let mut cur = scope.new_node(Element(ElementData("html", ~HTMLDivElement)));
    loop {
        let token = stream.recv();
        alt token {
          parser::Eof { break; }
          parser::StartOpeningTag(tag_name) {
            #debug["starting tag %s", tag_name];
            let element_kind = build_element_kind(tag_name);
            let new_node = scope.new_node(Element(ElementData(copy tag_name, element_kind)));
            scope.add_child(cur, new_node);
            cur = new_node;
          }
          parser::Attr(key, value) {
            #debug["attr: %? = %?", key, value];
            link_up_attribute(scope, cur, copy key, copy value);
          }
          parser::EndOpeningTag {
            #debug("end opening tag");
          }

          parser::EndTag(_) | parser::SelfCloseTag {
            // TODO: Assert that the closing tag has the right name.
            // TODO: Fail more gracefully (i.e. according to the HTML5
            //       spec) if we close more tags than we open.
            cur = scope.get_parent(cur).get();
          }
          parser::Text(s) if !s.is_whitespace() {
            let new_node = scope.new_node(Text(copy s));
            scope.add_child(cur, new_node);
          }
          parser::Text(_) {
            // FIXME: Whitespace should not be ignored.
          }
          parser::Doctype {
            // TODO: Do something here...
          }
        }
    }
    ret cur;
}

<|endoftext|>


<commit_before>use crate::states::play_state::tetromino::{u8_to_piece_type, Piece, PieceType};
use crate::states::Assets;
use crate::util::DurationExt;
use ggez::graphics::Point2;
use ggez::{graphics, Context};
use rand;
use std::time::Duration;

const SPEED: f32 = 170.0;

struct SpawnedPiece {
    position: Point2,
    extra_rotation: f64,
    piece: Piece,
    is_dead: bool,
}

impl SpawnedPiece {
    pub fn new(pos: Point2, rot: f64, ptype: PieceType) -> Self {
        Self {
            position: pos,
            extra_rotation: rot,
            piece: Piece::new(ptype),
            is_dead: false,
        }
    }

    pub fn update(&mut self, ctx: &mut Context, _assets: &Assets, dt: Duration) {
        // TODO: update position
        let coords = graphics::get_screen_coordinates(ctx);
        let height = coords.h * -1.0;
        self.position.y += SPEED * dt.as_subsec_millis() as f32;

        if self.position.y >= height {
            self.is_dead = true;
        }
        self.extra_rotation += dt.as_subsec_millis();
    }

    pub fn draw(&self, ctx: &mut Context, assets: &Assets) {
        self.piece
            .draw_at_point(
                ctx,
                assets.get_image("block").unwrap(),
                self.position,
                self.extra_rotation,
            )
            .unwrap();
    }

    pub fn is_dead(&self) -> bool {
        self.is_dead
    }
}

const TIME_BETWEEN_SPAWNS: f64 = 0.5;
const MAX_ROTATION: f64 = 50.0;

pub struct Spawner {
    active_pieces: Vec<SpawnedPiece>,
    time_until_next_spawn: f64,
}

impl Spawner {
    pub fn new() -> Self {
        Self {
            active_pieces: vec![],
            time_until_next_spawn: 0.0,
        }
    }

    pub fn update(&mut self, ctx: &mut Context, assets: &Assets, dt: Duration) {
        // update current time
        self.time_until_next_spawn += dt.as_subsec_millis();
        if self.time_until_next_spawn >= TIME_BETWEEN_SPAWNS {
            self.time_until_next_spawn -= TIME_BETWEEN_SPAWNS;
            self.spawn_new_piece(ctx);
        }

        // check for dead pieces
        for i in (0..self.active_pieces.len()).rev() {
            if self.active_pieces[i].is_dead() {
                self.active_pieces.remove(i);
            }
        }

        // check if time to spawn new piece
        for piece in &mut self.active_pieces {
            piece.update(ctx, assets, dt);
        }
    }

    pub fn draw(&self, ctx: &mut Context, assets: &Assets) {
        for piece in &self.active_pieces {
            piece.draw(ctx, assets);
        }
    }

    fn spawn_new_piece(&mut self, ctx: &Context) {
        use rand::Rng;
        let coords = graphics::get_screen_coordinates(ctx);
        let x = rand::thread_rng().gen_range(0.0, coords.w);
        let extra_rotation = rand::thread_rng().gen_range(0.0, MAX_ROTATION);

        let piece_type = {
            let piece_type_no = rand::thread_rng().gen_range(0, 7);
            u8_to_piece_type(piece_type_no).unwrap()
        };

        // spawn at a random x position way above viewable screen so pieces just
        // dont 'pop' in but kinda just float into view
        let position = Point2::new(x, -200.0);
        self.active_pieces
            .push(SpawnedPiece::new(position, extra_rotation, piece_type));
    }
}
<commit_msg>Fix: Update to 0.4 broke menu piece spawn<commit_after>use crate::states::play_state::tetromino::{u8_to_piece_type, Piece, PieceType};
use crate::states::Assets;
use crate::util::DurationExt;
use ggez::graphics::Point2;
use ggez::{graphics, Context};
use rand;
use std::time::Duration;

const SPEED: f32 = 170.0;

struct SpawnedPiece {
    position: Point2,
    extra_rotation: f64,
    piece: Piece,
    is_dead: bool,
}

impl SpawnedPiece {
    pub fn new(pos: Point2, rot: f64, ptype: PieceType) -> Self {
        Self {
            position: pos,
            extra_rotation: rot,
            piece: Piece::new(ptype),
            is_dead: false,
        }
    }

    pub fn update(&mut self, ctx: &mut Context, _assets: &Assets, dt: Duration) {
        let coords = graphics::get_screen_coordinates(ctx);
        let height = coords.h;
        self.position.y += SPEED * dt.as_subsec_millis() as f32;

        if self.position.y >= height {
            self.is_dead = true;
        }
        self.extra_rotation += dt.as_subsec_millis();
    }

    pub fn draw(&self, ctx: &mut Context, assets: &Assets) {
        self.piece
            .draw_at_point(
                ctx,
                assets.get_image("block").unwrap(),
                self.position,
                self.extra_rotation,
            )
            .unwrap();
    }

    pub fn is_dead(&self) -> bool {
        self.is_dead
    }
}

const TIME_BETWEEN_SPAWNS: f64 = 0.5;
const MAX_ROTATION: f64 = 50.0;

pub struct Spawner {
    active_pieces: Vec<SpawnedPiece>,
    time_until_next_spawn: f64,
}

impl Spawner {
    pub fn new() -> Self {
        Self {
            active_pieces: vec![],
            time_until_next_spawn: 0.0,
        }
    }

    pub fn update(&mut self, ctx: &mut Context, assets: &Assets, dt: Duration) {
        // update current time
        self.time_until_next_spawn += dt.as_subsec_millis();
        if self.time_until_next_spawn >= TIME_BETWEEN_SPAWNS {
            self.time_until_next_spawn -= TIME_BETWEEN_SPAWNS;
            self.spawn_new_piece(ctx);
        }

        // check for dead pieces
        for i in (0..self.active_pieces.len()).rev() {
            if self.active_pieces[i].is_dead() {
                self.active_pieces.remove(i);
            }
        }

        // check if time to spawn new piece
        for piece in &mut self.active_pieces {
            piece.update(ctx, assets, dt);
        }
    }

    pub fn draw(&self, ctx: &mut Context, assets: &Assets) {
        for piece in &self.active_pieces {
            piece.draw(ctx, assets);
        }
    }

    fn spawn_new_piece(&mut self, ctx: &Context) {
        use rand::Rng;
        let coords = graphics::get_screen_coordinates(ctx);
        let x = rand::thread_rng().gen_range(0.0, coords.w);
        let extra_rotation = rand::thread_rng().gen_range(0.0, MAX_ROTATION);

        let piece_type = {
            let piece_type_no = rand::thread_rng().gen_range(0, 7);
            u8_to_piece_type(piece_type_no).unwrap()
        };

        // spawn at a random x position way above viewable screen so pieces just
        // dont 'pop' in but kinda just float into view
        let position = Point2::new(x, -200.0);
        self.active_pieces
            .push(SpawnedPiece::new(position, extra_rotation, piece_type));
    }
}
<|endoftext|>


<commit_before>fn add(i: [int], m: [mut int], c: [const int]) {

    // Check that:
    //  (1) vectors of any two mutabilities can be added
    //  (2) result has mutability of lhs

   add(i + [3],
       m + [3],
       [3]);

   add(i + [mut 3],
       m + [mut 3],
       [mut 3]);

   add(i + i,
       m + i,
       i);

   add(i + m,
       m + m,
       m);

   add(i + c,
       m + c,
       c);

   add(m + [3], //! ERROR mismatched types
       m + [3],
       m + [3]);

   add(i + [3],
       i + [3], //! ERROR mismatched types
       i + [3]);

   add(c + [3], //! ERROR mismatched types
                //!^ ERROR binary operation + cannot be applied
       c + [3], //! ERROR binary operation + cannot be applied
                //!^ mismatched types
       [3]);

   add(m + [mut 3], //! ERROR mismatched types
       m + [mut 3],
       m + [mut 3]);

   add(i + [mut 3],
       i + [mut 3], //! ERROR mismatched types
       i + [mut 3]);

   add(c + [mut 3], //! ERROR binary operation + cannot be applied
                    //!^ mismatched types
       c + [mut 3], //! ERROR binary operation + cannot be applied
                    //!^ mismatched types
       [mut 3]);

   add(m + i, //! ERROR mismatched types
       m + i,
       m + i);

   add(i + i,
       i + i, //! ERROR mismatched types
       i + i);

   add(c + i, //! ERROR binary operation + cannot be applied
              //!^ ERROR mismatched types
       c + i, //! ERROR binary operation + cannot be applied
              //!^ ERROR mismatched types
       i);

   add(m + m, //! ERROR mismatched types
       m + m,
       m + m);

   add(i + m,
       i + m, //! ERROR mismatched types
       i + m);

   add(c + m, //! ERROR binary operation + cannot be applied
              //!^ ERROR mismatched types
       c + m, //! ERROR binary operation + cannot be applied
              //!^ ERROR mismatched types
       m);

   add(m + c, //! ERROR mismatched types
       m + c,
       m + c);

   add(i + c,
       i + c, //! ERROR mismatched types
       i + c);

   add(c + c, //! ERROR binary operation + cannot be applied
              //!^ ERROR mismatched types
       c + c, //! ERROR binary operation + cannot be applied
              //!^ ERROR mismatched types
       c);
}

fn main() {
}
<commit_msg>xfailing vec-add.<commit_after>// xfail-test

// FIXME: + should allow immutable or mutable vectors on the right
// hand side in all cases. We are getting compiler errors about this
// now, so I'm xfailing the test for now. -eholk

fn add(i: [int], m: [mut int], c: [const int]) {

    // Check that:
    //  (1) vectors of any two mutabilities can be added
    //  (2) result has mutability of lhs

   add(i + [3],
       m + [3],
       [3]);

   add(i + [mut 3],
       m + [mut 3],
       [mut 3]);

   add(i + i,
       m + i,
       i);

   add(i + m,
       m + m,
       m);

   add(i + c,
       m + c,
       c);

   add(m + [3], //! ERROR mismatched types
       m + [3],
       m + [3]);

   add(i + [3],
       i + [3], //! ERROR mismatched types
       i + [3]);

   add(c + [3], //! ERROR mismatched types
                //!^ ERROR binary operation + cannot be applied
       c + [3], //! ERROR binary operation + cannot be applied
                //!^ mismatched types
       [3]);

   add(m + [mut 3], //! ERROR mismatched types
       m + [mut 3],
       m + [mut 3]);

   add(i + [mut 3],
       i + [mut 3], //! ERROR mismatched types
       i + [mut 3]);

   add(c + [mut 3], //! ERROR binary operation + cannot be applied
                    //!^ mismatched types
       c + [mut 3], //! ERROR binary operation + cannot be applied
                    //!^ mismatched types
       [mut 3]);

   add(m + i, //! ERROR mismatched types
       m + i,
       m + i);

   add(i + i,
       i + i, //! ERROR mismatched types
       i + i);

   add(c + i, //! ERROR binary operation + cannot be applied
              //!^ ERROR mismatched types
       c + i, //! ERROR binary operation + cannot be applied
              //!^ ERROR mismatched types
       i);

   add(m + m, //! ERROR mismatched types
       m + m,
       m + m);

   add(i + m,
       i + m, //! ERROR mismatched types
       i + m);

   add(c + m, //! ERROR binary operation + cannot be applied
              //!^ ERROR mismatched types
       c + m, //! ERROR binary operation + cannot be applied
              //!^ ERROR mismatched types
       m);

   add(m + c, //! ERROR mismatched types
       m + c,
       m + c);

   add(i + c,
       i + c, //! ERROR mismatched types
       i + c);

   add(c + c, //! ERROR binary operation + cannot be applied
              //!^ ERROR mismatched types
       c + c, //! ERROR binary operation + cannot be applied
              //!^ ERROR mismatched types
       c);
}

fn main() {
}
<|endoftext|>