<commit_before>//! Tests for renaming dependencies.

use cargo_test_support::git;
use cargo_test_support::paths;
use cargo_test_support::registry::{self, Package};
use cargo_test_support::{basic_manifest, project};

#[cargo_test]
fn rename_dependency() {
    Package::new("bar", "0.1.0").publish();
    Package::new("bar", "0.2.0").publish();

    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [project]
                name = "foo"
                version = "0.0.1"
                authors = []

                [dependencies]
                bar = { version = "0.1.0" }
                baz = { version = "0.2.0", package = "bar" }
            "#,
        )
        .file("src/lib.rs", "extern crate bar; extern crate baz;")
        .build();

    p.cargo("build").run();
}

#[cargo_test]
fn rename_with_different_names() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [project]
                name = "foo"
                version = "0.0.1"
                authors = []

                [dependencies]
                baz = { path = "bar", package = "bar" }
            "#,
        )
        .file("src/lib.rs", "extern crate baz;")
        .file(
            "bar/Cargo.toml",
            r#"
                [project]
                name = "bar"
                version = "0.0.1"
                authors = []

                [lib]
                name = "random_name"
            "#,
        )
        .file("bar/src/lib.rs", "")
        .build();

    p.cargo("build").run();
}

#[cargo_test]
fn lots_of_names() {
    registry::alt_init();
    Package::new("foo", "0.1.0")
        .file("src/lib.rs", "pub fn foo1() {}")
        .publish();
    Package::new("foo", "0.2.0")
        .file("src/lib.rs", "pub fn foo() {}")
        .publish();
    Package::new("foo", "0.1.0")
        .file("src/lib.rs", "pub fn foo2() {}")
        .alternative(true)
        .publish();

    let g = git::repo(&paths::root().join("another"))
        .file("Cargo.toml", &basic_manifest("foo", "0.1.0"))
        .file("src/lib.rs", "pub fn foo3() {}")
        .build();

    let p = project()
        .file(
            "Cargo.toml",
            &format!(
                r#"
                    [package]
                    name = "test"
                    version = "0.1.0"
                    authors = []

                    [dependencies]
                    foo = "0.2"
                    foo1 = {{ version = "0.1", package = "foo" }}
                    foo2 = {{ version = "0.1", registry = "alternative", package = "foo" }}
                    foo3 = {{ git = '{}', package = "foo" }}
                    foo4 = {{ path = "foo", package = "foo" }}
                "#,
                g.url()
            ),
        )
        .file(
            "src/lib.rs",
            "
                extern crate foo;
                extern crate foo1;
                extern crate foo2;
                extern crate foo3;
                extern crate foo4;

                pub fn foo() {
                    foo::foo();
                    foo1::foo1();
                    foo2::foo2();
                    foo3::foo3();
                    foo4::foo4();
                }
            ",
        )
        .file("foo/Cargo.toml", &basic_manifest("foo", "0.1.0"))
        .file("foo/src/lib.rs", "pub fn foo4() {}")
        .build();

    p.cargo("build -v").run();
}

#[cargo_test]
fn rename_and_patch() {
    Package::new("foo", "0.1.0").publish();

    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "test"
                version = "0.1.0"
                authors = []

                [dependencies]
                bar = { version = "0.1", package = "foo" }

                [patch.crates-io]
                foo = { path = "foo" }
            "#,
        )
        .file(
            "src/lib.rs",
            "extern crate bar; pub fn foo() { bar::foo(); }",
        )
        .file("foo/Cargo.toml", &basic_manifest("foo", "0.1.0"))
        .file("foo/src/lib.rs", "pub fn foo() {}")
        .build();

    p.cargo("build -v").run();
}

#[cargo_test]
fn rename_twice() {
    Package::new("foo", "0.1.0").publish();

    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "test"
                version = "0.1.0"
                authors = []

                [dependencies]
                bar = { version = "0.1", package = "foo" }
                [build-dependencies]
                foo = { version = "0.1" }
            "#,
        )
        .file("src/lib.rs", "")
        .build();

    p.cargo("build -v")
        .with_status(101)
        .with_stderr(
            "\
[UPDATING] `[..]` index
[DOWNLOADING] crates ...
[DOWNLOADED] foo v0.1.0 (registry [..])
error: the crate `test v0.1.0 ([CWD])` depends on crate `foo v0.1.0` multiple times with different names
",
        )
        .run();
}

#[cargo_test]
fn rename_affects_fingerprint() {
    Package::new("foo", "0.1.0").publish();

    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "test"
                version = "0.1.0"
                authors = []

                [dependencies]
                foo = { version = "0.1", package = "foo" }
            "#,
        )
        .file("src/lib.rs", "extern crate foo;")
        .build();

    p.cargo("build -v").run();

    p.change_file(
        "Cargo.toml",
        r#"
                [package]
                name = "test"
                version = "0.1.0"
                authors = []

                [dependencies]
                bar = { version = "0.1", package = "foo" }
        "#,
    );

    p.cargo("build -v")
        .with_status(101)
        .with_stderr_contains("[..]can't find crate for `foo`")
        .run();
}

#[cargo_test]
fn can_run_doc_tests() {
    Package::new("bar", "0.1.0").publish();
    Package::new("bar", "0.2.0").publish();

    let foo = project()
        .file(
            "Cargo.toml",
            r#"
                [project]
                name = "foo"
                version = "0.0.1"

                [dependencies]
                bar = { version = "0.1.0" }
                baz = { version = "0.2.0", package = "bar" }
            "#,
        )
        .file(
            "src/lib.rs",
            "
            extern crate bar;
            extern crate baz;
        ",
        )
        .build();

    foo.cargo("test -v")
        .with_stderr_contains(
            "\
[DOCTEST] foo
[RUNNING] `rustdoc [..]--test [..]src/lib.rs \
        [..] \
        --extern bar=[CWD]/target/debug/deps/libbar-[..].rlib \
        --extern baz=[CWD]/target/debug/deps/libbar-[..].rlib \
        [..]`
",
        )
        .run();
}

#[cargo_test]
fn features_still_work() {
    Package::new("foo", "0.1.0").publish();
    Package::new("bar", "0.1.0").publish();

    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "test"
                version = "0.1.0"
                authors = []

                [dependencies]
                p1 = { path = 'a', features = ['b'] }
                p2 = { path = 'b' }
            "#,
        )
        .file("src/lib.rs", "")
        .file(
            "a/Cargo.toml",
            r#"
                [package]
                name = "p1"
                version = "0.1.0"
                authors = []

                [dependencies]
                b = { version = "0.1", package = "foo", optional = true }
            "#,
        )
        .file("a/src/lib.rs", "extern crate b;")
        .file(
            "b/Cargo.toml",
            r#"
                [package]
                name = "p2"
                version = "0.1.0"
                authors = []

                [dependencies]
                b = { version = "0.1", package = "bar", optional = true }

                [features]
                default = ['b']
            "#,
        )
        .file("b/src/lib.rs", "extern crate b;")
        .build();

    p.cargo("build -v").run();
}

#[cargo_test]
fn features_not_working() {
    Package::new("foo", "0.1.0").publish();
    Package::new("bar", "0.1.0").publish();

    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "test"
                version = "0.1.0"
                authors = []

                [dependencies]
                a = { path = 'a', package = 'p1', optional = true }

                [features]
                default = ['p1']
            "#,
        )
        .file("src/lib.rs", "")
        .file("a/Cargo.toml", &basic_manifest("p1", "0.1.0"))
        .build();

    p.cargo("build -v")
        .with_status(101)
        .with_stderr(
            "\
error: failed to parse manifest at `[..]`

Caused by:
  feature `default` includes `p1` which is neither a dependency nor another feature
",
        )
        .run();
}

#[cargo_test]
fn rename_with_dash() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "qwerty"
                version = "0.1.0"

                [dependencies]
                foo-bar = { path = 'a', package = 'a' }
            "#,
        )
        .file("src/lib.rs", "extern crate foo_bar;")
        .file("a/Cargo.toml", &basic_manifest("a", "0.1.0"))
        .file("a/src/lib.rs", "")
        .build();

    p.cargo("build").run();
}
<commit_msg>Fix test<commit_after>//! Tests for renaming dependencies.

use cargo_test_support::git;
use cargo_test_support::paths;
use cargo_test_support::registry::{self, Package};
use cargo_test_support::{basic_manifest, project};

#[cargo_test]
fn rename_dependency() {
    Package::new("bar", "0.1.0").publish();
    Package::new("bar", "0.2.0").publish();

    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [project]
                name = "foo"
                version = "0.0.1"
                authors = []

                [dependencies]
                bar = { version = "0.1.0" }
                baz = { version = "0.2.0", package = "bar" }
            "#,
        )
        .file("src/lib.rs", "extern crate bar; extern crate baz;")
        .build();

    p.cargo("build").run();
}

#[cargo_test]
fn rename_with_different_names() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [project]
                name = "foo"
                version = "0.0.1"
                authors = []

                [dependencies]
                baz = { path = "bar", package = "bar" }
            "#,
        )
        .file("src/lib.rs", "extern crate baz;")
        .file(
            "bar/Cargo.toml",
            r#"
                [project]
                name = "bar"
                version = "0.0.1"
                authors = []

                [lib]
                name = "random_name"
            "#,
        )
        .file("bar/src/lib.rs", "")
        .build();

    p.cargo("build").run();
}

#[cargo_test]
fn lots_of_names() {
    registry::alt_init();
    Package::new("foo", "0.1.0")
        .file("src/lib.rs", "pub fn foo1() {}")
        .publish();
    Package::new("foo", "0.2.0")
        .file("src/lib.rs", "pub fn foo() {}")
        .publish();
    Package::new("foo", "0.1.0")
        .file("src/lib.rs", "pub fn foo2() {}")
        .alternative(true)
        .publish();

    let g = git::repo(&paths::root().join("another"))
        .file("Cargo.toml", &basic_manifest("foo", "0.1.0"))
        .file("src/lib.rs", "pub fn foo3() {}")
        .build();

    let p = project()
        .file(
            "Cargo.toml",
            &format!(
                r#"
                    [package]
                    name = "test"
                    version = "0.1.0"
                    authors = []

                    [dependencies]
                    foo = "0.2"
                    foo1 = {{ version = "0.1", package = "foo" }}
                    foo2 = {{ version = "0.1", registry = "alternative", package = "foo" }}
                    foo3 = {{ git = '{}', package = "foo" }}
                    foo4 = {{ path = "foo", package = "foo" }}
                "#,
                g.url()
            ),
        )
        .file(
            "src/lib.rs",
            "
                extern crate foo;
                extern crate foo1;
                extern crate foo2;
                extern crate foo3;
                extern crate foo4;

                pub fn foo() {
                    foo::foo();
                    foo1::foo1();
                    foo2::foo2();
                    foo3::foo3();
                    foo4::foo4();
                }
            ",
        )
        .file("foo/Cargo.toml", &basic_manifest("foo", "0.1.0"))
        .file("foo/src/lib.rs", "pub fn foo4() {}")
        .build();

    p.cargo("build -v").run();
}

#[cargo_test]
fn rename_and_patch() {
    Package::new("foo", "0.1.0").publish();

    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "test"
                version = "0.1.0"
                authors = []

                [dependencies]
                bar = { version = "0.1", package = "foo" }

                [patch.crates-io]
                foo = { path = "foo" }
            "#,
        )
        .file(
            "src/lib.rs",
            "extern crate bar; pub fn foo() { bar::foo(); }",
        )
        .file("foo/Cargo.toml", &basic_manifest("foo", "0.1.0"))
        .file("foo/src/lib.rs", "pub fn foo() {}")
        .build();

    p.cargo("build -v").run();
}

#[cargo_test]
fn rename_twice() {
    Package::new("foo", "0.1.0").publish();

    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "test"
                version = "0.1.0"
                authors = []

                [dependencies]
                bar = { version = "0.1", package = "foo" }
                [build-dependencies]
                foo = { version = "0.1" }
            "#,
        )
        .file("src/lib.rs", "")
        .build();

    p.cargo("build -v")
        .with_status(101)
        .with_stderr(
            "\
[UPDATING] `[..]` index
[DOWNLOADING] crates ...
[DOWNLOADED] foo v0.1.0 (registry [..])
error: the crate `test v0.1.0 ([CWD])` depends on crate `foo v0.1.0` multiple times with different names
",
        )
        .run();
}

#[cargo_test]
fn rename_affects_fingerprint() {
    Package::new("foo", "0.1.0").publish();

    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "test"
                version = "0.1.0"
                authors = []

                [dependencies]
                foo = { version = "0.1", package = "foo" }
            "#,
        )
        .file("src/lib.rs", "extern crate foo;")
        .build();

    p.cargo("build -v").run();

    p.change_file(
        "Cargo.toml",
        r#"
                [package]
                name = "test"
                version = "0.1.0"
                authors = []

                [dependencies]
                bar = { version = "0.1", package = "foo" }
        "#,
    );

    p.cargo("build -v")
        .with_status(101)
        .with_stderr_contains("[..]can't find crate for `foo`")
        .run();
}

#[cargo_test]
fn can_run_doc_tests() {
    Package::new("bar", "0.1.0").publish();
    Package::new("bar", "0.2.0").publish();

    let foo = project()
        .file(
            "Cargo.toml",
            r#"
                [project]
                name = "foo"
                version = "0.0.1"

                [dependencies]
                bar = { version = "0.1.0" }
                baz = { version = "0.2.0", package = "bar" }
            "#,
        )
        .file(
            "src/lib.rs",
            "
            extern crate bar;
            extern crate baz;
        ",
        )
        .build();

    foo.cargo("test -v")
        .with_stderr_contains(
            "\
[DOCTEST] foo
[RUNNING] `rustdoc [..]--test \
        [..] \
        --extern bar=[CWD]/target/debug/deps/libbar-[..].rlib \
        --extern baz=[CWD]/target/debug/deps/libbar-[..].rlib \
        [..]src/lib.rs`
",
        )
        .run();
}

#[cargo_test]
fn features_still_work() {
    Package::new("foo", "0.1.0").publish();
    Package::new("bar", "0.1.0").publish();

    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "test"
                version = "0.1.0"
                authors = []

                [dependencies]
                p1 = { path = 'a', features = ['b'] }
                p2 = { path = 'b' }
            "#,
        )
        .file("src/lib.rs", "")
        .file(
            "a/Cargo.toml",
            r#"
                [package]
                name = "p1"
                version = "0.1.0"
                authors = []

                [dependencies]
                b = { version = "0.1", package = "foo", optional = true }
            "#,
        )
        .file("a/src/lib.rs", "extern crate b;")
        .file(
            "b/Cargo.toml",
            r#"
                [package]
                name = "p2"
                version = "0.1.0"
                authors = []

                [dependencies]
                b = { version = "0.1", package = "bar", optional = true }

                [features]
                default = ['b']
            "#,
        )
        .file("b/src/lib.rs", "extern crate b;")
        .build();

    p.cargo("build -v").run();
}

#[cargo_test]
fn features_not_working() {
    Package::new("foo", "0.1.0").publish();
    Package::new("bar", "0.1.0").publish();

    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "test"
                version = "0.1.0"
                authors = []

                [dependencies]
                a = { path = 'a', package = 'p1', optional = true }

                [features]
                default = ['p1']
            "#,
        )
        .file("src/lib.rs", "")
        .file("a/Cargo.toml", &basic_manifest("p1", "0.1.0"))
        .build();

    p.cargo("build -v")
        .with_status(101)
        .with_stderr(
            "\
error: failed to parse manifest at `[..]`

Caused by:
  feature `default` includes `p1` which is neither a dependency nor another feature
",
        )
        .run();
}

#[cargo_test]
fn rename_with_dash() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "qwerty"
                version = "0.1.0"

                [dependencies]
                foo-bar = { path = 'a', package = 'a' }
            "#,
        )
        .file("src/lib.rs", "extern crate foo_bar;")
        .file("a/Cargo.toml", &basic_manifest("a", "0.1.0"))
        .file("a/src/lib.rs", "")
        .build();

    p.cargo("build").run();
}
<|endoftext|>


<commit_before>fn main() {
	// Dynamic linking
	println!("cargo:rustc-link-search=native={}", "C:/Windows/System32/");
}<commit_msg>Remove unneeded build script<commit_after><|endoftext|>


<commit_before>extern crate gcc;

use std::fs;
use std::io;
use std::env;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::ffi::OsString;
use std::ffi::OsStr;

trait CommandExt {
    fn execute(&mut self) -> io::Result<()>;
}

impl CommandExt for Command {
    /// Execute the command and return an error if it exited with a failure status.
    fn execute(&mut self) -> io::Result<()> {
        let status = try!(self.status());
        if status.success() {
            Ok(())
        } else {
            Err(io::Error::new(io::ErrorKind::Other, format!("The command\n\
            \t{:?}\n\
            did not run successfully.", self)))
        }
    }
}

/// The command to build lua, with switches for different *nix targets.
fn build_lua(tooling: &gcc::Tool, source: &Path, build: &Path) -> io::Result<()> {
    // calculate the Lua platform name
    let platform = match env::var("TARGET").unwrap().split('-').nth(2).unwrap() {
        "windows" => "mingw",
        "darwin" => "macosx",
        "linux" => "linux",
        "freebsd" => "freebsd",
        "dragonfly" => "bsd",
        // fall back to the "generic" system
        _ => "generic",
    };

    // extract CC and MYCFLAGS from the detected tooling
    let cc = tooling.path();
    let mut cflags = OsString::new();
    for arg in tooling.args() {
        cflags.push(arg);
        cflags.push(" ");
    }

    // VPATH is used to invoke "make" from the directory where we want Lua to
    // be built into, but read the sources from the provided source directory.
    // Setting MAKE to match the command we invoke means that the VPATH and
    // Makefile path will be carried over when the Makefile invokes itself.
    let makefile = source.join("Makefile");
    let make = OsString::from(format!("make -e -f {:?}", makefile.to_string_lossy().replace("\\", "/")));

    // call the makefile
    let mut command = Command::new("make");
    for &(ref key, ref val) in tooling.env() {
        command.env(key, val);
    }
    command.current_dir(build)
        .env("VPATH", source.to_string_lossy().replace("\\", "/"))
        .env("MAKE", make)
        .env("CC", cc)
        .env("MYCFLAGS", cflags)
        .arg("-e")
        .arg("-f").arg(makefile)
        .arg(platform)
        .execute()
}

/// Ensure we have cl.exe and lib.exe at our disposal.
fn verify_msvc_environment() {
    let found_cl_exe = Command::new("cl.exe").arg("/help").output().is_ok();
    let found_lib_exe = Command::new("lib.exe").arg("/help").output().is_ok();

    if !found_cl_exe || !found_lib_exe {
        panic!("cl.exe and lib.exe must be on your %PATH% to compile Lua for MSVC.\n\
        Please install this crate through the Visual Studio Native Tools Command Line.");
    }
}

/// Compile liblua.lib for use with MSVC flavored Rust.
fn build_lua_msvc(source: &Path, build: &Path) -> io::Result<()>{
    verify_msvc_environment();
    let build_str = build.as_os_str().to_str().unwrap();
    // Compile our .obj files
    let mut compile_cmd = Command::new("cl.exe");
    compile_cmd.current_dir(&source);
    // Give cl.exe our .c files.
    for file_res in fs::read_dir(source).unwrap() {
        let dir_entry = file_res.unwrap();
        let file_name = dir_entry.file_name().into_string().unwrap();
        if file_name.ends_with(".c") && file_name != "luac.c" {
            compile_cmd.arg(file_name);
        }
    }
    compile_cmd.arg("/c") // Don't link. Just generate .obj files.
        .arg("/MP") // Builds multiple source files concurrently.
        .arg(format!("/Fo{}\\", &build_str)) // Output to the build folder
        .arg("/nologo"); // Prevent stdout pollution
        //.arg("/LD") // Not sure if I need this or not.
    compile_cmd.execute().unwrap(); // Block until compilation is complete.
    // Link our .obj files into liblua.lib.
    let mut lib_cmd = Command::new("lib.exe");
    lib_cmd.current_dir(&build);
    for file_res in fs::read_dir(build).unwrap() {
        let dir_entry = file_res.unwrap();
        let file_name = dir_entry.file_name().into_string().unwrap();
        if file_name.ends_with(".obj") {
            lib_cmd.arg(file_name);
        }
    }
    lib_cmd.arg(format!("/out:{}\\lua.lib", &build_str)) // Output file
        .arg("/NOLOGO");
    lib_cmd.execute()
}

/// If a static Lua is not yet available from a prior run of this script, this
/// will download Lua and build it. The cargo configuration text to link
/// statically against liblua.a/liblua.lib is then printed to stdout.
fn prebuild() -> io::Result<()> {
    let lua_dir : PathBuf = match env::var_os("LUA_LOCAL_SOURCE") {
        // If LUA_LOCAL_SOURCE is set, use it
        Some(dir) => PathBuf::from(dir),
        // Otherwise, pull from lua-source/src in the crate root
        None => {
            let mut dir = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap());
            dir.push(OsStr::new("lua-source/src").to_str().unwrap());
            dir
        }
    };
    let build_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let mut config = gcc::Config::new();
    let msvc = env::var("TARGET").unwrap().split('-').last().unwrap() == "msvc";
    println!("cargo:rustc-link-lib=static=lua");
    if !msvc && lua_dir.join("liblua.a").exists() {
        // If liblua.a is already in lua_dir, use it
        println!("cargo:rustc-link-search=native={}", &lua_dir.display());
    } else if msvc {
        if !build_dir.join("lua.lib").exists() {
            try!(build_lua_msvc(&lua_dir, &build_dir));
        }
        println!("cargo:rustc-link-search=native={}", &build_dir.display());
    } else {
        // Check build_dir
        if !build_dir.join("liblua.a").exists() {
            // Build liblua.a
            let tooling = config.get_compiler();
            try!(fs::create_dir_all(&build_dir));
            try!(build_lua(&tooling, &lua_dir, &build_dir));
        }
        println!("cargo:rustc-link-search=native={}", &build_dir.display());
    }

    // Ensure the presence of glue.rs
    if !build_dir.join("glue.rs").exists() {
        // Compile and run glue.c
        let glue = build_dir.join("glue");
        try!(config.include(&lua_dir).get_compiler().to_command()
            .arg("-I").arg(&lua_dir)
            .arg("src/glue/glue.c")
            .arg("-o").arg(&glue)
            .execute());
        try!(Command::new(glue)
            .arg(build_dir.join("glue.rs"))
            .execute());
    }
    Ok(())
}

fn main() {
    match prebuild() {
        Err(e) => panic!("Error: {}", e),
        Ok(()) => (),
    }
}
<commit_msg>fix deprecated `gcc::Config`<commit_after>extern crate gcc;

use std::fs;
use std::io;
use std::env;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::ffi::OsString;
use std::ffi::OsStr;

trait CommandExt {
    fn execute(&mut self) -> io::Result<()>;
}

impl CommandExt for Command {
    /// Execute the command and return an error if it exited with a failure status.
    fn execute(&mut self) -> io::Result<()> {
        let status = try!(self.status());
        if status.success() {
            Ok(())
        } else {
            Err(io::Error::new(io::ErrorKind::Other, format!("The command\n\
            \t{:?}\n\
            did not run successfully.", self)))
        }
    }
}

/// The command to build lua, with switches for different *nix targets.
fn build_lua(tooling: &gcc::Tool, source: &Path, build: &Path) -> io::Result<()> {
    // calculate the Lua platform name
    let platform = match env::var("TARGET").unwrap().split('-').nth(2).unwrap() {
        "windows" => "mingw",
        "darwin" => "macosx",
        "linux" => "linux",
        "freebsd" => "freebsd",
        "dragonfly" => "bsd",
        // fall back to the "generic" system
        _ => "generic",
    };

    // extract CC and MYCFLAGS from the detected tooling
    let cc = tooling.path();
    let mut cflags = OsString::new();
    for arg in tooling.args() {
        cflags.push(arg);
        cflags.push(" ");
    }

    // VPATH is used to invoke "make" from the directory where we want Lua to
    // be built into, but read the sources from the provided source directory.
    // Setting MAKE to match the command we invoke means that the VPATH and
    // Makefile path will be carried over when the Makefile invokes itself.
    let makefile = source.join("Makefile");
    let make = OsString::from(format!("make -e -f {:?}", makefile.to_string_lossy().replace("\\", "/")));

    // call the makefile
    let mut command = Command::new("make");
    for &(ref key, ref val) in tooling.env() {
        command.env(key, val);
    }
    command.current_dir(build)
        .env("VPATH", source.to_string_lossy().replace("\\", "/"))
        .env("MAKE", make)
        .env("CC", cc)
        .env("MYCFLAGS", cflags)
        .arg("-e")
        .arg("-f").arg(makefile)
        .arg(platform)
        .execute()
}

/// Ensure we have cl.exe and lib.exe at our disposal.
fn verify_msvc_environment() {
    let found_cl_exe = Command::new("cl.exe").arg("/help").output().is_ok();
    let found_lib_exe = Command::new("lib.exe").arg("/help").output().is_ok();

    if !found_cl_exe || !found_lib_exe {
        panic!("cl.exe and lib.exe must be on your %PATH% to compile Lua for MSVC.\n\
        Please install this crate through the Visual Studio Native Tools Command Line.");
    }
}

/// Compile liblua.lib for use with MSVC flavored Rust.
fn build_lua_msvc(source: &Path, build: &Path) -> io::Result<()>{
    verify_msvc_environment();
    let build_str = build.as_os_str().to_str().unwrap();
    // Compile our .obj files
    let mut compile_cmd = Command::new("cl.exe");
    compile_cmd.current_dir(&source);
    // Give cl.exe our .c files.
    for file_res in fs::read_dir(source).unwrap() {
        let dir_entry = file_res.unwrap();
        let file_name = dir_entry.file_name().into_string().unwrap();
        if file_name.ends_with(".c") && file_name != "luac.c" {
            compile_cmd.arg(file_name);
        }
    }
    compile_cmd.arg("/c") // Don't link. Just generate .obj files.
        .arg("/MP") // Builds multiple source files concurrently.
        .arg(format!("/Fo{}\\", &build_str)) // Output to the build folder
        .arg("/nologo"); // Prevent stdout pollution
        //.arg("/LD") // Not sure if I need this or not.
    compile_cmd.execute().unwrap(); // Block until compilation is complete.
    // Link our .obj files into liblua.lib.
    let mut lib_cmd = Command::new("lib.exe");
    lib_cmd.current_dir(&build);
    for file_res in fs::read_dir(build).unwrap() {
        let dir_entry = file_res.unwrap();
        let file_name = dir_entry.file_name().into_string().unwrap();
        if file_name.ends_with(".obj") {
            lib_cmd.arg(file_name);
        }
    }
    lib_cmd.arg(format!("/out:{}\\lua.lib", &build_str)) // Output file
        .arg("/NOLOGO");
    lib_cmd.execute()
}

/// If a static Lua is not yet available from a prior run of this script, this
/// will download Lua and build it. The cargo configuration text to link
/// statically against liblua.a/liblua.lib is then printed to stdout.
fn prebuild() -> io::Result<()> {
    let lua_dir : PathBuf = match env::var_os("LUA_LOCAL_SOURCE") {
        // If LUA_LOCAL_SOURCE is set, use it
        Some(dir) => PathBuf::from(dir),
        // Otherwise, pull from lua-source/src in the crate root
        None => {
            let mut dir = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap());
            dir.push(OsStr::new("lua-source/src").to_str().unwrap());
            dir
        }
    };
    let build_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let mut config = gcc::Build::new();
    let msvc = env::var("TARGET").unwrap().split('-').last().unwrap() == "msvc";
    println!("cargo:rustc-link-lib=static=lua");
    if !msvc && lua_dir.join("liblua.a").exists() {
        // If liblua.a is already in lua_dir, use it
        println!("cargo:rustc-link-search=native={}", &lua_dir.display());
    } else if msvc {
        if !build_dir.join("lua.lib").exists() {
            try!(build_lua_msvc(&lua_dir, &build_dir));
        }
        println!("cargo:rustc-link-search=native={}", &build_dir.display());
    } else {
        // Check build_dir
        if !build_dir.join("liblua.a").exists() {
            // Build liblua.a
            let tooling = config.get_compiler();
            try!(fs::create_dir_all(&build_dir));
            try!(build_lua(&tooling, &lua_dir, &build_dir));
        }
        println!("cargo:rustc-link-search=native={}", &build_dir.display());
    }

    // Ensure the presence of glue.rs
    if !build_dir.join("glue.rs").exists() {
        // Compile and run glue.c
        let glue = build_dir.join("glue");
        try!(config.include(&lua_dir).get_compiler().to_command()
            .arg("-I").arg(&lua_dir)
            .arg("src/glue/glue.c")
            .arg("-o").arg(&glue)
            .execute());
        try!(Command::new(glue)
            .arg(build_dir.join("glue.rs"))
            .execute());
    }
    Ok(())
}

fn main() {
    match prebuild() {
        Err(e) => panic!("Error: {}", e),
        Ok(()) => (),
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2013 - 2021 Tim Düsterhus
// Copyright (C) 2021 Maximilian Mader
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// SPDX-License-Identifier: AGPL-3.0-or-later

use sha2::{Digest, Sha384};
use std::{
    collections::HashMap,
    io::Write,
    path::{Path, PathBuf},
};

type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;

fn write_license_info_file(
    dependencies: Vec<cargo_license::DependencyDetails>,
) -> std::io::Result<()> {
    let dst = std::path::Path::new(&std::env::var("OUT_DIR").unwrap()).join("licence_info.rs");
    let mut file = std::fs::File::create(&dst)?;

    writeln!(file, "pub type LicenseInfo = &'static [(&'static str, &'static str, &'static str, &'static [&'static str])];")?;
    writeln!(file, "pub const LICENSE_INFO: LicenseInfo = &[")?;

    for dependency in dependencies {
        let name = dependency.name.clone();
        let version = dependency.version.clone();
        let license = dependency.license.unwrap_or_else(|| "N/A".to_owned());
        let authors = dependency
            .authors
            .unwrap_or_else(|| "N/A".to_owned())
            .split('|')
            .map(|a| format!(r#""{}""#, a.replace(" <>", "")))
            .collect::<Vec<_>>()
            .join(", ");

        writeln!(
            file,
            r#"    ("{}", "{}", "{}", &[{}]),"#,
            name, version, license, authors
        )?;
    }

    writeln!(file, "];")?;

    Ok(())
}

fn bundle_source_code() -> crate::Result<()> {
    use ignore::{overrides::OverrideBuilder, WalkBuilder};
    use std::io::BufWriter;

    fn const_name(path: &Path, const_names: &mut HashMap<PathBuf, String>) -> String {
        if let Some(name) = const_names.get(path) {
            return name.clone();
        }

        let name = format!("FILE_{}", const_names.len());

        const_names.insert(path.to_path_buf(), name.clone());

        name
    }

    let mut builder = phf_codegen::OrderedMap::new();

    let overrides = OverrideBuilder::new("./")
        .add("!/.git/")
        .unwrap()
        .build()
        .unwrap();

    let walker = WalkBuilder::new("./")
        .hidden(false)
        .overrides(overrides)
        .sort_by_file_name(|a, b| a.cmp(b))
        .build();

    let dst = std::path::Path::new(&std::env::var("OUT_DIR").unwrap()).join("source_files.rs");
    let mut out = BufWriter::new(std::fs::File::create(&dst)?);

    let mut const_names = HashMap::new();

    let mut combined_hasher = Sha384::new();

    for result in walker {
        let entry = result?;
        if let Some(file_type) = entry.file_type() {
            if !file_type.is_file() {
                continue;
            }

            println!("cargo:rerun-if-changed={}", entry.path().display());

            let file = entry.path().strip_prefix("./").unwrap();
            let name = file.to_str().unwrap().to_owned();
            let const_name = const_name(file, &mut const_names);

            let hash = {
                let mut hasher = Sha384::new();
                let mut file = std::fs::File::open(entry.path())?;
                let _ = std::io::copy(&mut file, &mut hasher)?;
                hasher.finalize()
            };

            combined_hasher.update(hash);

            let src = std::path::Path::new(&std::env::var("CARGO_MANIFEST_DIR").unwrap())
                .join(entry.path());

            writeln!(
                out,
                "const {}: &[u8] = include_bytes!(\"{}\");",
                const_name,
                src.display()
            )?;

            writeln!(
                out,
                "const {}_SHA384_DIGEST: &str = \"sha384-{}\";",
                const_name,
                base64::encode(hash)
            )?;

            builder.entry(
                name,
                &format!(
                    "SourceFile {{ contents: {}, sha384_digest: {}_SHA384_DIGEST }}",
                    &const_name, &const_name
                ),
            );
        }
    }

    writeln!(
        out,
        "pub const SOURCE_FILES: ::phf::OrderedMap<&'static str, SourceFile> = \n{};\n",
        builder.build()
    )?;

    writeln!(
        out,
        "pub const SOURCE_FILES_COMBINED_HASH: &str = \"{}\";\n",
        base64::encode(combined_hasher.finalize())
    )?;

    out.flush().unwrap();

    Ok(())
}

fn main() -> crate::Result<()> {
    built::write_built_file().expect("Failed to acquire build-time information");

    let cmd = cargo_metadata::MetadataCommand::new();
    let dependencies = cargo_license::get_dependencies_from_cargo_lock(cmd, false, false)?;

    write_license_info_file(dependencies)?;

    bundle_source_code()?;

    Ok(())
}
<commit_msg>Explicitly exclude the `/target` directory from the source code bundle<commit_after>// Copyright (C) 2013 - 2021 Tim Düsterhus
// Copyright (C) 2021 Maximilian Mader
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// SPDX-License-Identifier: AGPL-3.0-or-later

use sha2::{Digest, Sha384};
use std::{
    collections::HashMap,
    io::Write,
    path::{Path, PathBuf},
};

type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;

fn write_license_info_file(
    dependencies: Vec<cargo_license::DependencyDetails>,
) -> std::io::Result<()> {
    let dst = std::path::Path::new(&std::env::var("OUT_DIR").unwrap()).join("licence_info.rs");
    let mut file = std::fs::File::create(&dst)?;

    writeln!(file, "pub type LicenseInfo = &'static [(&'static str, &'static str, &'static str, &'static [&'static str])];")?;
    writeln!(file, "pub const LICENSE_INFO: LicenseInfo = &[")?;

    for dependency in dependencies {
        let name = dependency.name.clone();
        let version = dependency.version.clone();
        let license = dependency.license.unwrap_or_else(|| "N/A".to_owned());
        let authors = dependency
            .authors
            .unwrap_or_else(|| "N/A".to_owned())
            .split('|')
            .map(|a| format!(r#""{}""#, a.replace(" <>", "")))
            .collect::<Vec<_>>()
            .join(", ");

        writeln!(
            file,
            r#"    ("{}", "{}", "{}", &[{}]),"#,
            name, version, license, authors
        )?;
    }

    writeln!(file, "];")?;

    Ok(())
}

fn bundle_source_code() -> crate::Result<()> {
    use ignore::{overrides::OverrideBuilder, WalkBuilder};
    use std::io::BufWriter;

    fn const_name(path: &Path, const_names: &mut HashMap<PathBuf, String>) -> String {
        if let Some(name) = const_names.get(path) {
            return name.clone();
        }

        let name = format!("FILE_{}", const_names.len());

        const_names.insert(path.to_path_buf(), name.clone());

        name
    }

    let mut builder = phf_codegen::OrderedMap::new();

    let overrides = OverrideBuilder::new("./")
        .add("!/.git/")
        .unwrap()
        .add("!/target/")
        .unwrap()
        .build()
        .unwrap();

    let walker = WalkBuilder::new("./")
        .hidden(false)
        .require_git(false)
        .overrides(overrides)
        .sort_by_file_name(|a, b| a.cmp(b))
        .build();

    let dst = std::path::Path::new(&std::env::var("OUT_DIR").unwrap()).join("source_files.rs");
    let mut out = BufWriter::new(std::fs::File::create(&dst)?);

    let mut const_names = HashMap::new();

    let mut combined_hasher = Sha384::new();

    for result in walker {
        let entry = result?;
        if let Some(file_type) = entry.file_type() {
            if !file_type.is_file() {
                continue;
            }

            println!("cargo:rerun-if-changed={}", entry.path().display());

            let file = entry.path().strip_prefix("./").unwrap();
            let name = file.to_str().unwrap().to_owned();
            let const_name = const_name(file, &mut const_names);

            let hash = {
                let mut hasher = Sha384::new();
                let mut file = std::fs::File::open(entry.path())?;
                let _ = std::io::copy(&mut file, &mut hasher)?;
                hasher.finalize()
            };

            combined_hasher.update(hash);

            let src = std::path::Path::new(&std::env::var("CARGO_MANIFEST_DIR").unwrap())
                .join(entry.path());

            writeln!(
                out,
                "const {}: &[u8] = include_bytes!(\"{}\");",
                const_name,
                src.display()
            )?;

            writeln!(
                out,
                "const {}_SHA384_DIGEST: &str = \"sha384-{}\";",
                const_name,
                base64::encode(hash)
            )?;

            builder.entry(
                name,
                &format!(
                    "SourceFile {{ contents: {}, sha384_digest: {}_SHA384_DIGEST }}",
                    &const_name, &const_name
                ),
            );
        }
    }

    writeln!(
        out,
        "pub const SOURCE_FILES: ::phf::OrderedMap<&'static str, SourceFile> = \n{};\n",
        builder.build()
    )?;

    writeln!(
        out,
        "pub const SOURCE_FILES_COMBINED_HASH: &str = \"{}\";\n",
        base64::encode(combined_hasher.finalize())
    )?;

    out.flush().unwrap();

    Ok(())
}

fn main() -> crate::Result<()> {
    built::write_built_file().expect("Failed to acquire build-time information");

    let cmd = cargo_metadata::MetadataCommand::new();
    let dependencies = cargo_license::get_dependencies_from_cargo_lock(cmd, false, false)?;

    write_license_info_file(dependencies)?;

    bundle_source_code()?;

    Ok(())
}
<|endoftext|>


<commit_before>extern crate cmake;
extern crate pkg_config;

use std::env;
use std::env::consts;
use std::path::PathBuf;

fn build_dos(cmake_cfg: &mut cmake::Config) {
    let use_dos_dylib = option_env!("DyLib_DOtherSide").is_some();
    let dst = cmake_cfg.build();

    println!("cargo:rustc-link-search=native={}", dst.join("lib").display());

    if cfg!(windows) {
        println!("cargo:rustc-link-search=native={}", dst.join("build").join("lib").join("Release").display());
    } else {
        println!("cargo:rustc-link-search=native={}", dst.join("build").join("lib").display());
    }

    if use_dos_dylib {
        println!("cargo:rustc-link-lib=dylib=DOtherSide");
    } else {
        println!("cargo:rustc-link-lib=static=DOtherSideStatic");
    }
}

fn find_qt5(_: &mut cmake::Config) {
    /*
     * Support Qt installed via the Ports system on BSD-like systems.
     *
     * The native libs are in `/usr/local/lib`, which is not linked against by default.
     * This means that either the user or every package has to add this if they want to link
     * against something that is not part of the core distribution in `/usr/lib`.
     *
     * See https://wiki.freebsd.org/WarnerLosh/UsrLocal for the line of reasoning & how this will
     * change in the future.
     */
    if cfg!(any(target_os = "freebsd", target_os = "openbsd", target_os = "netbsd",
                target_os = "dragonfly", target_os = "bitrig")) {
        println!("cargo:rustc-link-search=native=/usr/local/lib");
    }

    /*
     * Parameters for supporting QT on OS X
     *
     * Because QT5 conflicts with QT4 the homebrew package manager won't link
     * the QT5 package into the default search paths for libraries, to deal
     * with this we need to give pkg-config and cmake a nudge in the right
     * direction.
     */
    if cfg!(target_os = "macos") {
        // We use the QTDIR or QTDIR64 env variables to find the location of
        // Qt5. If these are not set, we use the default homebrew install
        // location.
        let qtdir_variable = match consts::ARCH {
            "x86_64" => "QTDIR64",
            _ => "QTDIR",
        };
        let mut qt5_lib_path = PathBuf::new();
        qt5_lib_path.push(env::var(qtdir_variable).unwrap_or(String::from("/usr/local/opt/qt5")));
        qt5_lib_path.push("lib");

        if qt5_lib_path.exists() {
            // First nudge cmake in the direction of the .cmake files added by
            // homebrew. This clobbers the existing value if present, it's
            // unlikely to be present though.
            env::set_var("CMAKE_PREFIX_PATH", qt5_lib_path.join("cmake"));

            // Nudge pkg-config in the direction of the brewed QT to ensure the
            // correct compiler flags get found for the project.
            env::set_var("PKG_CONFIG_PATH", qt5_lib_path.join("pkgconfig"));
        } else {
            panic!("QT5 was not found at the expected location ({}) please install it via homebrew, or set the {} env variable.",
            qt5_lib_path.display(), qtdir_variable);
        }
    }

    if cfg!(windows) {
        let mut qt5_lib_path = PathBuf::new();
        qt5_lib_path.push(env::var("QTDIR").unwrap_or(String::from("C:\\Qt\\5.7\\msvc2015_64")));

        if qt5_lib_path.exists() {
            env::set_var("CMAKE_PREFIX_PATH", &qt5_lib_path);

            qt5_lib_path.push("lib");

            println!("cargo:rustc-link-search=native={}\\system32",env::var("WINDIR").unwrap());
            println!("cargo:rustc-link-search=native={}",qt5_lib_path.display());

            println!("cargo:rustc-link-lib=dylib=Qt5Core");
            println!("cargo:rustc-link-lib=dylib=Qt5Gui");
            println!("cargo:rustc-link-lib=dylib=Qt5Qml");
            println!("cargo:rustc-link-lib=dylib=Qt5Quick");
            println!("cargo:rustc-link-lib=dylib=Qt5Svg");
            println!("cargo:rustc-link-lib=dylib=Qt5Widgets");
        } else {
            panic!("QT5 was not found at the expected location ({}) please install the SDK or set the QTDIR env variable.",
            qt5_lib_path.display());
        }
    } else {
        use pkg_config;

        if cfg!(target_os = "macos") {
            println!("cargo:rustc-link-lib=dylib=c++");
        } else {
            println!("cargo:rustc-link-lib=dylib=stdc++");
        }

        match pkg_config::find_library("Qt5Core Qt5Gui Qt5Qml Qt5Quick Qt5Svg") {
            Ok(lib) => {
                for p in lib.link_paths { println!("cargo:rustc-link-search=native={}",p.display()); }
                for p in lib.libs { println!("cargo:rustc-link-lib=dylib={}",p); }
                if cfg!(target_os = "macos") {
                    for p in lib.frameworks { println!("cargo:rustc-link-lib=framework={}",p); }
                }
                for p in lib.include_paths { println!("cargo:include={}",p.display()); }
            }
            Err(e) => panic!("QT5 was not found using pkg-config: {}",e)
        }
    }
}

fn main() {
    let mut cmake_cfg = cmake::Config::new("DOtherSide");
    let dos_path = PathBuf::from("DOtherSide").join("CMakeLists.txt");

    if !dos_path.exists() {
        panic!("DOtherSide submodule not checked out. Please run 'git submodule init' followed by 'git submodule update'.");
    }

    if let Ok(gen) = env::var("CMAKE_GENERATOR") {
        cmake_cfg.generator(gen);
    }

    find_qt5(&mut cmake_cfg);
    build_dos(&mut cmake_cfg);
}
<commit_msg>added freebsd and bitrig for llvms libc++ option<commit_after>extern crate cmake;
extern crate pkg_config;

use std::env;
use std::env::consts;
use std::path::PathBuf;

fn build_dos(cmake_cfg: &mut cmake::Config) {
    let use_dos_dylib = option_env!("DyLib_DOtherSide").is_some();
    let dst = cmake_cfg.build();

    println!("cargo:rustc-link-search=native={}", dst.join("lib").display());

    if cfg!(windows) {
        println!("cargo:rustc-link-search=native={}", dst.join("build").join("lib").join("Release").display());
    } else {
        println!("cargo:rustc-link-search=native={}", dst.join("build").join("lib").display());
    }

    if use_dos_dylib {
        println!("cargo:rustc-link-lib=dylib=DOtherSide");
    } else {
        println!("cargo:rustc-link-lib=static=DOtherSideStatic");
    }
}

fn find_qt5(_: &mut cmake::Config) {
    /*
     * Support Qt installed via the Ports system on BSD-like systems.
     *
     * The native libs are in `/usr/local/lib`, which is not linked against by default.
     * This means that either the user or every package has to add this if they want to link
     * against something that is not part of the core distribution in `/usr/lib`.
     *
     * See https://wiki.freebsd.org/WarnerLosh/UsrLocal for the line of reasoning & how this will
     * change in the future.
     */
    if cfg!(any(target_os = "freebsd", target_os = "openbsd", target_os = "netbsd",
                target_os = "dragonfly", target_os = "bitrig")) {
        println!("cargo:rustc-link-search=native=/usr/local/lib");
    }

    /*
     * Parameters for supporting QT on OS X
     *
     * Because QT5 conflicts with QT4 the homebrew package manager won't link
     * the QT5 package into the default search paths for libraries, to deal
     * with this we need to give pkg-config and cmake a nudge in the right
     * direction.
     */
    if cfg!(target_os = "macos") {
        // We use the QTDIR or QTDIR64 env variables to find the location of
        // Qt5. If these are not set, we use the default homebrew install
        // location.
        let qtdir_variable = match consts::ARCH {
            "x86_64" => "QTDIR64",
            _ => "QTDIR",
        };
        let mut qt5_lib_path = PathBuf::new();
        qt5_lib_path.push(env::var(qtdir_variable).unwrap_or(String::from("/usr/local/opt/qt5")));
        qt5_lib_path.push("lib");

        if qt5_lib_path.exists() {
            // First nudge cmake in the direction of the .cmake files added by
            // homebrew. This clobbers the existing value if present, it's
            // unlikely to be present though.
            env::set_var("CMAKE_PREFIX_PATH", qt5_lib_path.join("cmake"));

            // Nudge pkg-config in the direction of the brewed QT to ensure the
            // correct compiler flags get found for the project.
            env::set_var("PKG_CONFIG_PATH", qt5_lib_path.join("pkgconfig"));
        } else {
            panic!("QT5 was not found at the expected location ({}) please install it via homebrew, or set the {} env variable.",
            qt5_lib_path.display(), qtdir_variable);
        }
    }

    if cfg!(windows) {
        let mut qt5_lib_path = PathBuf::new();
        qt5_lib_path.push(env::var("QTDIR").unwrap_or(String::from("C:\\Qt\\5.7\\msvc2015_64")));

        if qt5_lib_path.exists() {
            env::set_var("CMAKE_PREFIX_PATH", &qt5_lib_path);

            qt5_lib_path.push("lib");

            println!("cargo:rustc-link-search=native={}\\system32",env::var("WINDIR").unwrap());
            println!("cargo:rustc-link-search=native={}",qt5_lib_path.display());

            println!("cargo:rustc-link-lib=dylib=Qt5Core");
            println!("cargo:rustc-link-lib=dylib=Qt5Gui");
            println!("cargo:rustc-link-lib=dylib=Qt5Qml");
            println!("cargo:rustc-link-lib=dylib=Qt5Quick");
            println!("cargo:rustc-link-lib=dylib=Qt5Svg");
            println!("cargo:rustc-link-lib=dylib=Qt5Widgets");
        } else {
            panic!("QT5 was not found at the expected location ({}) please install the SDK or set the QTDIR env variable.",
            qt5_lib_path.display());
        }
    } else {
        use pkg_config;

        if cfg!(any(target_os = "macos", target_os = "freebsd", target_os = "bitrig")) {
            println!("cargo:rustc-link-lib=dylib=c++");
        } else {
            println!("cargo:rustc-link-lib=dylib=stdc++");
        }

        match pkg_config::find_library("Qt5Core Qt5Gui Qt5Qml Qt5Quick Qt5Svg") {
            Ok(lib) => {
                for p in lib.link_paths { println!("cargo:rustc-link-search=native={}",p.display()); }
                for p in lib.libs { println!("cargo:rustc-link-lib=dylib={}",p); }
                if cfg!(target_os = "macos") {
                    for p in lib.frameworks { println!("cargo:rustc-link-lib=framework={}",p); }
                }
                for p in lib.include_paths { println!("cargo:include={}",p.display()); }
            }
            Err(e) => panic!("QT5 was not found using pkg-config: {}",e)
        }
    }
}

fn main() {
    let mut cmake_cfg = cmake::Config::new("DOtherSide");
    let dos_path = PathBuf::from("DOtherSide").join("CMakeLists.txt");

    if !dos_path.exists() {
        panic!("DOtherSide submodule not checked out. Please run 'git submodule init' followed by 'git submodule update'.");
    }

    if let Ok(gen) = env::var("CMAKE_GENERATOR") {
        cmake_cfg.generator(gen);
    }

    find_qt5(&mut cmake_cfg);
    build_dos(&mut cmake_cfg);
}
<|endoftext|>


<commit_before>use camera::Camera;
use scene::Scene;
use ray::Ray;
use vec3::Vec3;

pub struct Renderer {
    pub reflect_depth: int,
    pub refract_depth: int,
    pub use_octree: bool,
    pub shadows: bool,
    pub threads: int
}

impl Renderer {
    pub fn render(&self, camera: Camera, scene: Scene) -> Vec<int> {
        // // ABANDONED THREADING SUPPORT

        // let (tx, rx): (Sender<Vec<int>>, Receiver<Vec<int>>) = channel();

        // // Copy camera and scene for now for each thread
        // // Use a per-tile task -- don't see utility in a per-trace/per-pixel task
        // // due to low processor count
        // for thread_no in range(0, 1) {
        //     let child_tx = tx.clone();

        //     spawn(proc() {
        //         let result = Renderer::render_tile(camera, scene, 0, 0, camera.image_width, camera.image_height);
        //         child_tx.send(result);
        //     });
        // }

        // // TODO: Composite tiles
        // // for range(0, 1) {
        //     let mut composite = rx.recv();
        // // }

        // composite

        Renderer::render_tile(camera, scene, true, 0, 0, camera.image_width, camera.image_height)
    }

    fn render_tile(camera: Camera,
                   scene: Scene,
                   shadows: bool,
                   from_x: int,
                   from_y: int,
                   to_x: int,
                   to_y: int)
                   -> Vec<int> {
        // TODO: replace int with uint or better
        let width  = to_x - from_x;
        let height = to_y - from_y;
        let tile_size = width * height * 3;
        let mut tile: Vec<int> = Vec::with_capacity(tile_size as uint);

        for y in range(from_y, to_y) {
            for x in range(from_x, to_x) {
                let ray = camera.get_ray(x, y);
                // Hardcoded reflect/refract depth, octree to come
                let color = Renderer::trace(&scene, &ray, shadows, 2, 4);

                // TODO: factor out floor to avoid premature precision loss
                // let index = ((x - from_x) * 3) + ((y - from_y) * width * 3);
                tile.push((color.x * 255.0) as int);
                tile.push((color.y * 255.0) as int);
                tile.push((color.z * 255.0) as int);
            }
        }

        tile
    }

    fn trace(scene: &Scene,
             ray: &Ray,
             shadows: bool,
             reflect_depth: int,
             refract_depth: int)
             -> Vec3 {
        if reflect_depth <= 0 || refract_depth <= 0 {
            return Vec3 {x: 0.0, y: 0.0, z: 0.0}
        }

        let nearest_hit = ray.get_nearest_hit(scene);

        match nearest_hit {
            Some(nearest_hit) => {
                let mut result = Vec3 {x: 0.0, y: 0.0, z: 0.0};
                let mut shadow = Vec3 {x: 1.0, y: 1.0, z: 1.0};

                let n = nearest_hit.n.unit();
                let i = (ray.direction.scale(-1.0)).unit();

                // Local lighting computation: surface shading, shadows
                for light in scene.lights.iter() {
                    let l = (light.position() - nearest_hit.position).unit();

                    if (shadows) {
                        // L has to be unit vector for t_max 1:1 correspondence to
                        // distance to light to work. Shadow feelers only search up
                        // until light source
                        let shadow_ray = Ray {origin: nearest_hit.position, direction: l};
                        let distance_to_light = (light.position() - nearest_hit.position).len();

                        // Check against candidate primitives in scene for occlusion
                        // and multiply shadow color by occluders' shadow colors
                        for prim in scene.prims.iter() {
                            let occulusion = prim.intersects(&shadow_ray, 0.0001, distance_to_light);
                            shadow = match occulusion {
                                Some(occulusion) => {shadow * occulusion.material.transmission()}
                                None => {shadow}
                            }
                        }
                    }

                    result = result + light.color() * nearest_hit.material.sample(n, i, l) * shadow;
                }

                // Global reflection
                if nearest_hit.material.is_specular() {
                    let r = Vec3::reflect(&ray.direction.scale(-1.0), &n);
                    let reflect_ray = Ray{origin: nearest_hit.position, direction: r};
                    let reflection = Renderer::trace(scene, &reflect_ray, shadows, reflect_depth - 1, refract_depth);

                    result = result + nearest_hit.material.global_specular(&reflection);
                }

                result
            }

            None => {
                scene.background
            }
        }
    }
}
<commit_msg>Flip image vertically.<commit_after>use camera::Camera;
use scene::Scene;
use ray::Ray;
use vec3::Vec3;

pub struct Renderer {
    pub reflect_depth: int,
    pub refract_depth: int,
    pub use_octree: bool,
    pub shadows: bool,
    pub threads: int
}

impl Renderer {
    pub fn render(&self, camera: Camera, scene: Scene) -> Vec<int> {
        // // ABANDONED THREADING SUPPORT

        // let (tx, rx): (Sender<Vec<int>>, Receiver<Vec<int>>) = channel();

        // // Copy camera and scene for now for each thread
        // // Use a per-tile task -- don't see utility in a per-trace/per-pixel task
        // // due to low processor count
        // for thread_no in range(0, 1) {
        //     let child_tx = tx.clone();

        //     spawn(proc() {
        //         let result = Renderer::render_tile(camera, scene, 0, 0, camera.image_width, camera.image_height);
        //         child_tx.send(result);
        //     });
        // }

        // // TODO: Composite tiles
        // // for range(0, 1) {
        //     let mut composite = rx.recv();
        // // }

        // composite

        Renderer::render_tile(camera, scene, true, 0, 0, camera.image_width, camera.image_height)
    }

    fn render_tile(camera: Camera,
                   scene: Scene,
                   shadows: bool,
                   from_x: int,
                   from_y: int,
                   to_x: int,
                   to_y: int)
                   -> Vec<int> {
        // TODO: replace int with uint or better
        let width  = to_x - from_x;
        let height = to_y - from_y;
        let tile_size = width * height * 3;
        let mut tile: Vec<int> = Vec::with_capacity(tile_size as uint);

        for y in range(from_y, to_y) {
            let inv_y = to_y - y;
            for x in range(from_x, to_x) {
                let ray = camera.get_ray(x, inv_y);
                // Hardcoded reflect/refract depth, octree to come
                let color = Renderer::trace(&scene, &ray, shadows, 2, 4);

                // TODO: factor out floor to avoid premature precision loss
                // let index = ((x - from_x) * 3) + ((y - from_y) * width * 3);
                tile.push((color.x * 255.0) as int);
                tile.push((color.y * 255.0) as int);
                tile.push((color.z * 255.0) as int);
            }
        }

        tile
    }

    fn trace(scene: &Scene,
             ray: &Ray,
             shadows: bool,
             reflect_depth: int,
             refract_depth: int)
             -> Vec3 {
        if reflect_depth <= 0 || refract_depth <= 0 {
            return Vec3 {x: 0.0, y: 0.0, z: 0.0}
        }

        let nearest_hit = ray.get_nearest_hit(scene);

        match nearest_hit {
            Some(nearest_hit) => {
                let mut result = Vec3 {x: 0.0, y: 0.0, z: 0.0};
                let mut shadow = Vec3 {x: 1.0, y: 1.0, z: 1.0};

                let n = nearest_hit.n.unit();
                let i = (ray.direction.scale(-1.0)).unit();

                // Local lighting computation: surface shading, shadows
                for light in scene.lights.iter() {
                    let l = (light.position() - nearest_hit.position).unit();

                    if (shadows) {
                        // L has to be unit vector for t_max 1:1 correspondence to
                        // distance to light to work. Shadow feelers only search up
                        // until light source
                        let shadow_ray = Ray {origin: nearest_hit.position, direction: l};
                        let distance_to_light = (light.position() - nearest_hit.position).len();

                        // Check against candidate primitives in scene for occlusion
                        // and multiply shadow color by occluders' shadow colors
                        for prim in scene.prims.iter() {
                            let occulusion = prim.intersects(&shadow_ray, 0.0001, distance_to_light);
                            shadow = match occulusion {
                                Some(occulusion) => {shadow * occulusion.material.transmission()}
                                None => {shadow}
                            }
                        }
                    }

                    result = result + light.color() * nearest_hit.material.sample(n, i, l) * shadow;
                }

                // Global reflection
                if nearest_hit.material.is_specular() {
                    let r = Vec3::reflect(&ray.direction.scale(-1.0), &n);
                    let reflect_ray = Ray{origin: nearest_hit.position, direction: r};
                    let reflection = Renderer::trace(scene, &reflect_ray, shadows, reflect_depth - 1, refract_depth);

                    result = result + nearest_hit.material.global_specular(&reflection);
                }

                result
            }

            None => {
                scene.background
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::str;
use std::ops::Deref;

use bytes::Bytes;

use clear::Clear;

/// Thin wrapper around `Bytes` which guarantees that bytes are valid UTF-8 string.
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Chars(Bytes);

impl Chars {
    /// New empty object.
    pub fn new() -> Chars {
        Chars(Bytes::new())
    }

    /// Try convert from `Bytes`
    pub fn from_bytes(bytes: Bytes) -> Result<Chars, str::Utf8Error> {
        str::from_utf8(&bytes)?;

        Ok(Chars(bytes))
    }

    /// Len in bytes.
    pub fn len(&self) -> usize {
        self.0.len()
    }

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

impl<'a> From<&'a str> for Chars {
    fn from(src: &'a str) -> Chars {
        Chars(Bytes::from(src))
    }
}

impl Default for Chars {
    fn default() -> Self {
        Chars::new()
    }
}

impl Deref for Chars {
    type Target = str;

    fn deref(&self) -> &str {
        unsafe {
            str::from_utf8_unchecked(&self.0)
        }
    }
}

impl Clear for Chars {
    fn clear(&mut self) {
        self.0.clear();
    }
}
<commit_msg>Impl Display and Debug for Chars<commit_after>use std::str;
use std::ops::Deref;
use std::fmt;

use bytes::Bytes;

use clear::Clear;

/// Thin wrapper around `Bytes` which guarantees that bytes are valid UTF-8 string.
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Chars(Bytes);

impl Chars {
    /// New empty object.
    pub fn new() -> Chars {
        Chars(Bytes::new())
    }

    /// Try convert from `Bytes`
    pub fn from_bytes(bytes: Bytes) -> Result<Chars, str::Utf8Error> {
        str::from_utf8(&bytes)?;

        Ok(Chars(bytes))
    }

    /// Len in bytes.
    pub fn len(&self) -> usize {
        self.0.len()
    }

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

impl<'a> From<&'a str> for Chars {
    fn from(src: &'a str) -> Chars {
        Chars(Bytes::from(src))
    }
}

impl Default for Chars {
    fn default() -> Self {
        Chars::new()
    }
}

impl Deref for Chars {
    type Target = str;

    fn deref(&self) -> &str {
        unsafe {
            str::from_utf8_unchecked(&self.0)
        }
    }
}

impl Clear for Chars {
    fn clear(&mut self) {
        self.0.clear();
    }
}

impl fmt::Display for Chars {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&**self, f)
    }
}

impl fmt::Debug for Chars {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&**self, f)
    }
}

#[cfg(test)]
mod test {
    use super::Chars;

    #[test]
    fn test_display_and_debug() {
        let s = "test";
        let string: String = s.into();
        let chars: Chars = s.into();

        assert_eq!(format!("{}", string), format!("{}", chars));
        assert_eq!(format!("{:?}", string), format!("{:?}", chars));
    }
}
<|endoftext|>


<commit_before>use super::Resource;

use alloc::boxed::Box;

use collections::String;
use collections::borrow::ToOwned;

use core::result::Result::{Ok, Err};

use common::slice::GetSlice;

use system::error::{Result, Error};
use system::syscall::{O_CREAT, O_RDWR, O_TRUNC};

/// An URL, see wiki
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub struct Url<'a> {
    scheme: &'a str,
    reference: &'a str,
}

impl<'a> Url<'a> {
    /// Create a new empty URL
    pub fn new() -> Url<'static> {
        Url {
            scheme: "",
            reference: "",
        }
    }

    /// Create from str
    pub fn from_str(string: &'a str) -> Result<Url<'a>> {
        let split = if let Some(x) = string.find(':') {
            x
        } else {
            return Err(Error::new(22));
        };

        Ok(Url {
            scheme: string.get_slice(..split),
            reference: string.get_slice(split + 1..),
        })
    }

    /// Convert the url to string
    pub fn to_string(self) -> String {
        self.scheme.to_owned() + ":" + self.reference
    }

    /// Get the length of this URL
    pub fn len(self) -> usize {
        self.scheme.len() + self.reference.len() + 1
    }

    /// Open this URL (returns a resource)
    pub fn open(self) -> Result<Box<Resource>> {
        ::env().open(self, O_RDWR)
    }

    /// Create this URL (returns a resource)
    pub fn create(self) -> Result<Box<Resource>> {
        ::env().open(self, O_CREAT | O_RDWR | O_TRUNC)
    }

    /// Return the scheme of this url
    pub fn scheme(self) -> &'a str {
        self.scheme
    }

    /// Get the reference (after the ':') of the url
    pub fn reference(self) -> &'a str {
        self.reference
    }

    /// To owned equivalent
    pub fn to_owned(&self) -> OwnedUrl {
        OwnedUrl {
            scheme: self.scheme.to_owned(),
            reference: self.reference.to_owned(),
        }
    }

    /// Into a cow
    pub fn to_cow(self) -> CowUrl<'a> {
        CowUrl::Ref(self)
    }
}

#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct OwnedUrl {
    scheme: String,
    reference: String,
}

impl OwnedUrl {
    /// Create a new empty URL
    pub fn new() -> OwnedUrl {
        OwnedUrl {
            scheme: String::new(),
            reference: String::new(),
        }
    }

    /// Into a cow
    pub fn into_cow<'a>(self) -> CowUrl<'a> {
        /*
             ______________
            < Mooooooooooo >
             --------------
                    \   ^__^
                     \  (oo)\_______
                        (__)\       )\/\
                            ||----w |
                            ||     ||

         */
        CowUrl::Owned(self)
    }

    /// As an unowned URL
    pub fn as_url(&self) -> Url {
        Url {
            scheme: &self.scheme,
            reference: &self.reference,
        }
    }
}

/// A Copy-On-Write URL
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub enum CowUrl<'a> {
    Ref(Url<'a>),
    Owned(OwnedUrl),
}

impl<'a> CowUrl<'a> {
    /// As URL
    pub fn as_url(&self) -> Url {
        match self {
            &CowUrl::Ref(u) => u,
            &CowUrl::Owned(ref u) => u.as_url(),
        }
    }
}
<commit_msg>Fixed URL capitalization consistency.<commit_after>use super::Resource;

use alloc::boxed::Box;

use collections::String;
use collections::borrow::ToOwned;

use core::result::Result::{Ok, Err};

use common::slice::GetSlice;

use system::error::{Result, Error};
use system::syscall::{O_CREAT, O_RDWR, O_TRUNC};

/// A URL, see wiki
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub struct Url<'a> {
    scheme: &'a str,
    reference: &'a str,
}

impl<'a> Url<'a> {
    /// Create a new empty URL
    pub fn new() -> Url<'static> {
        Url {
            scheme: "",
            reference: "",
        }
    }

    /// Create from str
    pub fn from_str(string: &'a str) -> Result<Url<'a>> {
        let split = if let Some(x) = string.find(':') {
            x
        } else {
            return Err(Error::new(22));
        };

        Ok(Url {
            scheme: string.get_slice(..split),
            reference: string.get_slice(split + 1..),
        })
    }

    /// Convert the URL to string
    pub fn to_string(self) -> String {
        self.scheme.to_owned() + ":" + self.reference
    }

    /// Get the length of this URL
    pub fn len(self) -> usize {
        self.scheme.len() + self.reference.len() + 1
    }

    /// Open this URL (returns a resource)
    pub fn open(self) -> Result<Box<Resource>> {
        ::env().open(self, O_RDWR)
    }

    /// Create this URL (returns a resource)
    pub fn create(self) -> Result<Box<Resource>> {
        ::env().open(self, O_CREAT | O_RDWR | O_TRUNC)
    }

    /// Return the scheme of this URL
    pub fn scheme(self) -> &'a str {
        self.scheme
    }

    /// Get the reference (after the ':') of the URL
    pub fn reference(self) -> &'a str {
        self.reference
    }

    /// To owned equivalent
    pub fn to_owned(&self) -> OwnedUrl {
        OwnedUrl {
            scheme: self.scheme.to_owned(),
            reference: self.reference.to_owned(),
        }
    }

    /// Into a cow
    pub fn to_cow(self) -> CowUrl<'a> {
        CowUrl::Ref(self)
    }
}

#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct OwnedUrl {
    scheme: String,
    reference: String,
}

impl OwnedUrl {
    /// Create a new empty URL
    pub fn new() -> OwnedUrl {
        OwnedUrl {
            scheme: String::new(),
            reference: String::new(),
        }
    }

    /// Into a cow
    pub fn into_cow<'a>(self) -> CowUrl<'a> {
        /*
             ______________
            < Mooooooooooo >
             --------------
                    \   ^__^
                     \  (oo)\_______
                        (__)\       )\/\
                            ||----w |
                            ||     ||

         */
        CowUrl::Owned(self)
    }

    /// As an unowned URL
    pub fn as_url(&self) -> Url {
        Url {
            scheme: &self.scheme,
            reference: &self.reference,
        }
    }
}

/// A Copy-On-Write URL
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub enum CowUrl<'a> {
    Ref(Url<'a>),
    Owned(OwnedUrl),
}

impl<'a> CowUrl<'a> {
    /// As URL
    pub fn as_url(&self) -> Url {
        match self {
            &CowUrl::Ref(u) => u,
            &CowUrl::Owned(ref u) => u.as_url(),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Developers of the Rand project.
// Copyright 2017 Paul Dicker.
// Copyright 2014-2017 Melissa O'Neill and PCG Project contributors
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! PCG random number generators

use core::fmt;
use rand_core::{impls, le, Error, RngCore, SeedableRng};
#[cfg(feature = "serde1")] use serde::{Deserialize, Serialize};

// This is the default multiplier used by PCG for 64-bit state.
const MULTIPLIER: u64 = 6364136223846793005;

/// A PCG random number generator (XSH RR 64/32 (LCG) variant).
///
/// Permuted Congruential Generator with 64-bit state, internal Linear
/// Congruential Generator, and 32-bit output via "xorshift high (bits),
/// random rotation" output function.
///
/// This is a 64-bit LCG with explicitly chosen stream with the PCG-XSH-RR
/// output function. This combination is the standard `pcg32`.
///
/// Despite the name, this implementation uses 16 bytes (128 bit) space
/// comprising 64 bits of state and 64 bits stream selector. These are both set
/// by `SeedableRng`, using a 128-bit seed.
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
pub struct Lcg64Xsh32 {
    state: u64,
    increment: u64,
}

/// [`Lcg64Xsh32`] is also officially known as `pcg32`.
pub type Pcg32 = Lcg64Xsh32;

impl Lcg64Xsh32 {
    /// Multi-step advance functions (jump-ahead, jump-back)
    ///
    /// The method used here is based on Brown, "Random Number Generation
    /// with Arbitrary Stride,", Transactions of the American Nuclear
    /// Society (Nov. 1994).  The algorithm is very similar to fast
    /// exponentiation.
    ///
    /// Even though delta is an unsigned integer, we can pass a
    /// signed integer to go backwards, it just goes "the long way round".
    #[inline]
    pub fn advance(&mut self, delta: u64) {
        let mut acc_mult: u64 = 1;
        let mut acc_plus: u64 = 0;
        let mut cur_mult = MULTIPLIER;
        let mut cur_plus = self.increment;
        let mut mdelta = delta;

        while mdelta > 0 {
            if (mdelta & 1) != 0 {
                acc_mult = acc_mult.wrapping_mul(cur_mult);
                acc_plus = acc_plus.wrapping_mul(cur_mult).wrapping_add(cur_plus);
            }
            cur_plus = cur_mult.wrapping_add(1).wrapping_mul(cur_plus);
            cur_mult = cur_mult.wrapping_mul(cur_mult);
            mdelta /= 2;
        }
        self.state = acc_mult.wrapping_mul(self.state).wrapping_add(acc_plus);
    }

    /// Construct an instance compatible with PCG seed and stream.
    ///
    /// Note that PCG specifies default values for both parameters:
    ///
    /// - `state = 0xcafef00dd15ea5e5`
    /// - `stream = 0xa02bdbf7bb3c0a7`
    // Note: stream is 1442695040888963407u64 >> 1
    pub fn new(state: u64, stream: u64) -> Self {
        // The increment must be odd, hence we discard one bit:
        let increment = (stream << 1) | 1;
        Lcg64Xsh32::from_state_incr(state, increment)
    }

    #[inline]
    fn from_state_incr(state: u64, increment: u64) -> Self {
        let mut pcg = Lcg64Xsh32 { state, increment };
        // Move away from inital value:
        pcg.state = pcg.state.wrapping_add(pcg.increment);
        pcg.step();
        pcg
    }

    #[inline]
    fn step(&mut self) {
        // prepare the LCG for the next round
        self.state = self
            .state
            .wrapping_mul(MULTIPLIER)
            .wrapping_add(self.increment);
    }
}

// Custom Debug implementation that does not expose the internal state
impl fmt::Debug for Lcg64Xsh32 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Lcg64Xsh32 {{}}")
    }
}

/// We use a single 127-bit seed to initialise the state and select a stream.
/// One `seed` bit (lowest bit of `seed[8]`) is ignored.
impl SeedableRng for Lcg64Xsh32 {
    type Seed = [u8; 16];

    fn from_seed(seed: Self::Seed) -> Self {
        let mut seed_u64 = [0u64; 2];
        le::read_u64_into(&seed, &mut seed_u64);

        // The increment must be odd, hence we discard one bit:
        Lcg64Xsh32::from_state_incr(seed_u64[0], seed_u64[1] | 1)
    }
}

impl RngCore for Lcg64Xsh32 {
    #[inline]
    fn next_u32(&mut self) -> u32 {
        let state = self.state;
        self.step();

        // Output function XSH RR: xorshift high (bits), followed by a random rotate
        // Constants are for 64-bit state, 32-bit output
        const ROTATE: u32 = 59; // 64 - 5
        const XSHIFT: u32 = 18; // (5 + 32) / 2
        const SPARE: u32 = 27; // 64 - 32 - 5

        let rot = (state >> ROTATE) as u32;
        let xsh = (((state >> XSHIFT) ^ state) >> SPARE) as u32;
        xsh.rotate_right(rot)
    }

    #[inline]
    fn next_u64(&mut self) -> u64 {
        impls::next_u64_via_u32(self)
    }

    #[inline]
    fn fill_bytes(&mut self, dest: &mut [u8]) {
        impls::fill_bytes_via_next(self, dest)
    }

    #[inline]
    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
        self.fill_bytes(dest);
        Ok(())
    }
}
<commit_msg>Delta needs to be doubled when advancing Lcg64Xsh32<commit_after>// Copyright 2018 Developers of the Rand project.
// Copyright 2017 Paul Dicker.
// Copyright 2014-2017 Melissa O'Neill and PCG Project contributors
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! PCG random number generators

use core::fmt;
use rand_core::{impls, le, Error, RngCore, SeedableRng};
#[cfg(feature = "serde1")] use serde::{Deserialize, Serialize};

// This is the default multiplier used by PCG for 64-bit state.
const MULTIPLIER: u64 = 6364136223846793005;

/// A PCG random number generator (XSH RR 64/32 (LCG) variant).
///
/// Permuted Congruential Generator with 64-bit state, internal Linear
/// Congruential Generator, and 32-bit output via "xorshift high (bits),
/// random rotation" output function.
///
/// This is a 64-bit LCG with explicitly chosen stream with the PCG-XSH-RR
/// output function. This combination is the standard `pcg32`.
///
/// Despite the name, this implementation uses 16 bytes (128 bit) space
/// comprising 64 bits of state and 64 bits stream selector. These are both set
/// by `SeedableRng`, using a 128-bit seed.
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
pub struct Lcg64Xsh32 {
    state: u64,
    increment: u64,
}

/// [`Lcg64Xsh32`] is also officially known as `pcg32`.
pub type Pcg32 = Lcg64Xsh32;

impl Lcg64Xsh32 {
    /// Multi-step advance functions (jump-ahead, jump-back)
    ///
    /// The method used here is based on Brown, "Random Number Generation
    /// with Arbitrary Stride,", Transactions of the American Nuclear
    /// Society (Nov. 1994).  The algorithm is very similar to fast
    /// exponentiation.
    ///
    /// Even though delta is an unsigned integer, we can pass a
    /// signed integer to go backwards, it just goes "the long way round".
    #[inline]
    pub fn advance(&mut self, delta: u64) {
        let mut acc_mult: u64 = 1;
        let mut acc_plus: u64 = 0;
        let mut cur_mult = MULTIPLIER;
        let mut cur_plus = self.increment;
        let mut mdelta = delta.wrapping_mul(2);

        while mdelta > 0 {
            if (mdelta & 1) != 0 {
                acc_mult = acc_mult.wrapping_mul(cur_mult);
                acc_plus = acc_plus.wrapping_mul(cur_mult).wrapping_add(cur_plus);
            }
            cur_plus = cur_mult.wrapping_add(1).wrapping_mul(cur_plus);
            cur_mult = cur_mult.wrapping_mul(cur_mult);
            mdelta /= 2;
        }
        self.state = acc_mult.wrapping_mul(self.state).wrapping_add(acc_plus);
    }

    /// Construct an instance compatible with PCG seed and stream.
    ///
    /// Note that PCG specifies default values for both parameters:
    ///
    /// - `state = 0xcafef00dd15ea5e5`
    /// - `stream = 0xa02bdbf7bb3c0a7`
    // Note: stream is 1442695040888963407u64 >> 1
    pub fn new(state: u64, stream: u64) -> Self {
        // The increment must be odd, hence we discard one bit:
        let increment = (stream << 1) | 1;
        Lcg64Xsh32::from_state_incr(state, increment)
    }

    #[inline]
    fn from_state_incr(state: u64, increment: u64) -> Self {
        let mut pcg = Lcg64Xsh32 { state, increment };
        // Move away from inital value:
        pcg.state = pcg.state.wrapping_add(pcg.increment);
        pcg.step();
        pcg
    }

    #[inline]
    fn step(&mut self) {
        // prepare the LCG for the next round
        self.state = self
            .state
            .wrapping_mul(MULTIPLIER)
            .wrapping_add(self.increment);
    }
}

// Custom Debug implementation that does not expose the internal state
impl fmt::Debug for Lcg64Xsh32 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Lcg64Xsh32 {{}}")
    }
}

/// We use a single 127-bit seed to initialise the state and select a stream.
/// One `seed` bit (lowest bit of `seed[8]`) is ignored.
impl SeedableRng for Lcg64Xsh32 {
    type Seed = [u8; 16];

    fn from_seed(seed: Self::Seed) -> Self {
        let mut seed_u64 = [0u64; 2];
        le::read_u64_into(&seed, &mut seed_u64);

        // The increment must be odd, hence we discard one bit:
        Lcg64Xsh32::from_state_incr(seed_u64[0], seed_u64[1] | 1)
    }
}

impl RngCore for Lcg64Xsh32 {
    #[inline]
    fn next_u32(&mut self) -> u32 {
        let state = self.state;
        self.step();

        // Output function XSH RR: xorshift high (bits), followed by a random rotate
        // Constants are for 64-bit state, 32-bit output
        const ROTATE: u32 = 59; // 64 - 5
        const XSHIFT: u32 = 18; // (5 + 32) / 2
        const SPARE: u32 = 27; // 64 - 32 - 5

        let rot = (state >> ROTATE) as u32;
        let xsh = (((state >> XSHIFT) ^ state) >> SPARE) as u32;
        xsh.rotate_right(rot)
    }

    #[inline]
    fn next_u64(&mut self) -> u64 {
        impls::next_u64_via_u32(self)
    }

    #[inline]
    fn fill_bytes(&mut self, dest: &mut [u8]) {
        impls::fill_bytes_via_next(self, dest)
    }

    #[inline]
    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
        self.fill_bytes(dest);
        Ok(())
    }
}
<|endoftext|>