<commit_before>//! Tests for profiles.

use std::env;

use cargo_test_support::{is_nightly, project};

#[cargo_test]
fn profile_overrides() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]

            name = "test"
            version = "0.0.0"
            authors = []

            [profile.dev]
            opt-level = 1
            debug = false
            rpath = true
        "#,
        )
        .file("src/lib.rs", "")
        .build();
    p.cargo("build -v")
        .with_stderr(
            "\
[COMPILING] test v0.0.0 ([CWD])
[RUNNING] `rustc --crate-name test src/lib.rs [..]--crate-type lib \
        --emit=[..]link[..]\
        -C opt-level=1[..]\
        -C debug-assertions=on \
        -C metadata=[..] \
        -C rpath \
        --out-dir [..] \
        -L dependency=[CWD]/target/debug/deps`
[FINISHED] dev [optimized] target(s) in [..]
",
        )
        .run();
}

#[cargo_test]
fn opt_level_override_0() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]

            name = "test"
            version = "0.0.0"
            authors = []

            [profile.dev]
            opt-level = 0
        "#,
        )
        .file("src/lib.rs", "")
        .build();
    p.cargo("build -v")
        .with_stderr(
            "\
[COMPILING] test v0.0.0 ([CWD])
[RUNNING] `rustc --crate-name test src/lib.rs [..]--crate-type lib \
        --emit=[..]link[..]\
        -C debuginfo=2 \
        -C metadata=[..] \
        --out-dir [..] \
        -L dependency=[CWD]/target/debug/deps`
[FINISHED] [..] target(s) in [..]
",
        )
        .run();
}

#[cargo_test]
fn debug_override_1() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]
            name = "test"
            version = "0.0.0"
            authors = []

            [profile.dev]
            debug = 1
        "#,
        )
        .file("src/lib.rs", "")
        .build();
    p.cargo("build -v")
        .with_stderr(
            "\
[COMPILING] test v0.0.0 ([CWD])
[RUNNING] `rustc --crate-name test src/lib.rs [..]--crate-type lib \
        --emit=[..]link[..]\
        -C debuginfo=1 \
        -C metadata=[..] \
        --out-dir [..] \
        -L dependency=[CWD]/target/debug/deps`
[FINISHED] [..] target(s) in [..]
",
        )
        .run();
}

fn check_opt_level_override(profile_level: &str, rustc_level: &str) {
    let p = project()
        .file(
            "Cargo.toml",
            &format!(
                r#"
            [package]

            name = "test"
            version = "0.0.0"
            authors = []

            [profile.dev]
            opt-level = {level}
        "#,
                level = profile_level
            ),
        )
        .file("src/lib.rs", "")
        .build();
    p.cargo("build -v")
        .with_stderr(&format!(
            "\
[COMPILING] test v0.0.0 ([CWD])
[RUNNING] `rustc --crate-name test src/lib.rs [..]--crate-type lib \
        --emit=[..]link \
        -C opt-level={level}[..]\
        -C debuginfo=2 \
        -C debug-assertions=on \
        -C metadata=[..] \
        --out-dir [..] \
        -L dependency=[CWD]/target/debug/deps`
[FINISHED] [..] target(s) in [..]
",
            level = rustc_level
        ))
        .run();
}

#[cargo_test]
fn opt_level_overrides() {
    for &(profile_level, rustc_level) in &[
        ("1", "1"),
        ("2", "2"),
        ("3", "3"),
        ("\"s\"", "s"),
        ("\"z\"", "z"),
    ] {
        check_opt_level_override(profile_level, rustc_level)
    }
}

#[cargo_test]
fn top_level_overrides_deps() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]

            name = "test"
            version = "0.0.0"
            authors = []

            [profile.release]
            opt-level = 1
            debug = true

            [dependencies.foo]
            path = "foo"
        "#,
        )
        .file("src/lib.rs", "")
        .file(
            "foo/Cargo.toml",
            r#"
            [package]

            name = "foo"
            version = "0.0.0"
            authors = []

            [profile.release]
            opt-level = 0
            debug = false

            [lib]
            name = "foo"
            crate_type = ["dylib", "rlib"]
        "#,
        )
        .file("foo/src/lib.rs", "")
        .build();
    p.cargo("build -v --release")
        .with_stderr(&format!(
            "\
[COMPILING] foo v0.0.0 ([CWD]/foo)
[RUNNING] `rustc --crate-name foo foo/src/lib.rs [..]\
        --crate-type dylib --crate-type rlib \
        --emit=[..]link \
        -C prefer-dynamic \
        -C opt-level=1[..]\
        -C debuginfo=2 \
        -C metadata=[..] \
        --out-dir [CWD]/target/release/deps \
        -L dependency=[CWD]/target/release/deps`
[COMPILING] test v0.0.0 ([CWD])
[RUNNING] `rustc --crate-name test src/lib.rs [..]--crate-type lib \
        --emit=[..]link \
        -C opt-level=1[..]\
        -C debuginfo=2 \
        -C metadata=[..] \
        --out-dir [..] \
        -L dependency=[CWD]/target/release/deps \
        --extern foo=[CWD]/target/release/deps/\
                     {prefix}foo[..]{suffix} \
        --extern foo=[CWD]/target/release/deps/libfoo.rlib`
[FINISHED] release [optimized + debuginfo] target(s) in [..]
",
            prefix = env::consts::DLL_PREFIX,
            suffix = env::consts::DLL_SUFFIX
        ))
        .run();
}

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

            [workspace]
            members = ["bar"]

            [profile.dev]
            debug = false
        "#,
        )
        .file("src/main.rs", "fn main() {}")
        .file(
            "bar/Cargo.toml",
            r#"
            [project]
            name = "bar"
            version = "0.1.0"
            authors = []
            workspace = ".."

            [profile.dev]
            opt-level = 1
        "#,
        )
        .file("bar/src/main.rs", "fn main() {}")
        .build();

    p.cargo("build -v")
        .cwd("bar")
        .with_stderr(
            "\
[WARNING] profiles for the non root package will be ignored, specify profiles at the workspace root:
package:   [..]
workspace: [..]
[COMPILING] bar v0.1.0 ([..])
[RUNNING] `rustc [..]`
[FINISHED] dev [unoptimized] target(s) in [..]",
        )
        .run();
}

#[cargo_test]
fn profile_in_virtual_manifest_works() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [workspace]
            members = ["bar"]

            [profile.dev]
            opt-level = 1
            debug = false
        "#,
        )
        .file("src/main.rs", "fn main() {}")
        .file(
            "bar/Cargo.toml",
            r#"
            [project]
            name = "bar"
            version = "0.1.0"
            authors = []
            workspace = ".."
        "#,
        )
        .file("bar/src/main.rs", "fn main() {}")
        .build();

    p.cargo("build -v")
        .cwd("bar")
        .with_stderr(
            "\
[COMPILING] bar v0.1.0 ([..])
[RUNNING] `rustc [..]`
[FINISHED] dev [optimized] target(s) in [..]",
        )
        .run();
}

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

            [profile.test]
            panic = "abort"

            [profile.bench]
            panic = "abort"
        "#,
        )
        .file("src/lib.rs", "")
        .build();

    p.cargo("build")
        .with_stderr_contains(
            "\
[WARNING] `panic` setting is ignored for `bench` profile
[WARNING] `panic` setting is ignored for `test` profile
",
        )
        .run();
}

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

            [profile.doc]
            opt-level = 0
        "#,
        )
        .file("src/lib.rs", "")
        .build();

    p.cargo("build")
        .with_stderr_contains("[WARNING] profile `doc` is deprecated and has no effect")
        .run();
}

#[cargo_test]
fn panic_unwind_does_not_build_twice() {
    // Check for a bug where `lib` was built twice, once with panic set and
    // once without. Since "unwind" is the default, they are the same and
    // should only be built once.
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]
            name = "foo"
            version = "0.1.0"

            [profile.dev]
            panic = "unwind"
            "#,
        )
        .file("src/lib.rs", "")
        .file("src/main.rs", "fn main() {}")
        .file("tests/t1.rs", "")
        .build();

    p.cargo("test -v --tests --no-run")
        .with_stderr_unordered(
            "\
[COMPILING] foo [..]
[RUNNING] `rustc --crate-name foo src/lib.rs [..]--crate-type lib [..]
[RUNNING] `rustc --crate-name foo src/lib.rs [..] --test [..]
[RUNNING] `rustc --crate-name foo src/main.rs [..]--crate-type bin [..]
[RUNNING] `rustc --crate-name foo src/main.rs [..] --test [..]
[RUNNING] `rustc --crate-name t1 tests/t1.rs [..]
[FINISHED] [..]
",
        )
        .run();
}

#[cargo_test]
fn debug_0_report() {
    // The finished line handles 0 correctly.
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]
            name = "foo"
            version = "0.1.0"

            [profile.dev]
            debug = 0
            "#,
        )
        .file("src/lib.rs", "")
        .build();

    p.cargo("build -v")
        .with_stderr(
            "\
[COMPILING] foo v0.1.0 [..]
[RUNNING] `rustc --crate-name foo src/lib.rs [..]-C debuginfo=0 [..]
[FINISHED] dev [unoptimized] target(s) in [..]
",
        )
        .run();
}

#[cargo_test]
fn thin_lto_works() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [project]
            name = "top"
            version = "0.5.0"
            authors = []

            [profile.release]
            lto = 'thin'
        "#,
        )
        .file("src/main.rs", "fn main() {}")
        .build();

    p.cargo("build --release -v")
        .with_stderr(
            "\
[COMPILING] top [..]
[RUNNING] `rustc [..] -C lto=thin [..]`
[FINISHED] [..]
",
        )
        .run();
}

#[cargo_test]
fn strip_works() {
    if !is_nightly() {
        return;
    }

    let p = project()
        .file(
            "Cargo.toml",
            r#"
            cargo-features = ["strip"]

            [package]
            name = "foo"
            version = "0.1.0"

            [profile.release]
            strip = 'symbols'
        "#,
        )
        .file("src/main.rs", "fn main() {}")
        .build();

    p.cargo("build --release -v")
        .masquerade_as_nightly_cargo()
        .with_stderr(
            "\
[COMPILING] foo [..]
[RUNNING] `rustc [..] -Z strip=symbols [..]`
[FINISHED] [..]
",
        )
        .run();
}

#[cargo_test]
fn strip_requires_cargo_feature() {
    if !is_nightly() {
        return;
    }

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

            [profile.release]
            strip = 'symbols'
        "#,
        )
        .file("src/main.rs", "fn main() {}")
        .build();

    p.cargo("build --release -v")
        .masquerade_as_nightly_cargo()
        .with_status(101)
        .with_stderr(
            "\
[ERROR] failed to parse manifest at `[CWD]/Cargo.toml`

Caused by:
  feature `strip` is required

consider adding `cargo-features = [\"strip\"]` to the manifest
",
        )
        .run();
}
#[cargo_test]
fn strip_rejects_invalid_option() {
    if !is_nightly() {
        return;
    }

    let p = project()
        .file(
            "Cargo.toml",
            r#"
            cargo-features = ["strip"]

            [package]
            name = "foo"
            version = "0.1.0"

            [profile.release]
            strip = 'wrong'
        "#,
        )
        .file("src/main.rs", "fn main() {}")
        .build();

    p.cargo("build --release -v")
        .masquerade_as_nightly_cargo()
        .with_status(101)
        .with_stderr(
            "\
[ERROR] failed to parse manifest at `[CWD]/Cargo.toml`

Caused by:
  unknown variant `wrong`, expected one of `debuginfo`, `none`, `symbols` for key [..]
",
        )
        .run();
}
<commit_msg>Auto merge of #8301 - ehuss:disable-strip-macos, r=alexcrichton<commit_after>//! Tests for profiles.

use std::env;

use cargo_test_support::{is_nightly, project};

#[cargo_test]
fn profile_overrides() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]

            name = "test"
            version = "0.0.0"
            authors = []

            [profile.dev]
            opt-level = 1
            debug = false
            rpath = true
        "#,
        )
        .file("src/lib.rs", "")
        .build();
    p.cargo("build -v")
        .with_stderr(
            "\
[COMPILING] test v0.0.0 ([CWD])
[RUNNING] `rustc --crate-name test src/lib.rs [..]--crate-type lib \
        --emit=[..]link[..]\
        -C opt-level=1[..]\
        -C debug-assertions=on \
        -C metadata=[..] \
        -C rpath \
        --out-dir [..] \
        -L dependency=[CWD]/target/debug/deps`
[FINISHED] dev [optimized] target(s) in [..]
",
        )
        .run();
}

#[cargo_test]
fn opt_level_override_0() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]

            name = "test"
            version = "0.0.0"
            authors = []

            [profile.dev]
            opt-level = 0
        "#,
        )
        .file("src/lib.rs", "")
        .build();
    p.cargo("build -v")
        .with_stderr(
            "\
[COMPILING] test v0.0.0 ([CWD])
[RUNNING] `rustc --crate-name test src/lib.rs [..]--crate-type lib \
        --emit=[..]link[..]\
        -C debuginfo=2 \
        -C metadata=[..] \
        --out-dir [..] \
        -L dependency=[CWD]/target/debug/deps`
[FINISHED] [..] target(s) in [..]
",
        )
        .run();
}

#[cargo_test]
fn debug_override_1() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]
            name = "test"
            version = "0.0.0"
            authors = []

            [profile.dev]
            debug = 1
        "#,
        )
        .file("src/lib.rs", "")
        .build();
    p.cargo("build -v")
        .with_stderr(
            "\
[COMPILING] test v0.0.0 ([CWD])
[RUNNING] `rustc --crate-name test src/lib.rs [..]--crate-type lib \
        --emit=[..]link[..]\
        -C debuginfo=1 \
        -C metadata=[..] \
        --out-dir [..] \
        -L dependency=[CWD]/target/debug/deps`
[FINISHED] [..] target(s) in [..]
",
        )
        .run();
}

fn check_opt_level_override(profile_level: &str, rustc_level: &str) {
    let p = project()
        .file(
            "Cargo.toml",
            &format!(
                r#"
            [package]

            name = "test"
            version = "0.0.0"
            authors = []

            [profile.dev]
            opt-level = {level}
        "#,
                level = profile_level
            ),
        )
        .file("src/lib.rs", "")
        .build();
    p.cargo("build -v")
        .with_stderr(&format!(
            "\
[COMPILING] test v0.0.0 ([CWD])
[RUNNING] `rustc --crate-name test src/lib.rs [..]--crate-type lib \
        --emit=[..]link \
        -C opt-level={level}[..]\
        -C debuginfo=2 \
        -C debug-assertions=on \
        -C metadata=[..] \
        --out-dir [..] \
        -L dependency=[CWD]/target/debug/deps`
[FINISHED] [..] target(s) in [..]
",
            level = rustc_level
        ))
        .run();
}

#[cargo_test]
fn opt_level_overrides() {
    for &(profile_level, rustc_level) in &[
        ("1", "1"),
        ("2", "2"),
        ("3", "3"),
        ("\"s\"", "s"),
        ("\"z\"", "z"),
    ] {
        check_opt_level_override(profile_level, rustc_level)
    }
}

#[cargo_test]
fn top_level_overrides_deps() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]

            name = "test"
            version = "0.0.0"
            authors = []

            [profile.release]
            opt-level = 1
            debug = true

            [dependencies.foo]
            path = "foo"
        "#,
        )
        .file("src/lib.rs", "")
        .file(
            "foo/Cargo.toml",
            r#"
            [package]

            name = "foo"
            version = "0.0.0"
            authors = []

            [profile.release]
            opt-level = 0
            debug = false

            [lib]
            name = "foo"
            crate_type = ["dylib", "rlib"]
        "#,
        )
        .file("foo/src/lib.rs", "")
        .build();
    p.cargo("build -v --release")
        .with_stderr(&format!(
            "\
[COMPILING] foo v0.0.0 ([CWD]/foo)
[RUNNING] `rustc --crate-name foo foo/src/lib.rs [..]\
        --crate-type dylib --crate-type rlib \
        --emit=[..]link \
        -C prefer-dynamic \
        -C opt-level=1[..]\
        -C debuginfo=2 \
        -C metadata=[..] \
        --out-dir [CWD]/target/release/deps \
        -L dependency=[CWD]/target/release/deps`
[COMPILING] test v0.0.0 ([CWD])
[RUNNING] `rustc --crate-name test src/lib.rs [..]--crate-type lib \
        --emit=[..]link \
        -C opt-level=1[..]\
        -C debuginfo=2 \
        -C metadata=[..] \
        --out-dir [..] \
        -L dependency=[CWD]/target/release/deps \
        --extern foo=[CWD]/target/release/deps/\
                     {prefix}foo[..]{suffix} \
        --extern foo=[CWD]/target/release/deps/libfoo.rlib`
[FINISHED] release [optimized + debuginfo] target(s) in [..]
",
            prefix = env::consts::DLL_PREFIX,
            suffix = env::consts::DLL_SUFFIX
        ))
        .run();
}

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

            [workspace]
            members = ["bar"]

            [profile.dev]
            debug = false
        "#,
        )
        .file("src/main.rs", "fn main() {}")
        .file(
            "bar/Cargo.toml",
            r#"
            [project]
            name = "bar"
            version = "0.1.0"
            authors = []
            workspace = ".."

            [profile.dev]
            opt-level = 1
        "#,
        )
        .file("bar/src/main.rs", "fn main() {}")
        .build();

    p.cargo("build -v")
        .cwd("bar")
        .with_stderr(
            "\
[WARNING] profiles for the non root package will be ignored, specify profiles at the workspace root:
package:   [..]
workspace: [..]
[COMPILING] bar v0.1.0 ([..])
[RUNNING] `rustc [..]`
[FINISHED] dev [unoptimized] target(s) in [..]",
        )
        .run();
}

#[cargo_test]
fn profile_in_virtual_manifest_works() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [workspace]
            members = ["bar"]

            [profile.dev]
            opt-level = 1
            debug = false
        "#,
        )
        .file("src/main.rs", "fn main() {}")
        .file(
            "bar/Cargo.toml",
            r#"
            [project]
            name = "bar"
            version = "0.1.0"
            authors = []
            workspace = ".."
        "#,
        )
        .file("bar/src/main.rs", "fn main() {}")
        .build();

    p.cargo("build -v")
        .cwd("bar")
        .with_stderr(
            "\
[COMPILING] bar v0.1.0 ([..])
[RUNNING] `rustc [..]`
[FINISHED] dev [optimized] target(s) in [..]",
        )
        .run();
}

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

            [profile.test]
            panic = "abort"

            [profile.bench]
            panic = "abort"
        "#,
        )
        .file("src/lib.rs", "")
        .build();

    p.cargo("build")
        .with_stderr_contains(
            "\
[WARNING] `panic` setting is ignored for `bench` profile
[WARNING] `panic` setting is ignored for `test` profile
",
        )
        .run();
}

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

            [profile.doc]
            opt-level = 0
        "#,
        )
        .file("src/lib.rs", "")
        .build();

    p.cargo("build")
        .with_stderr_contains("[WARNING] profile `doc` is deprecated and has no effect")
        .run();
}

#[cargo_test]
fn panic_unwind_does_not_build_twice() {
    // Check for a bug where `lib` was built twice, once with panic set and
    // once without. Since "unwind" is the default, they are the same and
    // should only be built once.
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]
            name = "foo"
            version = "0.1.0"

            [profile.dev]
            panic = "unwind"
            "#,
        )
        .file("src/lib.rs", "")
        .file("src/main.rs", "fn main() {}")
        .file("tests/t1.rs", "")
        .build();

    p.cargo("test -v --tests --no-run")
        .with_stderr_unordered(
            "\
[COMPILING] foo [..]
[RUNNING] `rustc --crate-name foo src/lib.rs [..]--crate-type lib [..]
[RUNNING] `rustc --crate-name foo src/lib.rs [..] --test [..]
[RUNNING] `rustc --crate-name foo src/main.rs [..]--crate-type bin [..]
[RUNNING] `rustc --crate-name foo src/main.rs [..] --test [..]
[RUNNING] `rustc --crate-name t1 tests/t1.rs [..]
[FINISHED] [..]
",
        )
        .run();
}

#[cargo_test]
fn debug_0_report() {
    // The finished line handles 0 correctly.
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]
            name = "foo"
            version = "0.1.0"

            [profile.dev]
            debug = 0
            "#,
        )
        .file("src/lib.rs", "")
        .build();

    p.cargo("build -v")
        .with_stderr(
            "\
[COMPILING] foo v0.1.0 [..]
[RUNNING] `rustc --crate-name foo src/lib.rs [..]-C debuginfo=0 [..]
[FINISHED] dev [unoptimized] target(s) in [..]
",
        )
        .run();
}

#[cargo_test]
fn thin_lto_works() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [project]
            name = "top"
            version = "0.5.0"
            authors = []

            [profile.release]
            lto = 'thin'
        "#,
        )
        .file("src/main.rs", "fn main() {}")
        .build();

    p.cargo("build --release -v")
        .with_stderr(
            "\
[COMPILING] top [..]
[RUNNING] `rustc [..] -C lto=thin [..]`
[FINISHED] [..]
",
        )
        .run();
}

#[cargo_test]
// Strip doesn't work on macos.
#[cfg_attr(target_os = "macos", ignore)]
fn strip_works() {
    if !is_nightly() {
        return;
    }

    let p = project()
        .file(
            "Cargo.toml",
            r#"
            cargo-features = ["strip"]

            [package]
            name = "foo"
            version = "0.1.0"

            [profile.release]
            strip = 'symbols'
        "#,
        )
        .file("src/main.rs", "fn main() {}")
        .build();

    p.cargo("build --release -v")
        .masquerade_as_nightly_cargo()
        .with_stderr(
            "\
[COMPILING] foo [..]
[RUNNING] `rustc [..] -Z strip=symbols [..]`
[FINISHED] [..]
",
        )
        .run();
}

#[cargo_test]
fn strip_requires_cargo_feature() {
    if !is_nightly() {
        return;
    }

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

            [profile.release]
            strip = 'symbols'
        "#,
        )
        .file("src/main.rs", "fn main() {}")
        .build();

    p.cargo("build --release -v")
        .masquerade_as_nightly_cargo()
        .with_status(101)
        .with_stderr(
            "\
[ERROR] failed to parse manifest at `[CWD]/Cargo.toml`

Caused by:
  feature `strip` is required

consider adding `cargo-features = [\"strip\"]` to the manifest
",
        )
        .run();
}
#[cargo_test]
fn strip_rejects_invalid_option() {
    if !is_nightly() {
        return;
    }

    let p = project()
        .file(
            "Cargo.toml",
            r#"
            cargo-features = ["strip"]

            [package]
            name = "foo"
            version = "0.1.0"

            [profile.release]
            strip = 'wrong'
        "#,
        )
        .file("src/main.rs", "fn main() {}")
        .build();

    p.cargo("build --release -v")
        .masquerade_as_nightly_cargo()
        .with_status(101)
        .with_stderr(
            "\
[ERROR] failed to parse manifest at `[CWD]/Cargo.toml`

Caused by:
  unknown variant `wrong`, expected one of `debuginfo`, `none`, `symbols` for key [..]
",
        )
        .run();
}
<|endoftext|>


<commit_before>//! Module for kernels
//!
//! Currently used within Gaussian Processes and SVMs.

use linalg::vector::Vector;
use linalg::utils;
use linalg::Metric;

use libnum::Float;

/// The Kernel trait
///
/// Requires a function mapping two vectors to a scalar.
pub trait Kernel {
    /// The kernel function.
    ///
    /// Takes two equal length slices and returns a scalar.
    fn kernel(&self, x1: &[f64], x2: &[f64]) -> f64;
}

/// The Linear Kernel
///
/// k(x,y) = xTy + c
pub struct Linear {
    /// Constant term added to inner product.
    pub c: f64,
}

impl Linear {
    /// Constructs a new Linear Kernel.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::learning::toolkit::kernel;
    /// use rusty_machine::learning::toolkit::kernel::Kernel;
    ///
    /// let ker = kernel::Linear::new(5.0);
    ///
    /// println!("{0}", ker.kernel(&[1.,2.,3.], &[3.,4.,5.]));
    /// ```
    pub fn new(c: f64) -> Linear {
        Linear {
            c : c,
        }
    }
}

/// Constructs the default Linear Kernel
///
/// The defaults are:
///
/// - c = 0
impl Default for Linear {
    fn default() -> Linear {
        Linear {
            c: 0f64,
        }
    }
}

impl Kernel for Linear {
    fn kernel(&self, x1: &[f64], x2: &[f64]) -> f64 {
        utils::dot(x1, x2) + self.c
    }
}

/// The Polynomial Kernel
///
/// k(x,y) = (αxTy + c)d
pub struct Polynomial {
    /// Scaling of the inner product.
    pub alpha: f64,
    /// Constant added to inner product.
    pub c: f64,
    /// The power to raise the sum to.
    pub d: f64,
}

impl Polynomial {

    /// Constructs a new Polynomial Kernel.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::learning::toolkit::kernel;
    /// use rusty_machine::learning::toolkit::kernel::Kernel;
    ///
    /// // Constructs a new polynomial with alpha = 1, c = 0, d = 2.
    /// let ker = kernel::Polynomial::new(1.0, 0.0, 2.0);
    ///
    /// println!("{0}", ker.kernel(&[1.,2.,3.], &[3.,4.,5.]));
    /// ```
    pub fn new(alpha: f64, c: f64, d: f64) -> Polynomial {
        Polynomial {
            alpha: alpha,
            c : c,
            d: d,
        }
    }
}

/// Construct a new polynomial kernel.
///
/// The defaults are:
///
/// - alpha = 1
/// - c = 0
/// - d = 1
impl Default for Polynomial {
    fn default() -> Polynomial {
        Polynomial {
            alpha: 1f64,
            c: 0f64,
            d: 1f64,
        }
    }
}

impl Kernel for Polynomial {
    fn kernel(&self, x1: &[f64], x2: &[f64]) -> f64 {
        (self.alpha * utils::dot(x1, x2) + self.c).powf(self.d)
    }
}

/// Squared exponential kernel
///
/// Equivalently a gaussian function.
///
/// k(x,y) = A _exp_(-||x-y||2 / 2l2)
///
/// Where A is the amplitude and l the length scale.
pub struct SquaredExp {
    /// The length scale of the kernel.
    pub ls: f64,
    /// The amplitude of the kernel.
    pub ampl: f64,
}

impl SquaredExp {
    /// Construct a new squared exponential kernel.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::learning::toolkit::kernel;
    /// use rusty_machine::learning::toolkit::kernel::Kernel;
    ///
    /// // Construct a kernel with lengthscale 2 and amplitude 1.
    /// let ker = kernel::SquaredExp::new(2f64, 1f64);
    ///
    /// println!("{0}", ker.kernel(&[1.,2.,3.], &[3.,4.,5.]));
    /// ```
    pub fn new(ls: f64, ampl: f64) -> SquaredExp {
        SquaredExp {
            ls: ls,
            ampl: ampl,
        }
    }
}

/// Constructs the default Squared Exp kernel.
///
/// The defaults are:
///
/// - ls = 1
/// - ampl = 1
impl Default for SquaredExp {
    fn default() -> SquaredExp {
        SquaredExp {
            ls: 1f64,
            ampl: 1f64,
        }
    }
}

impl Kernel for SquaredExp {
    /// The squared exponential kernel function.
    fn kernel(&self, x1: &[f64], x2: &[f64]) -> f64 {
        assert_eq!(x1.len(), x2.len());

        let diff = Vector::new(x1.to_vec()) - Vector::new(x2.to_vec());

        let x = -diff.dot(&diff) / (2f64 * self.ls * self.ls);
        (self.ampl * x.exp())
    }
}

/// The Exponential Kernel
///
/// k(x,y) = A _exp_(-||x-y|| / 2l2)
///
/// Where A is the amplitude and l is the length scale.
pub struct Exponential {
    /// The length scale of the kernel.
    pub ls: f64,
    /// The amplitude of the kernel.
    pub ampl: f64,
}

impl Exponential {
    /// Construct a new squared exponential kernel.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::learning::toolkit::kernel;
    /// use rusty_machine::learning::toolkit::kernel::Kernel;
    ///
    /// // Construct a kernel with lengthscale 2 and amplitude 1.
    /// let ker = kernel::Exponential::new(2f64, 1f64);
    ///
    /// println!("{0}", ker.kernel(&[1.,2.,3.], &[3.,4.,5.]));
    /// ```
    pub fn new(ls: f64, ampl: f64) -> Exponential {
        Exponential {
            ls: ls,
            ampl: ampl,
        }
    }
}

/// Constructs the default Exponential kernel.
///
/// The defaults are:
///
/// - ls = 1
/// - amplitude = 1
impl Default for Exponential {

    fn default() -> Exponential {
        Exponential {
            ls: 1f64,
            ampl: 1f64,
        }
    }
}

impl Kernel for Exponential {
    /// The squared exponential kernel function.
    fn kernel(&self, x1: &[f64], x2: &[f64]) -> f64 {
        assert_eq!(x1.len(), x2.len());

        let diff = Vector::new(x1.to_vec()) - Vector::new(x2.to_vec());

        let x = -diff.norm() / (2f64 * self.ls * self.ls);
        (self.ampl * x.exp())
    }
}

/// The Hyperbolic Tangent Kernel.
///
/// ker(x,y) = _tanh_(αxTy + c)
pub struct HyperTan {
    /// The scaling of the inner product.
    pub alpha: f64,
    /// The constant to add to the inner product.
    pub c: f64,
}

impl HyperTan {

    /// Constructs a new Hyperbolic Tangent Kernel.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::learning::toolkit::kernel;
    /// use rusty_machine::learning::toolkit::kernel::Kernel;
    ///
    /// // Construct a kernel with alpha = 1, c = 2.
    /// let ker = kernel::HyperTan::new(1.0, 2.0);
    ///
    /// println!("{0}", ker.kernel(&[1.,2.,3.], &[3.,4.,5.]));
    /// ```
    pub fn new(alpha: f64, c: f64) -> HyperTan {
        HyperTan {
            alpha: alpha,
            c : c,
        }
    }
}

/// Constructs a default Hyperbolic Tangent Kernel.
///
/// The defaults are:
///
/// - alpha = 1
/// - c = 0
impl Default for HyperTan {
    fn default() -> HyperTan {
        HyperTan {
            alpha: 1f64,
            c: 0f64,
        }
    }
}

impl Kernel for HyperTan {
    fn kernel(&self, x1: &[f64], x2: &[f64]) -> f64 {
        (self.alpha * utils::dot(x1, x2) + self.c).tanh()
    }
}

/// The Multiquadric Kernel.
///
/// k(x,y) = _sqrt_(||x-y||2 + c2)
pub struct Multiquadric {
    /// Constant added to square of difference.
    pub c: f64,
}

impl Multiquadric {

    /// Constructs a new Multiquadric Kernel.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::learning::toolkit::kernel;
    /// use rusty_machine::learning::toolkit::kernel::Kernel;
    ///
    /// // Construct a kernel with c = 2.
    /// let ker = kernel::Multiquadric::new(2.0);
    ///
    /// println!("{0}", ker.kernel(&[1.,2.,3.], &[3.,4.,5.]));
    /// ```
    pub fn new(c: f64) -> Multiquadric {
        Multiquadric {
            c : c,
        }
    }
}

/// Constructs a default Multiquadric Kernel.
///
/// The defaults are:
///
/// - c = 0
impl Default for Multiquadric {
    fn default() -> Multiquadric {
        Multiquadric {
            c: 0f64,
        }
    }
}

impl Kernel for Multiquadric {
    fn kernel(&self, x1: &[f64], x2: &[f64]) -> f64 {
        assert_eq!(x1.len(), x2.len());

        let diff = Vector::new(x1.to_vec()) - Vector::new(x2.to_vec());

        diff.norm().hypot(self.c)
    }
}

/// The Rational Quadratic Kernel.
///
/// k(x,y) = (1 + ||x-y||2 / (2αl2))-α
pub struct RationalQuadratic {
    /// Controls inverse power and difference scale.
    pub alpha: f64,
    /// Length scale controls scale of difference.
    pub ls: f64,
}

impl RationalQuadratic {

    /// Constructs a new Rational Quadratic Kernel.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::learning::toolkit::kernel;
    /// use rusty_machine::learning::toolkit::kernel::Kernel;
    ///
    /// // Construct a kernel with alpha = 2, ls = 2.
    /// let ker = kernel::RationalQuadratic::new(2.0, 2.0);
    ///
    /// println!("{0}", ker.kernel(&[1.,2.,3.], &[3.,4.,5.]));
    /// ```
    pub fn new(alpha: f64, ls: f64) -> RationalQuadratic {
        RationalQuadratic {
            alpha: alpha,
            ls: ls,
        }
    }
}

/// The default Rational Qaudratic Kernel.
///
/// The defaults are:
///
/// - alpha = 1
/// - ls = 1
impl Default for RationalQuadratic {
    fn default() -> RationalQuadratic {
        RationalQuadratic {
            alpha: 1f64,
            ls: 1f64,
        }
    }
}

impl Kernel for RationalQuadratic {
    fn kernel(&self, x1: &[f64], x2: &[f64]) -> f64 {
        let diff = Vector::new(x1.to_vec()) - Vector::new(x2.to_vec());

        (1f64 + diff.dot(&diff) / (2f64 * self.alpha * self.ls * self.ls)).powf(-self.alpha)
    }
}<commit_msg>Adding basic kenrel arithmetic<commit_after>//! Module for kernels
//!
//! Currently used within Gaussian Processes and SVMs.

use std::ops::{Add, Mul};

use linalg::vector::Vector;
use linalg::utils;
use linalg::Metric;

use libnum::Float;

/// The Kernel trait
///
/// Requires a function mapping two vectors to a scalar.
pub trait Kernel {
    /// The kernel function.
    ///
    /// Takes two equal length slices and returns a scalar.
    fn kernel(&self, x1: &[f64], x2: &[f64]) -> f64;
}

/// The sum of two kernels
///
/// This struct should not be directly instantiated but instead
/// is created when we add two kernels together.
///
/// Note that it will be more efficient to implement the final kernel
/// manually yourself. However this provides an easy mechanism to test
/// different combinations.
///
/// # Examples
///
/// ```
/// use rusty_machine::learning::toolkit::kernel::{Kernel, Polynomial, HyperTan, KernelArith};
///
/// let poly_ker = Polynomial::new(1f64,2f64,3f64);
/// let hypert_ker = HyperTan::new(1f64,2.5);
///
/// let poly_plus_hypert_ker = KernelArith(poly_ker) + KernelArith(hypert_ker);
///
/// println!("{0}", poly_plus_hypert_ker.kernel(&[1f64,2f64,3f64],
///                                             &[3f64,1f64,2f64]));
/// ```
pub struct KernelSum<T, U>
    where T: Kernel,
          U: Kernel
{
    k1: T,
    k2: U,
}

/// Computes the sum of the two associated kernels.
impl<T, U> Kernel for KernelSum<T, U>
    where T: Kernel,
          U: Kernel
{
    fn kernel(&self, x1: &[f64], x2: &[f64]) -> f64 {
        self.k1.kernel(x1, x2) + self.k2.kernel(x1, x2)
    }
}

/// The pointwise product of two kernels
///
/// This struct should not be directly instantiated but instead
/// is created when we multiply two kernels together.
///
/// Note that it will be more efficient to implement the final kernel
/// manually yourself. However this provides an easy mechanism to test
/// different combinations.
///
/// # Examples
///
/// ```
/// use rusty_machine::learning::toolkit::kernel::{Kernel, Polynomial, HyperTan, KernelArith};
///
/// let poly_ker = Polynomial::new(1f64,2f64,3f64);
/// let hypert_ker = HyperTan::new(1f64,2.5);
///
/// let poly_plus_hypert_ker = KernelArith(poly_ker) * KernelArith(hypert_ker);
///
/// println!("{0}", poly_plus_hypert_ker.kernel(&[1f64,2f64,3f64],
///                                             &[3f64,1f64,2f64]));
/// ```
pub struct KernelProd<T, U>
    where T: Kernel,
          U: Kernel
{
    k1: T,
    k2: U,
}

/// Computes the product of the two associated kernels.
impl<T, U> Kernel for KernelProd<T, U>
    where T: Kernel,
          U: Kernel
{
    fn kernel(&self, x1: &[f64], x2: &[f64]) -> f64 {
        self.k1.kernel(x1, x2) * self.k2.kernel(x1, x2)
    }
}

/// A wrapper tuple struct used for kernel arithmetic
pub struct KernelArith<K: Kernel>(pub K);

impl<T: Kernel, U: Kernel> Add<KernelArith<T>> for KernelArith {
    type Output = KernelSum;

    fn add(self, ker: KernelArith<T>) -> KernelSum {
        KernelSum {
            k1: self.0,
            k2: ker.0,
        }
    }
}

impl<T: Kernel, U: Kernel> Mul<KernelArith<T>> for KernelArith {
    type Output = KernelProd;

    fn mul(self, ker: KernelArith<T>) -> KernelProd {
        KernelProd {
            k1: self.0,
            k2: ker.0,
        }
    }
}

/// The Linear Kernel
///
/// k(x,y) = xTy + c
pub struct Linear {
    /// Constant term added to inner product.
    pub c: f64,
}

impl Linear {
    /// Constructs a new Linear Kernel.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::learning::toolkit::kernel;
    /// use rusty_machine::learning::toolkit::kernel::Kernel;
    ///
    /// let ker = kernel::Linear::new(5.0);
    ///
    /// println!("{0}", ker.kernel(&[1.,2.,3.], &[3.,4.,5.]));
    /// ```
    pub fn new(c: f64) -> Linear {
        Linear { c: c }
    }
}

/// Constructs the default Linear Kernel
///
/// The defaults are:
///
/// - c = 0
impl Default for Linear {
    fn default() -> Linear {
        Linear { c: 0f64 }
    }
}

impl Kernel for Linear {
    fn kernel(&self, x1: &[f64], x2: &[f64]) -> f64 {
        utils::dot(x1, x2) + self.c
    }
}

/// The Polynomial Kernel
///
/// k(x,y) = (αxTy + c)d
pub struct Polynomial {
    /// Scaling of the inner product.
    pub alpha: f64,
    /// Constant added to inner product.
    pub c: f64,
    /// The power to raise the sum to.
    pub d: f64,
}

impl Polynomial {
    /// Constructs a new Polynomial Kernel.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::learning::toolkit::kernel;
    /// use rusty_machine::learning::toolkit::kernel::Kernel;
    ///
    /// // Constructs a new polynomial with alpha = 1, c = 0, d = 2.
    /// let ker = kernel::Polynomial::new(1.0, 0.0, 2.0);
    ///
    /// println!("{0}", ker.kernel(&[1.,2.,3.], &[3.,4.,5.]));
    /// ```
    pub fn new(alpha: f64, c: f64, d: f64) -> Polynomial {
        Polynomial {
            alpha: alpha,
            c: c,
            d: d,
        }
    }
}

/// Construct a new polynomial kernel.
///
/// The defaults are:
///
/// - alpha = 1
/// - c = 0
/// - d = 1
impl Default for Polynomial {
    fn default() -> Polynomial {
        Polynomial {
            alpha: 1f64,
            c: 0f64,
            d: 1f64,
        }
    }
}

impl Kernel for Polynomial {
    fn kernel(&self, x1: &[f64], x2: &[f64]) -> f64 {
        (self.alpha * utils::dot(x1, x2) + self.c).powf(self.d)
    }
}

/// Squared exponential kernel
///
/// Equivalently a gaussian function.
///
/// k(x,y) = A _exp_(-||x-y||2 / 2l2)
///
/// Where A is the amplitude and l the length scale.
pub struct SquaredExp {
    /// The length scale of the kernel.
    pub ls: f64,
    /// The amplitude of the kernel.
    pub ampl: f64,
}

impl SquaredExp {
    /// Construct a new squared exponential kernel.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::learning::toolkit::kernel;
    /// use rusty_machine::learning::toolkit::kernel::Kernel;
    ///
    /// // Construct a kernel with lengthscale 2 and amplitude 1.
    /// let ker = kernel::SquaredExp::new(2f64, 1f64);
    ///
    /// println!("{0}", ker.kernel(&[1.,2.,3.], &[3.,4.,5.]));
    /// ```
    pub fn new(ls: f64, ampl: f64) -> SquaredExp {
        SquaredExp {
            ls: ls,
            ampl: ampl,
        }
    }
}

/// Constructs the default Squared Exp kernel.
///
/// The defaults are:
///
/// - ls = 1
/// - ampl = 1
impl Default for SquaredExp {
    fn default() -> SquaredExp {
        SquaredExp {
            ls: 1f64,
            ampl: 1f64,
        }
    }
}

impl Kernel for SquaredExp {
    /// The squared exponential kernel function.
    fn kernel(&self, x1: &[f64], x2: &[f64]) -> f64 {
        assert_eq!(x1.len(), x2.len());

        let diff = Vector::new(x1.to_vec()) - Vector::new(x2.to_vec());

        let x = -diff.dot(&diff) / (2f64 * self.ls * self.ls);
        (self.ampl * x.exp())
    }
}

/// The Exponential Kernel
///
/// k(x,y) = A _exp_(-||x-y|| / 2l2)
///
/// Where A is the amplitude and l is the length scale.
pub struct Exponential {
    /// The length scale of the kernel.
    pub ls: f64,
    /// The amplitude of the kernel.
    pub ampl: f64,
}

impl Exponential {
    /// Construct a new squared exponential kernel.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::learning::toolkit::kernel;
    /// use rusty_machine::learning::toolkit::kernel::Kernel;
    ///
    /// // Construct a kernel with lengthscale 2 and amplitude 1.
    /// let ker = kernel::Exponential::new(2f64, 1f64);
    ///
    /// println!("{0}", ker.kernel(&[1.,2.,3.], &[3.,4.,5.]));
    /// ```
    pub fn new(ls: f64, ampl: f64) -> Exponential {
        Exponential {
            ls: ls,
            ampl: ampl,
        }
    }
}

/// Constructs the default Exponential kernel.
///
/// The defaults are:
///
/// - ls = 1
/// - amplitude = 1
impl Default for Exponential {
    fn default() -> Exponential {
        Exponential {
            ls: 1f64,
            ampl: 1f64,
        }
    }
}

impl Kernel for Exponential {
    /// The squared exponential kernel function.
    fn kernel(&self, x1: &[f64], x2: &[f64]) -> f64 {
        assert_eq!(x1.len(), x2.len());

        let diff = Vector::new(x1.to_vec()) - Vector::new(x2.to_vec());

        let x = -diff.norm() / (2f64 * self.ls * self.ls);
        (self.ampl * x.exp())
    }
}

/// The Hyperbolic Tangent Kernel.
///
/// ker(x,y) = _tanh_(αxTy + c)
pub struct HyperTan {
    /// The scaling of the inner product.
    pub alpha: f64,
    /// The constant to add to the inner product.
    pub c: f64,
}

impl HyperTan {
    /// Constructs a new Hyperbolic Tangent Kernel.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::learning::toolkit::kernel;
    /// use rusty_machine::learning::toolkit::kernel::Kernel;
    ///
    /// // Construct a kernel with alpha = 1, c = 2.
    /// let ker = kernel::HyperTan::new(1.0, 2.0);
    ///
    /// println!("{0}", ker.kernel(&[1.,2.,3.], &[3.,4.,5.]));
    /// ```
    pub fn new(alpha: f64, c: f64) -> HyperTan {
        HyperTan {
            alpha: alpha,
            c: c,
        }
    }
}

/// Constructs a default Hyperbolic Tangent Kernel.
///
/// The defaults are:
///
/// - alpha = 1
/// - c = 0
impl Default for HyperTan {
    fn default() -> HyperTan {
        HyperTan {
            alpha: 1f64,
            c: 0f64,
        }
    }
}

impl Kernel for HyperTan {
    fn kernel(&self, x1: &[f64], x2: &[f64]) -> f64 {
        (self.alpha * utils::dot(x1, x2) + self.c).tanh()
    }
}

/// The Multiquadric Kernel.
///
/// k(x,y) = _sqrt_(||x-y||2 + c2)
pub struct Multiquadric {
    /// Constant added to square of difference.
    pub c: f64,
}

impl Multiquadric {
    /// Constructs a new Multiquadric Kernel.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::learning::toolkit::kernel;
    /// use rusty_machine::learning::toolkit::kernel::Kernel;
    ///
    /// // Construct a kernel with c = 2.
    /// let ker = kernel::Multiquadric::new(2.0);
    ///
    /// println!("{0}", ker.kernel(&[1.,2.,3.], &[3.,4.,5.]));
    /// ```
    pub fn new(c: f64) -> Multiquadric {
        Multiquadric { c: c }
    }
}

/// Constructs a default Multiquadric Kernel.
///
/// The defaults are:
///
/// - c = 0
impl Default for Multiquadric {
    fn default() -> Multiquadric {
        Multiquadric { c: 0f64 }
    }
}

impl Kernel for Multiquadric {
    fn kernel(&self, x1: &[f64], x2: &[f64]) -> f64 {
        assert_eq!(x1.len(), x2.len());

        let diff = Vector::new(x1.to_vec()) - Vector::new(x2.to_vec());

        diff.norm().hypot(self.c)
    }
}

/// The Rational Quadratic Kernel.
///
/// k(x,y) = (1 + ||x-y||2 / (2αl2))-α
pub struct RationalQuadratic {
    /// Controls inverse power and difference scale.
    pub alpha: f64,
    /// Length scale controls scale of difference.
    pub ls: f64,
}

impl RationalQuadratic {
    /// Constructs a new Rational Quadratic Kernel.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::learning::toolkit::kernel;
    /// use rusty_machine::learning::toolkit::kernel::Kernel;
    ///
    /// // Construct a kernel with alpha = 2, ls = 2.
    /// let ker = kernel::RationalQuadratic::new(2.0, 2.0);
    ///
    /// println!("{0}", ker.kernel(&[1.,2.,3.], &[3.,4.,5.]));
    /// ```
    pub fn new(alpha: f64, ls: f64) -> RationalQuadratic {
        RationalQuadratic {
            alpha: alpha,
            ls: ls,
        }
    }
}

/// The default Rational Qaudratic Kernel.
///
/// The defaults are:
///
/// - alpha = 1
/// - ls = 1
impl Default for RationalQuadratic {
    fn default() -> RationalQuadratic {
        RationalQuadratic {
            alpha: 1f64,
            ls: 1f64,
        }
    }
}

impl Kernel for RationalQuadratic {
    fn kernel(&self, x1: &[f64], x2: &[f64]) -> f64 {
        let diff = Vector::new(x1.to_vec()) - Vector::new(x2.to_vec());

        (1f64 + diff.dot(&diff) / (2f64 * self.alpha * self.ls * self.ls)).powf(-self.alpha)
    }
}
<|endoftext|>


<commit_before>/*!
Library for reading/writing Labeled Tab-Separated Values

# Example

~~~~~~~~~~~~~~~~~~~~~~
extern mod ltsv;
use ltsv::LTSVWriter;
use ltsv::LTSVReader;

fn main() {
    let infile = io::file_reader(&Path("path/fo/file.tlsv")).get();
    for infile.read_ltsv().each |record| {
        for record.each |&(label, value)| {
            io::println(fmt!("%s: %s", *label, *value));
        }
    }
}
~~~~~~~~~~~~~~~~~~~~~~
*/
#[link(name = "ltsv",
       vers = "0.2",
       uuid = "E0EA0251-E165-4612-919F-38E89ACECBE9",
       url  = "https://github.com/tychosci/rust-ltsv/")];

#[comment = "Library for reading/writing Labeled Tab-Separated Values"];
#[license = "MIT license"];
#[crate_type = "lib"];

use core::container::Map;
use core::hashmap::linear::LinearMap;
use io::WriterUtil;

pub type Record = LinearMap<~str, ~str>;

enum ParseType {
    FieldLabel,
    FieldValue,
    Field,
    Record,
    Ltsv
}

enum ParseResult<T> {
    ParseError(~str),
    ParseOk(ParseType, T)
}

pub trait LTSVWriter {
    fn write_ltsv(&self, ltsv: &[Record]);
    fn write_ltsv_record(&self, record: &Record);
}

pub trait LTSVReader {
    fn read_ltsv(&self) -> ~[Record];
    fn each_ltsv_record(&self, f: &fn(&Record) -> bool);
    fn each_ltsv_field(&self, f: &fn(&(~str, ~str)) -> bool);
}

pub impl<T: io::Writer> LTSVWriter for T {
    fn write_ltsv(&self, ltsv: &[Record]) {
        for ltsv.each |record| {
            self.write_ltsv_record(record);
            self.write_char('\n');
        }
    }
    fn write_ltsv_record(&self, record: &Record) {
        let mut is_first = true;
        for record.each |&(k, v)| {
            if !is_first { self.write_char('\t'); }
            self.write_str(fmt!("%s:%s", *k, *v));
            if is_first { is_first = false; }
        }
    }
}

pub impl<T: io::Reader> LTSVReader for T {
    fn read_ltsv(&self) -> ~[Record] {
        let mut parser = LTSVParser::new(self);
        match parser.parse_ltsv() {
            ParseOk(_, records) => records,
            ParseError(reason) => die!(reason)
        }
    }
    fn each_ltsv_record(&self, f: &fn(&Record) -> bool) {
        let mut parser = LTSVParser::new(self);
        while !parser.eof() { // FIXME: This emits odd loaning errors.
            match parser.parse_record() {
                ParseOk(_, record) => if !f(&record) { break; },
                ParseError(reason) => die!(reason)
            }
        }
    }
    fn each_ltsv_field(&self, f: &fn(&(~str, ~str)) -> bool) {
        let mut parser = LTSVParser::new(self);
        while !parser.eof() { // FIXME: This emits odd loaning errors.
            match parser.parse_field() {
                ParseOk(_, field)  => if !f(&field) { break; },
                ParseError(reason) => die!(reason)
            }
            parser.bump();
        }
    }
}

struct LTSVParser<T> {
    priv rd: &T,
    priv cur: int
}

impl<T: io::Reader> LTSVParser<T> {
    static fn new(rd: &r/T) -> LTSVParser/&r<T> {
        let cur = rd.read_byte();
        LTSVParser { rd: rd, cur: cur }
    }

    fn eof(&self) -> bool { self.cur == -1 }

    fn bump(&mut self) {
        if !self.eof() {
            self.cur = self.rd.read_byte();
        }
    }

    fn parse_ltsv(&mut self) -> ParseResult<~[Record]> {
        let mut records = ~[];
        loop {
            match self.parse_record() {
                ParseOk(_, record) => {
                    records.push(record);
                    if self.eof() { break; }
                }
                ParseError(reason) => {
                    return ParseError(reason);
                }
            }
        }
        ParseOk(Ltsv, records)
    }

    fn parse_record(&mut self) -> ParseResult<Record> {
        let mut record = LinearMap::new();
        self.skip_whitespaces();
        loop {
            match self.parse_field() {
                ParseOk(_, (label, value)) => {
                    let saved_cur = self.cur;
                    self.bump();
                    record.insert(label, value);
                    if saved_cur == 0xa || saved_cur == -1 {
                        self.skip_whitespaces();
                        return ParseOk(Record, record);
                    }
                }
                ParseError(reason) => {
                    return ParseError(reason);
                }
            }
        }
    }

    fn parse_field(&mut self) -> ParseResult<(~str, ~str)> {
        let label = match self.parse_field_label() {
            ParseOk(_, label)  => { self.bump(); label },
            ParseError(reason) => return ParseError(reason)
        };
        match self.parse_field_value() {
            ParseOk(_, value) => {
                ParseOk(Field, (label, value))
            }
            ParseError(reason) => {
                ParseError(reason)
            }
        }
    }

    fn parse_field_label(&mut self) -> ParseResult<~str> {
        let mut bytes = ~[];
        loop {
            match self.cur {
                0x30..0x39 | 0x41..0x5a | 0x61..0x7a | 0x5f |
                0x2e | 0x2d => bytes.push(self.cur as u8),
                0x3a if bytes.len() == 0 => return ParseError(~"label is empty"),
                0x3a => return ParseOk(FieldLabel, str::from_bytes(bytes)),
                -1   => return ParseError(~"EOF while parsing field label"),
                _    => return ParseError(~"invalid byte detected")
            }
            self.bump();
        }
    }

    fn parse_field_value(&mut self) -> ParseResult<~str> {
        let mut bytes = ~[];
        loop {
            match self.cur {
                0x01..0x08 | 0x0b | 0x0c |
                0x0e..0xff => bytes.push(self.cur as u8),
                0x0d => return self.consume_forward_LF(str::from_bytes(bytes)),
                0x0a => return ParseOk(FieldValue, str::from_bytes(bytes)),
                0x09 => return ParseOk(FieldValue, str::from_bytes(bytes)),
                -1   => return ParseOk(FieldValue, str::from_bytes(bytes)),
                _    => return ParseError(~"invalid byte detected")
            }
            self.bump();
        }
    }

    fn consume_forward_LF(&mut self, rv: ~str) -> ParseResult<~str> {
        self.bump();
        if self.cur != 0x0a {
            ParseError(~"CR detected, but not provided with LF")
        } else {
            ParseOk(FieldValue, rv)
        }
    }

    fn skip_whitespaces(&mut self) {
        while char::is_whitespace(self.cur as char) {
            self.bump();
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use core::io::WriterUtil;

    #[test]
    fn test_parse_simple() {
        let records = io::with_str_reader(~"a:1\tb:2", |rd| rd.read_ltsv());
        assert records.len() == 1;
    }

    #[test]
    fn test_parse_full() {
        let s = io::with_str_writer(|wr| {
            // genzairyou
            wr.write_str(fmt!("%s:%s\t", "tofu", "豆"));
            wr.write_str(fmt!("%s:%s\t", "kamaboko", "魚"));
            wr.write_str(fmt!("%s:%s\n", "sukonbu", "海藻"));
            // konomi
            wr.write_str(fmt!("%s:%s\t", "tofu", "好き"));
            wr.write_str(fmt!("%s:%s\t", "kamaboko", "普通"));
            wr.write_str(fmt!("%s:%s\n", "sukonbu", "苦手"));
        });
        let records = io::with_str_reader(s, |rd| rd.read_ltsv());
        assert records.len() == 2;
    }

    #[test]
    fn test_parse_ltsv_trailing_nl_and_write() {
        let s = io::with_str_writer(|wr| {
            wr.write_str(fmt!("%s:%s\t", "neko", "yes"));
            wr.write_str(fmt!("%s:%s\t", "inu", "yes"));
            wr.write_str(fmt!("%s:%s\n", "tori", "yes"));
        });
        let records_1 = io::with_str_reader(s, |rd| rd.read_ltsv());
        let s2 = io::with_str_writer(|wr| wr.write_ltsv(records_1));
        let records_2 = io::with_str_reader(s2, |rd| rd.read_ltsv());
        assert records_1 == records_2;
    }
}
<commit_msg>Cleanup and refactoring<commit_after>/*!
Library for reading/writing Labeled Tab-Separated Values

# Example

~~~~~~~~~~~~~~~~~~~~~~
extern mod ltsv;
use ltsv::LTSVWriter;
use ltsv::LTSVReader;

fn main() {
    let infile = io::file_reader(&Path("path/fo/file.tlsv")).get();
    for infile.read_ltsv().each |record| {
        for record.each |&(label, value)| {
            io::println(fmt!("%s: %s", *label, *value));
        }
    }
}
~~~~~~~~~~~~~~~~~~~~~~
*/
#[link(name = "ltsv",
       vers = "0.2",
       uuid = "E0EA0251-E165-4612-919F-38E89ACECBE9",
       url  = "https://github.com/tychosci/rust-ltsv/")];

#[comment = "Library for reading/writing Labeled Tab-Separated Values"];
#[license = "MIT license"];
#[crate_type = "lib"];

use core::container::Map;
use core::hashmap::linear::LinearMap;
use io::WriterUtil;

pub type Record = LinearMap<~str, ~str>;

enum ParseType {
    FieldLabel,
    FieldValue,
    Field,
    Record,
    Ltsv
}

enum ParseDelimiter {
    EOF, TAB, NL, MISC
}

enum ParseResult<T> {
    ParseError(~str),
    ParseOk(ParseType, ParseDelimiter, T)
}

pub trait LTSVWriter {
    fn write_ltsv(&self, ltsv: &[Record]);
    fn write_ltsv_record(&self, record: &Record);
}

pub trait LTSVReader {
    fn read_ltsv(&self) -> ~[Record];
    fn each_ltsv_record(&self, f: &fn(&Record) -> bool);
    fn each_ltsv_field(&self, f: &fn(&(~str, ~str)) -> bool);
}

pub impl<T: io::Writer> LTSVWriter for T {
    fn write_ltsv(&self, ltsv: &[Record]) {
        for ltsv.each |record| {
            self.write_ltsv_record(record);
            self.write_char('\n');
        }
    }
    fn write_ltsv_record(&self, record: &Record) {
        let mut is_first = true;
        for record.each |&(k, v)| {
            if !is_first { self.write_char('\t'); }
            self.write_str(fmt!("%s:%s", *k, *v));
            if is_first { is_first = false; }
        }
    }
}

pub impl<T: io::Reader> LTSVReader for T {
    fn read_ltsv(&self) -> ~[Record] {
        let mut parser = LTSVParser::new(self);
        match parser.parse_ltsv() {
            ParseError(reason) => die!(reason),
            ParseOk(_, _, records) => records
        }
    }
    fn each_ltsv_record(&self, f: &fn(&Record) -> bool) {
        let mut parser = LTSVParser::new(self);
        while !parser.eof() { // FIXME: This emits odd loaning errors.
            match parser.parse_record() {
                ParseError(reason) => die!(reason),
                ParseOk(_, _, record) => if !f(&record) { break; }
            }
        }
    }
    fn each_ltsv_field(&self, f: &fn(&(~str, ~str)) -> bool) {
        let mut parser = LTSVParser::new(self);
        while !parser.eof() { // FIXME: This emits odd loaning errors.
            match parser.parse_field() {
                ParseError(reason) => die!(reason),
                ParseOk(_, _, field) => if !f(&field) { break; }
            }
        }
    }
}

struct LTSVParser<T> {
    priv rd: &T,
    priv cur: int
}

impl<T: io::Reader> LTSVParser<T> {
    static fn new(rd: &r/T) -> LTSVParser/&r<T> {
        let cur = rd.read_byte();
        LTSVParser { rd: rd, cur: cur }
    }

    fn eof(&self) -> bool { self.cur == -1 }

    fn bump(&mut self) {
        if !self.eof() {
            self.cur = self.rd.read_byte();
        }
    }

    fn parse_ltsv(&mut self) -> ParseResult<~[Record]> {
        let mut records = ~[];
        loop {
            match self.parse_record() {
                ParseError(reason) => {
                    return ParseError(reason);
                }
                ParseOk(_, EOF, record) => {
                    records.push(record);
                    break;
                }
                ParseOk(_, _, record) => {
                    records.push(record);
                }
            }
        }
        ParseOk(Ltsv, EOF, records)
    }

    fn parse_record(&mut self) -> ParseResult<Record> {
        let mut record = LinearMap::new();
        self.skip_whitespaces();
        loop {
            match self.parse_field() {
                ParseError(reason) => {
                    return ParseError(reason);
                }
                ParseOk(_, TAB, (label, value)) => {
                    record.insert(label, value);
                }
                ParseOk(_, delim, (label, value)) => {
                    record.insert(label, value);
                    return ParseOk(Record, delim, record);
                }
            }
        }
    }

    fn parse_field(&mut self) -> ParseResult<(~str, ~str)> {
        let label = match self.parse_field_label() {
            ParseError(reason) => return ParseError(reason),
            ParseOk(_, _, label) => { self.bump(); label }
        };
        match self.parse_field_value() {
            ParseError(reason) => {
                ParseError(reason)
            }
            ParseOk(_, delim, value) => {
                self.bump();
                ParseOk(Field, delim, (label, value))
            }
        }
    }

    fn parse_field_label(&mut self) -> ParseResult<~str> {
        let mut bytes = ~[];
        loop {
            match self.cur {
                0x30..0x39 | 0x41..0x5a | 0x61..0x7a | 0x5f |
                0x2e | 0x2d => bytes.push(self.cur as u8),
                0x3a if bytes.len() == 0 => return ParseError(~"label is empty"),
                0x3a => return ParseOk(FieldLabel, MISC, str::from_bytes(bytes)),
                -1   => return ParseError(~"EOF while parsing field label"),
                _    => return ParseError(~"invalid byte detected")
            }
            self.bump();
        }
    }

    fn parse_field_value(&mut self) -> ParseResult<~str> {
        let mut bytes = ~[];
        loop {
            match self.cur {
                0x01..0x08 | 0x0b | 0x0c |
                0x0e..0xff => bytes.push(self.cur as u8),
                0x0d => return self.consume_forward_LF(str::from_bytes(bytes)),
                0x0a => return ParseOk(FieldValue, NL, str::from_bytes(bytes)),
                0x09 => return ParseOk(FieldValue, TAB, str::from_bytes(bytes)),
                -1   => return ParseOk(FieldValue, EOF, str::from_bytes(bytes)),
                _    => return ParseError(~"invalid byte detected")
            }
            self.bump();
        }
    }

    fn consume_forward_LF(&mut self, rv: ~str) -> ParseResult<~str> {
        self.bump();
        if self.cur != 0x0a {
            ParseError(~"CR detected, but not provided with LF")
        } else {
            ParseOk(FieldValue, NL, rv)
        }
    }

    fn skip_whitespaces(&mut self) {
        while char::is_whitespace(self.cur as char) {
            self.bump();
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use core::io::WriterUtil;

    #[test]
    fn test_parse_simple() {
        let records = io::with_str_reader(~"a:1\tb:2", |rd| rd.read_ltsv());
        assert records.len() == 1;
    }

    #[test]
    fn test_parse_full() {
        let s = io::with_str_writer(|wr| {
            // genzairyou
            wr.write_str(fmt!("%s:%s\t", "tofu", "豆"));
            wr.write_str(fmt!("%s:%s\t", "kamaboko", "魚"));
            wr.write_str(fmt!("%s:%s\n", "sukonbu", "海藻"));
            // konomi
            wr.write_str(fmt!("%s:%s\t", "tofu", "好き"));
            wr.write_str(fmt!("%s:%s\t", "kamaboko", "普通"));
            wr.write_str(fmt!("%s:%s\n", "sukonbu", "苦手"));
        });
        let records = io::with_str_reader(s, |rd| rd.read_ltsv());
        assert records.len() == 2;
    }

    #[test]
    fn test_parse_ltsv_trailing_nl_and_write() {
        let s = io::with_str_writer(|wr| {
            wr.write_str(fmt!("%s:%s\t", "neko", "yes"));
            wr.write_str(fmt!("%s:%s\t", "inu", "yes"));
            wr.write_str(fmt!("%s:%s\n", "tori", "yes"));
        });
        let records_1 = io::with_str_reader(s, |rd| rd.read_ltsv());
        let s2 = io::with_str_writer(|wr| wr.write_ltsv(records_1));
        let records_2 = io::with_str_reader(s2, |rd| rd.read_ltsv());
        assert records_1 == records_2;
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Jauhien Piatlicki.
//
// 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. This file may not be copied, modified, or distributed
// except according to those terms.

// LLVM Execution Engine
// LLVM-C header ExecutionEngine.h

use std;
use std::ffi::CString;

use libc::{c_char, c_uint, size_t};

use llvm_sys::prelude::*;
use llvm_sys::core::*;
use llvm_sys::execution_engine::*;
use llvm_sys::target_machine::*;

use ::{LLVMRef, LLVMRefCtor};
use core;
use execution_engine::GenericValue;
use execution_engine::MCJITMemoryManager;

pub struct FrozenModule {
    module: core::Module
}

impl FrozenModule {
    pub fn get(&self) -> &core::Module {
        &self.module
    }
}

pub struct ExecutionEngine {
    ee: LLVMExecutionEngineRef,
    _memory_manager: Option<Box<MCJITMemoryManager>>
}

impl ExecutionEngine {
    pub fn new(mut module: core::Module) -> Result<(ExecutionEngine, FrozenModule), String> {
        let mut ee = 0 as LLVMExecutionEngineRef;
        let mut error = 0 as *mut c_char;
        unsafe {
            module.unown();
            if LLVMCreateExecutionEngineForModule(&mut ee, module.to_ref(), &mut error) > 0 {
                let cstr_buf = std::ffi::CStr::from_ptr(error);
                let result = String::from_utf8_lossy(cstr_buf.to_bytes()).into_owned();
                LLVMDisposeMessage(error);
                Err(result)
            } else {
                Ok((ExecutionEngine {ee:ee, _memory_manager: None}, FrozenModule {module:module}))
            }
        }
    }

    pub fn new_interpreter(mut module: core::Module) -> Result<(ExecutionEngine, FrozenModule), String> {
        let mut ee = 0 as LLVMExecutionEngineRef;
        let mut error = 0 as *mut c_char;
        unsafe {
            module.unown();
            if LLVMCreateInterpreterForModule(&mut ee, module.to_ref(), &mut error) > 0 {
                let cstr_buf = std::ffi::CStr::from_ptr(error);
                let result = String::from_utf8_lossy(cstr_buf.to_bytes()).into_owned();
                LLVMDisposeMessage(error);
                Err(result)
            } else {
                Ok((ExecutionEngine {ee:ee, _memory_manager: None}, FrozenModule {module:module}))
            }
        }
    }

    pub fn new_jit_compiler(mut module: core::Module, opt_level: u32) -> Result<(ExecutionEngine, FrozenModule), String> {
        let mut ee = 0 as LLVMExecutionEngineRef;
        let mut error = 0 as *mut c_char;
        unsafe {
            module.unown();
            if LLVMCreateJITCompilerForModule(&mut ee, module.to_ref(), opt_level, &mut error) > 0 {
                let cstr_buf = std::ffi::CStr::from_ptr(error);
                let result = String::from_utf8_lossy(cstr_buf.to_bytes()).into_owned();
                LLVMDisposeMessage(error);
                Err(result)
            } else {
                Ok((ExecutionEngine {ee:ee, _memory_manager: None}, FrozenModule {module:module}))
            }
        }
    }

    pub fn add_module(&mut self, mut module: core::Module) -> FrozenModule {
        unsafe {
            LLVMAddModule(self.to_ref(), module.to_ref());
            module.unown();
        }
        FrozenModule {module: module}
    }

    pub fn remove_module(&mut self, module: FrozenModule) -> Result<core::Module, String> {
        let mut module_ref = 0 as LLVMModuleRef;
        let mut error = 0 as *mut c_char;
        unsafe {
            if LLVMRemoveModule(self.to_ref(), module.get().to_ref(), &mut module_ref, &mut error) > 0 {
                let cstr_buf = std::ffi::CStr::from_ptr(error);
                let result = String::from_utf8_lossy(cstr_buf.to_bytes()).into_owned();
                LLVMDisposeMessage(error);
                Err(result)
            }
            else {
                Ok(core::Module::from_ref(module_ref))
            }
        }
    }

    pub fn run_static_constructors(&mut self) {
        unsafe {
            LLVMRunStaticConstructors(self.to_ref())
        }
    }

    pub fn run_static_destructors(&mut self) {
        unsafe {
            LLVMRunStaticDestructors(self.to_ref())
        }
    }

    pub fn run_function<T:core::Function>(&mut self, f: &T, args: &mut [LLVMGenericValueRef]) -> GenericValue {
        unsafe {
            GenericValue::from_ref(LLVMRunFunction(self.to_ref(), f.to_ref(), args.len() as c_uint, args.as_mut_ptr()))
        }
    }

    pub fn get_function_address(&self, name: &str) -> u64 {
        let name = CString::new(name).unwrap();
        unsafe {
            LLVMGetFunctionAddress(self.to_ref(), name.as_ptr() as *const c_char)
        }
    }

    pub fn find_function(&self, name: &str) -> Option<core::FunctionRef> {
        let name = CString::new(name).unwrap();
        let mut f = 0 as LLVMValueRef;
        unsafe {
            if LLVMFindFunction(self.to_ref(),
                                name.as_ptr() as *const c_char,
                                &mut f) > 0 {
                None
            } else {
                Some(core::FunctionRef::from_ref(f))
            }
        }
    }
}

impl LLVMRef<LLVMExecutionEngineRef> for ExecutionEngine {
    fn to_ref(&self) -> LLVMExecutionEngineRef {
        self.ee
    }
}

impl Drop for ExecutionEngine {
    fn drop(&mut self) {
        unsafe {
            LLVMDisposeExecutionEngine(self.to_ref())
        }
    }
}

pub struct MCJITBuilder {
    options: LLVMMCJITCompilerOptions,
    memory_manager: Option<Box<MCJITMemoryManager>>
}

impl MCJITBuilder {
    pub fn new() -> MCJITBuilder {
        let mut options;
        unsafe {
            options = std::mem::uninitialized();
            LLVMInitializeMCJITCompilerOptions(&mut options, std::mem::size_of::<LLVMMCJITCompilerOptions>() as size_t);
        }

        MCJITBuilder {options: options, memory_manager: None}
    }

    pub fn set_opt_level(mut self, opt_level: u32) -> Self {
        self.options.OptLevel = opt_level;
        self
    }

    pub fn set_code_model(mut self, code_model: LLVMCodeModel) -> Self {
        self.options.CodeModel = code_model;
        self
    }

    pub fn no_frame_pointer_elim(mut self) -> Self {
        self.options.NoFramePointerElim = 1;
        self
    }

    pub fn enable_fast_isel(mut self) -> Self {
        self.options.EnableFastISel = 1;
        self
    }

    pub fn set_mcjit_memory_manager(mut self, memory_manager: Box<MCJITMemoryManager>) -> Self {
        self.options.MCJMM = memory_manager.to_ref();
        self.memory_manager = Some(memory_manager);
        self
    }

    pub fn create(mut self, mut module: core::Module) -> Result<(ExecutionEngine, FrozenModule), String> {
        let mut ee = 0 as LLVMExecutionEngineRef;
        let mut error = 0 as *mut c_char;
        unsafe {
            module.unown();
            self.memory_manager = self.memory_manager.map(|mut mm| {mm.unown(); mm});
            if LLVMCreateMCJITCompilerForModule(&mut ee,
                                                module.to_ref(),
                                                &mut self.options,
                                                std::mem::size_of::<LLVMMCJITCompilerOptions>() as size_t,
                                                &mut error) > 0 {
                let cstr_buf = std::ffi::CStr::from_ptr(error);
                let result = String::from_utf8_lossy(cstr_buf.to_bytes()).into_owned();
                LLVMDisposeMessage(error);
                Err(result)
            } else {
                match self.memory_manager {
                    Some(memory_manager) => {
                        Ok((ExecutionEngine {ee:ee, _memory_manager: Some(memory_manager)}, FrozenModule {module:module}))
                    }
                    None => Ok((ExecutionEngine {ee:ee, _memory_manager: None}, FrozenModule {module:module}))
                }
            }
        }
    }
}

pub fn link_in_mcjit() {
    unsafe {
        LLVMLinkInMCJIT();
    }
}

pub fn link_in_interpreter() {
    unsafe {
        LLVMLinkInInterpreter();
    }
}
<commit_msg>[execution_engine] make run_function method in ExecutionEngine take immutable reference<commit_after>// Copyright 2015 Jauhien Piatlicki.
//
// 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. This file may not be copied, modified, or distributed
// except according to those terms.

// LLVM Execution Engine
// LLVM-C header ExecutionEngine.h

use std;
use std::ffi::CString;

use libc::{c_char, c_uint, size_t};

use llvm_sys::prelude::*;
use llvm_sys::core::*;
use llvm_sys::execution_engine::*;
use llvm_sys::target_machine::*;

use ::{LLVMRef, LLVMRefCtor};
use core;
use execution_engine::GenericValue;
use execution_engine::MCJITMemoryManager;

pub struct FrozenModule {
    module: core::Module
}

impl FrozenModule {
    pub fn get(&self) -> &core::Module {
        &self.module
    }
}

pub struct ExecutionEngine {
    ee: LLVMExecutionEngineRef,
    _memory_manager: Option<Box<MCJITMemoryManager>>
}

impl ExecutionEngine {
    pub fn new(mut module: core::Module) -> Result<(ExecutionEngine, FrozenModule), String> {
        let mut ee = 0 as LLVMExecutionEngineRef;
        let mut error = 0 as *mut c_char;
        unsafe {
            module.unown();
            if LLVMCreateExecutionEngineForModule(&mut ee, module.to_ref(), &mut error) > 0 {
                let cstr_buf = std::ffi::CStr::from_ptr(error);
                let result = String::from_utf8_lossy(cstr_buf.to_bytes()).into_owned();
                LLVMDisposeMessage(error);
                Err(result)
            } else {
                Ok((ExecutionEngine {ee:ee, _memory_manager: None}, FrozenModule {module:module}))
            }
        }
    }

    pub fn new_interpreter(mut module: core::Module) -> Result<(ExecutionEngine, FrozenModule), String> {
        let mut ee = 0 as LLVMExecutionEngineRef;
        let mut error = 0 as *mut c_char;
        unsafe {
            module.unown();
            if LLVMCreateInterpreterForModule(&mut ee, module.to_ref(), &mut error) > 0 {
                let cstr_buf = std::ffi::CStr::from_ptr(error);
                let result = String::from_utf8_lossy(cstr_buf.to_bytes()).into_owned();
                LLVMDisposeMessage(error);
                Err(result)
            } else {
                Ok((ExecutionEngine {ee:ee, _memory_manager: None}, FrozenModule {module:module}))
            }
        }
    }

    pub fn new_jit_compiler(mut module: core::Module, opt_level: u32) -> Result<(ExecutionEngine, FrozenModule), String> {
        let mut ee = 0 as LLVMExecutionEngineRef;
        let mut error = 0 as *mut c_char;
        unsafe {
            module.unown();
            if LLVMCreateJITCompilerForModule(&mut ee, module.to_ref(), opt_level, &mut error) > 0 {
                let cstr_buf = std::ffi::CStr::from_ptr(error);
                let result = String::from_utf8_lossy(cstr_buf.to_bytes()).into_owned();
                LLVMDisposeMessage(error);
                Err(result)
            } else {
                Ok((ExecutionEngine {ee:ee, _memory_manager: None}, FrozenModule {module:module}))
            }
        }
    }

    pub fn add_module(&mut self, mut module: core::Module) -> FrozenModule {
        unsafe {
            LLVMAddModule(self.to_ref(), module.to_ref());
            module.unown();
        }
        FrozenModule {module: module}
    }

    pub fn remove_module(&mut self, module: FrozenModule) -> Result<core::Module, String> {
        let mut module_ref = 0 as LLVMModuleRef;
        let mut error = 0 as *mut c_char;
        unsafe {
            if LLVMRemoveModule(self.to_ref(), module.get().to_ref(), &mut module_ref, &mut error) > 0 {
                let cstr_buf = std::ffi::CStr::from_ptr(error);
                let result = String::from_utf8_lossy(cstr_buf.to_bytes()).into_owned();
                LLVMDisposeMessage(error);
                Err(result)
            }
            else {
                Ok(core::Module::from_ref(module_ref))
            }
        }
    }

    pub fn run_static_constructors(&mut self) {
        unsafe {
            LLVMRunStaticConstructors(self.to_ref())
        }
    }

    pub fn run_static_destructors(&mut self) {
        unsafe {
            LLVMRunStaticDestructors(self.to_ref())
        }
    }

    pub fn run_function<T:core::Function>(&self, f: &T, args: &mut [LLVMGenericValueRef]) -> GenericValue {
        unsafe {
            GenericValue::from_ref(LLVMRunFunction(self.to_ref(), f.to_ref(), args.len() as c_uint, args.as_mut_ptr()))
        }
    }

    pub fn get_function_address(&self, name: &str) -> u64 {
        let name = CString::new(name).unwrap();
        unsafe {
            LLVMGetFunctionAddress(self.to_ref(), name.as_ptr() as *const c_char)
        }
    }

    pub fn find_function(&self, name: &str) -> Option<core::FunctionRef> {
        let name = CString::new(name).unwrap();
        let mut f = 0 as LLVMValueRef;
        unsafe {
            if LLVMFindFunction(self.to_ref(),
                                name.as_ptr() as *const c_char,
                                &mut f) > 0 {
                None
            } else {
                Some(core::FunctionRef::from_ref(f))
            }
        }
    }
}

impl LLVMRef<LLVMExecutionEngineRef> for ExecutionEngine {
    fn to_ref(&self) -> LLVMExecutionEngineRef {
        self.ee
    }
}

impl Drop for ExecutionEngine {
    fn drop(&mut self) {
        unsafe {
            LLVMDisposeExecutionEngine(self.to_ref())
        }
    }
}

pub struct MCJITBuilder {
    options: LLVMMCJITCompilerOptions,
    memory_manager: Option<Box<MCJITMemoryManager>>
}

impl MCJITBuilder {
    pub fn new() -> MCJITBuilder {
        let mut options;
        unsafe {
            options = std::mem::uninitialized();
            LLVMInitializeMCJITCompilerOptions(&mut options, std::mem::size_of::<LLVMMCJITCompilerOptions>() as size_t);
        }

        MCJITBuilder {options: options, memory_manager: None}
    }

    pub fn set_opt_level(mut self, opt_level: u32) -> Self {
        self.options.OptLevel = opt_level;
        self
    }

    pub fn set_code_model(mut self, code_model: LLVMCodeModel) -> Self {
        self.options.CodeModel = code_model;
        self
    }

    pub fn no_frame_pointer_elim(mut self) -> Self {
        self.options.NoFramePointerElim = 1;
        self
    }

    pub fn enable_fast_isel(mut self) -> Self {
        self.options.EnableFastISel = 1;
        self
    }

    pub fn set_mcjit_memory_manager(mut self, memory_manager: Box<MCJITMemoryManager>) -> Self {
        self.options.MCJMM = memory_manager.to_ref();
        self.memory_manager = Some(memory_manager);
        self
    }

    pub fn create(mut self, mut module: core::Module) -> Result<(ExecutionEngine, FrozenModule), String> {
        let mut ee = 0 as LLVMExecutionEngineRef;
        let mut error = 0 as *mut c_char;
        unsafe {
            module.unown();
            self.memory_manager = self.memory_manager.map(|mut mm| {mm.unown(); mm});
            if LLVMCreateMCJITCompilerForModule(&mut ee,
                                                module.to_ref(),
                                                &mut self.options,
                                                std::mem::size_of::<LLVMMCJITCompilerOptions>() as size_t,
                                                &mut error) > 0 {
                let cstr_buf = std::ffi::CStr::from_ptr(error);
                let result = String::from_utf8_lossy(cstr_buf.to_bytes()).into_owned();
                LLVMDisposeMessage(error);
                Err(result)
            } else {
                match self.memory_manager {
                    Some(memory_manager) => {
                        Ok((ExecutionEngine {ee:ee, _memory_manager: Some(memory_manager)}, FrozenModule {module:module}))
                    }
                    None => Ok((ExecutionEngine {ee:ee, _memory_manager: None}, FrozenModule {module:module}))
                }
            }
        }
    }
}

pub fn link_in_mcjit() {
    unsafe {
        LLVMLinkInMCJIT();
    }
}

pub fn link_in_interpreter() {
    unsafe {
        LLVMLinkInInterpreter();
    }
}
<|endoftext|>


<commit_before>use std::io;

fn evaluate(input: &str) -> ~str {
    // do nothing with the input for now
    input.to_owned()
}

pub fn main() {
    loop {
        io::print(">> ");
        match io::stdin().read_line() {
            Ok(line) => {
                io::print("=> ");
                io::println(evaluate(line.trim_right()));
            }
            Err(_) => {
                io::print("\n");
                break;
            }
        }
    }
}
<commit_msg>we have an AST but not a parser<commit_after>use std::io;

mod ast {
    pub trait Node {
        fn eval(&self) -> f64;
    }

    pub struct Num {
        pub num: f64
    }

    impl Node for Num {
        fn eval(&self) -> f64 {
            self.num
        }
    }

    pub struct Add {
        pub left: ~Node,
        pub right: ~Node,
    }

    impl Node for Add {
        fn eval(&self) -> f64 {
            self.left.eval() + self.right.eval()
        }
    }

    pub struct Sub {
        pub left: ~Node,
        pub right: ~Node,
    }

    impl Node for Sub {
        fn eval(&self) -> f64 {
            self.left.eval() - self.right.eval()
        }
    }

    pub struct Mul {
        pub left: ~Node,
        pub right: ~Node,
    }

    impl Node for Mul {
        fn eval(&self) -> f64 {
            self.left.eval() * self.right.eval()
        }
    }

    pub struct Div {
        pub left: ~Node,
        pub right: ~Node,
    }

    impl Node for Div {
        fn eval(&self) -> f64 {
            self.left.eval() / self.right.eval()
        }
    }
}

fn parse(input: &str) -> ~ast::Node {
    // just return a static ast for now
    ~ast::Add {
        left: ~ast::Num { num: 1.0 } as ~ast::Node,
        right: ~ast::Num { num: 2.0 } as ~ast::Node,
    } as ~ast::Node
}

fn evaluate(input: &str) -> ~str {
    parse(input).eval().to_str()
}

pub fn main() {
    loop {
        io::print(">> ");
        match io::stdin().read_line() {
            Ok(line) => {
                io::print("=> ");
                io::println(evaluate(line.trim_right()));
            }
            Err(_) => {
                io::print("\n");
                break;
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::time::Duration;
use std::{collections::HashMap, net::SocketAddr};

use anyhow::Result;
use crossbeam_channel::Sender;
use laminar::Packet;

use zombenum_shared::components::{Component, GameEntityId};
use zombenum_shared::messages::server::*;

/// This struct is used to accumulated all information that should be sent to users.
/// Each field is a collection of updates sorted by user id.
pub struct ScheduledUpdates {
    /// New entities.
    /// These have to be transmitted reliably.
    pub added_entities: HashMap<GameEntityId, Vec<Vec<Component>>>,
    /// Critical components.
    /// These have to be transmitted reliably.
    pub critical_components: HashMap<GameEntityId, Vec<(GameEntityId, Component)>>,
    /// Uncritical components.
    /// These updates will be sent, but can go missing.
    /// This is usually stuff that's rapidly updated all the time.
    pub components: HashMap<GameEntityId, Vec<(GameEntityId, Component)>>,
}

impl ScheduledUpdates {
    pub fn new() -> ScheduledUpdates {
        ScheduledUpdates {
            added_entities: HashMap::new(),
            critical_components: HashMap::new(),
            components: HashMap::new(),
        }
    }

    pub fn add_critical_component(
        &mut self,
        player_id: GameEntityId,
        entity_id: GameEntityId,
        component: Component,
    ) {
        let components = self
            .critical_components
            .entry(player_id)
            .or_insert(Vec::new());
        components.push((entity_id, component));
    }
}

/// Send all updates to their respective clients.
pub fn send_server_updates(
    sender: &Sender<Packet>,
    connected_users: &HashMap<SocketAddr, GameEntityId>,
    session_time: Duration,
    scheduled_updates: &ScheduledUpdates,
) -> Result<()> {
    let mut reliable_messages: HashMap<GameEntityId, ServerMessage> = HashMap::new();

    // Handle all new entities
    for (player_id, entities) in scheduled_updates.added_entities.iter() {
        // These entities should be sent to all users
        if *player_id == GameEntityId::all_users() {
            // Iterate over all connected uesrs and add these entities to their message
            for player_id in connected_users.values() {
                let entry = reliable_messages
                    .entry(player_id.clone())
                    .or_insert(ServerMessage::new(session_time));

                for entity in entities {
                    entry.new_entities.push(entity.clone())
                }
            }

            continue;
        }

        // Get the user
        let entry = reliable_messages
            .entry(player_id.clone())
            .or_insert(ServerMessage::new(session_time));

        for entity in entities {
            entry.new_entities.push(entity.clone())
        }
    }

    // Handle all critical components
    for (player_id, components) in scheduled_updates.critical_components.iter() {
        // These components should be sent to all users
        if *player_id == GameEntityId::all_users() {
            // Iterate over all connected users and add these components to their message
            for player_id in connected_users.values() {
                let entry = reliable_messages
                    .entry(player_id.clone())
                    .or_insert(ServerMessage::new(session_time));

                for component in components {
                    entry.changed_components.push(component.clone())
                }
            }

            continue;
        }

        for component in components {
            let entry = reliable_messages
                .entry(player_id.clone())
                .or_insert(ServerMessage::new(session_time));

            entry.changed_components.push(component.clone())
        }
    }

    Ok(())
}
<commit_msg>Send updates to clients<commit_after>use std::time::Duration;
use std::{collections::HashMap, net::SocketAddr};

use anyhow::Result;
use crossbeam_channel::Sender;
use laminar::Packet;

use zombenum_shared::components::{Component, GameEntityId};
use zombenum_shared::messages::server::*;

/// This struct is used to accumulated all information that should be sent to users.
/// Each field is a collection of updates sorted by user id.
pub struct ScheduledUpdates {
    /// New entities.
    /// These have to be transmitted reliably.
    pub added_entities: HashMap<GameEntityId, Vec<Vec<Component>>>,
    /// Critical components.
    /// These have to be transmitted reliably.
    pub critical_components: HashMap<GameEntityId, Vec<(GameEntityId, Component)>>,
    /// Uncritical components.
    /// These updates will be sent, but can go missing.
    /// This is usually stuff that's rapidly updated all the time.
    pub components: HashMap<GameEntityId, Vec<(GameEntityId, Component)>>,
}

impl ScheduledUpdates {
    pub fn new() -> ScheduledUpdates {
        ScheduledUpdates {
            added_entities: HashMap::new(),
            critical_components: HashMap::new(),
            components: HashMap::new(),
        }
    }

    pub fn add_critical_component(
        &mut self,
        player_id: GameEntityId,
        entity_id: GameEntityId,
        component: Component,
    ) {
        let components = self
            .critical_components
            .entry(player_id)
            .or_insert(Vec::new());
        components.push((entity_id, component));
    }
}

/// Send all updates to their respective clients.
pub fn send_server_updates(
    sender: &Sender<Packet>,
    connected_users: &HashMap<SocketAddr, GameEntityId>,
    session_time: Duration,
    scheduled_updates: &ScheduledUpdates,
) -> Result<()> {
    let mut reliable_messages: HashMap<GameEntityId, ServerMessage> = HashMap::new();

    // Handle all new entities
    for (player_id, entities) in scheduled_updates.added_entities.iter() {
        // These entities should be sent to all users
        if *player_id == GameEntityId::all_users() {
            // Iterate over all connected uesrs and add these entities to their message
            for player_id in connected_users.values() {
                let entry = reliable_messages
                    .entry(player_id.clone())
                    .or_insert(ServerMessage::new(session_time));

                for entity in entities {
                    entry.new_entities.push(entity.clone())
                }
            }

            continue;
        }

        // Get the user
        let entry = reliable_messages
            .entry(player_id.clone())
            .or_insert(ServerMessage::new(session_time));

        for entity in entities {
            entry.new_entities.push(entity.clone())
        }
    }

    // Handle all critical components
    for (player_id, components) in scheduled_updates.critical_components.iter() {
        // These components should be sent to all users
        if *player_id == GameEntityId::all_users() {
            // Iterate over all connected users and add these components to their message
            for player_id in connected_users.values() {
                let entry = reliable_messages
                    .entry(player_id.clone())
                    .or_insert(ServerMessage::new(session_time));

                for component in components {
                    entry.changed_components.push(component.clone())
                }
            }

            continue;
        }

        for component in components {
            let entry = reliable_messages
                .entry(player_id.clone())
                .or_insert(ServerMessage::new(session_time));

            entry.changed_components.push(component.clone())
        }
    }

    // Send all critical messages
    for (addr, player_id) in connected_users {
        if let Some(message) = reliable_messages.get(player_id) {
            sender.send(Packet::reliable_ordered(
                *addr,
                bincode::serialize(message)?,
                None,
            ))?;
        };
    }

    let mut unreliable_messages: HashMap<GameEntityId, ServerMessage> = HashMap::new();

    // Handle all non-critical components
    for (player_id, components) in scheduled_updates.components.iter() {
        // These components should be sent to all users
        if *player_id == GameEntityId::all_users() {
            // Iterate over all connected users and add these components to their message
            for player_id in connected_users.values() {
                let entry = unreliable_messages
                    .entry(player_id.clone())
                    .or_insert(ServerMessage::new(session_time));

                for component in components {
                    entry.changed_components.push(component.clone())
                }
            }

            continue;
        }

        for component in components {
            let entry = unreliable_messages
                .entry(player_id.clone())
                .or_insert(ServerMessage::new(session_time));

            entry.changed_components.push(component.clone())
        }
    }

    // Send all uncritical messages
    for (addr, player_id) in connected_users {
        if let Some(message) = unreliable_messages.get(player_id) {
            sender.send(Packet::reliable_ordered(
                *addr,
                bincode::serialize(message)?,
                None,
            ))?;
        };
    }

    Ok(())
}
<|endoftext|>