<commit_before>// Currently the only cross compilers available via nightlies are on linux/osx,
// so we can only run these tests on those platforms
#![cfg(target_os = "linux")]
#![cfg(target_os = "macos")]

use std::os;
use std::path;

use support::{project, execs, basic_bin_manifest};
use support::{RUNNING, COMPILING, DOCTEST, cargo_dir};
use hamcrest::{assert_that, existing_file};
use cargo::util::process;

fn setup() {
}

fn disabled() -> bool {
    match os::getenv("CFG_DISABLE_CROSS_TESTS") {
        Some(ref s) if s.as_slice() == "1" => true,
        _ => false,
    }
}

fn alternate() -> &'static str {
    match os::consts::SYSNAME {
        "linux" => "i686-unknown-linux-gnu",
        "macos" => "i686-apple-darwin",
        _ => unreachable!(),
    }
}

test!(simple_cross {
    if disabled() { return }

    let p = project("foo")
        .file("Cargo.toml", basic_bin_manifest("foo").as_slice())
        .file("src/foo.rs", r#"
            use std::os;
            fn main() {
                assert_eq!(os::consts::ARCH, "x86");
            }
        "#);

    let target = alternate();
    assert_that(p.cargo_process("cargo-build").arg("--target").arg(target),
                execs().with_status(0));
    assert_that(&p.target_bin(target, "foo"), existing_file());

    assert_that(
      process(p.target_bin(target, "foo")),
      execs().with_status(0));
})

test!(simple_deps {
    if disabled() { return }

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

            [dependencies.bar]
            path = "../bar"
        "#)
        .file("src/main.rs", r#"
            extern crate bar;
            fn main() { bar::bar(); }
        "#);
    let p2 = project("bar")
        .file("Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.0.1"
            authors = []
        "#)
        .file("src/lib.rs", "pub fn bar() {}");
    p2.build();

    let target = alternate();
    assert_that(p.cargo_process("cargo-build").arg("--target").arg(target),
                execs().with_status(0));
    assert_that(&p.target_bin(target, "foo"), existing_file());

    assert_that(
      process(p.target_bin(target, "foo")),
      execs().with_status(0));
})

test!(plugin_deps {
    if disabled() { return }

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

            [dependencies.bar]
            path = "../bar"

            [dependencies.baz]
            path = "../baz"
        "#)
        .file("src/main.rs", r#"
            #![feature(phase)]
            #[phase(plugin)]
            extern crate bar;
            extern crate baz;
            fn main() {
                assert_eq!(bar!(), baz::baz());
            }
        "#);
    let bar = project("bar")
        .file("Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.0.1"
            authors = []

            [[lib]]
            name = "bar"
            plugin = true
        "#)
        .file("src/lib.rs", r#"
            #![feature(plugin_registrar, quote)]

            extern crate rustc;
            extern crate syntax;

            use rustc::plugin::Registry;
            use syntax::ast::TokenTree;
            use syntax::codemap::Span;
            use syntax::ext::base::{ExtCtxt, MacExpr, MacResult};

            #[plugin_registrar]
            pub fn foo(reg: &mut Registry) {
                reg.register_macro("bar", expand_bar);
            }

            fn expand_bar(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
                          -> Box<MacResult> {
                MacExpr::new(quote_expr!(cx, 1i))
            }
        "#);
    let baz = project("baz")
        .file("Cargo.toml", r#"
            [package]
            name = "baz"
            version = "0.0.1"
            authors = []
        "#)
        .file("src/lib.rs", "pub fn baz() -> int { 1 }");
    bar.build();
    baz.build();

    let target = alternate();
    assert_that(foo.cargo_process("cargo-build").arg("--target").arg(target),
                execs().with_status(0));
    assert_that(&foo.target_bin(target, "foo"), existing_file());

    assert_that(
      process(foo.target_bin(target, "foo")),
      execs().with_status(0));
})

test!(plugin_to_the_max {
    if disabled() { return }

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

            [dependencies.bar]
            path = "../bar"

            [dependencies.baz]
            path = "../baz"
        "#)
        .file("src/main.rs", r#"
            #![feature(phase)]
            #[phase(plugin)]
            extern crate bar;
            extern crate baz;
            fn main() {
                assert_eq!(bar!(), baz::baz());
            }
        "#);
    let bar = project("bar")
        .file("Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.0.1"
            authors = []

            [[lib]]
            name = "bar"
            plugin = true

            [dependencies.baz]
            path = "../baz"
        "#)
        .file("src/lib.rs", r#"
            #![feature(plugin_registrar, quote)]

            extern crate rustc;
            extern crate syntax;
            extern crate baz;

            use rustc::plugin::Registry;
            use syntax::ast::TokenTree;
            use syntax::codemap::Span;
            use syntax::ext::base::{ExtCtxt, MacExpr, MacResult};

            #[plugin_registrar]
            pub fn foo(reg: &mut Registry) {
                reg.register_macro("bar", expand_bar);
            }

            fn expand_bar(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
                          -> Box<MacResult> {
                MacExpr::new(quote_expr!(cx, baz::baz()))
            }
        "#);
    let baz = project("baz")
        .file("Cargo.toml", r#"
            [package]
            name = "baz"
            version = "0.0.1"
            authors = []
        "#)
        .file("src/lib.rs", "pub fn baz() -> int { 1 }");
    bar.build();
    baz.build();

    let target = alternate();
    assert_that(foo.cargo_process("cargo-build").arg("--target").arg(target),
                execs().with_status(0));
    assert_that(foo.process(cargo_dir().join("cargo-build"))
                   .arg("--target").arg(target),
                execs().with_status(0));
    assert_that(&foo.target_bin(target, "foo"), existing_file());

    assert_that(
      process(foo.target_bin(target, "foo")),
      execs().with_status(0));
})

test!(linker_and_ar {
    if disabled() { return }

    let target = alternate();
    let p = project("foo")
        .file(".cargo/config", format!(r#"
            [target.{}]
            ar = "my-ar-tool"
            linker = "my-linker-tool"
        "#, target).as_slice())
        .file("Cargo.toml", basic_bin_manifest("foo").as_slice())
        .file("src/foo.rs", r#"
            use std::os;
            fn main() {
                assert_eq!(os::consts::ARCH, "x86");
            }
        "#);

    assert_that(p.cargo_process("cargo-build").arg("--target").arg(target)
                                              .arg("-v"),
                execs().with_status(101)
                       .with_stdout(format!("\
{running} `rustc src/foo.rs --crate-name foo --crate-type bin \
    --out-dir {dir}{sep}target{sep}{target} \
    --dep-info [..] \
    --target {target} \
    -C ar=my-ar-tool -C linker=my-linker-tool \
    -L {dir}{sep}target{sep}{target} \
    -L {dir}{sep}target{sep}{target}{sep}deps`
{compiling} foo v0.5.0 ({url})
",
                            running = RUNNING,
                            compiling = COMPILING,
                            dir = p.root().display(),
                            url = p.url(),
                            target = target,
                            sep = path::SEP,
                            ).as_slice()));
})

test!(plugin_with_extra_dylib_dep {
    if disabled() { return }

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

            [dependencies.bar]
            path = "../bar"
        "#)
        .file("src/main.rs", r#"
            #![feature(phase)]
            #[phase(plugin)] extern crate bar;

            fn main() {}
        "#);
    let bar = project("bar")
        .file("Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.0.1"
            authors = []

            [[lib]]
            name = "bar"
            plugin = true

            [dependencies.baz]
            path = "../baz"
        "#)
        .file("src/lib.rs", r#"
            #![feature(plugin_registrar)]

            extern crate rustc;
            extern crate baz;

            use rustc::plugin::Registry;

            #[plugin_registrar]
            pub fn foo(reg: &mut Registry) {
                println!("{}", baz::baz());
            }
        "#);
    let baz = project("baz")
        .file("Cargo.toml", r#"
            [package]
            name = "baz"
            version = "0.0.1"
            authors = []

            [[lib]]
            name = "baz"
            crate_type = ["dylib"]
        "#)
        .file("src/lib.rs", "pub fn baz() -> int { 1 }");
    bar.build();
    baz.build();

    let target = alternate();
    assert_that(foo.cargo_process("cargo-build").arg("--target").arg(target),
                execs().with_status(0));
})

test!(cross_tests {
    if disabled() { return }

    let p = project("foo")
        .file("Cargo.toml", r#"
            [project]
            name = "foo"
            authors = []
            version = "0.0.0"
        "#)
        .file("src/main.rs", r#"
            extern crate foo;
            use std::os;
            fn main() {
                assert_eq!(os::consts::ARCH, "x86");
            }
            #[test] fn test() { main() }
        "#)
        .file("src/lib.rs", r#"
            use std::os;
            pub fn foo() { assert_eq!(os::consts::ARCH, "x86"); }
            #[test] fn test_foo() { foo() }
        "#);

    let target = alternate();
    assert_that(p.cargo_process("cargo-test").arg("--target").arg(target),
                execs().with_status(0)
                       .with_stdout(format!("\
{compiling} foo v0.0.0 ({foo})
{running} target[..]{triple}[..]test[..]foo-[..]

running 1 test
test test ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured

{running} target[..]{triple}[..]test[..]foo-[..]

running 1 test
test test_foo ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured

{doctest} foo

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured

", compiling = COMPILING, running = RUNNING, foo = p.url(), triple = target,
   doctest = DOCTEST)));
})
<commit_msg>Fix a flaky test (due to hashes changing)<commit_after>// Currently the only cross compilers available via nightlies are on linux/osx,
// so we can only run these tests on those platforms
#![cfg(target_os = "linux")]
#![cfg(target_os = "macos")]

use std::os;
use std::path;

use support::{project, execs, basic_bin_manifest};
use support::{RUNNING, COMPILING, DOCTEST, cargo_dir};
use hamcrest::{assert_that, existing_file};
use cargo::util::process;

fn setup() {
}

fn disabled() -> bool {
    match os::getenv("CFG_DISABLE_CROSS_TESTS") {
        Some(ref s) if s.as_slice() == "1" => true,
        _ => false,
    }
}

fn alternate() -> &'static str {
    match os::consts::SYSNAME {
        "linux" => "i686-unknown-linux-gnu",
        "macos" => "i686-apple-darwin",
        _ => unreachable!(),
    }
}

test!(simple_cross {
    if disabled() { return }

    let p = project("foo")
        .file("Cargo.toml", basic_bin_manifest("foo").as_slice())
        .file("src/foo.rs", r#"
            use std::os;
            fn main() {
                assert_eq!(os::consts::ARCH, "x86");
            }
        "#);

    let target = alternate();
    assert_that(p.cargo_process("cargo-build").arg("--target").arg(target),
                execs().with_status(0));
    assert_that(&p.target_bin(target, "foo"), existing_file());

    assert_that(
      process(p.target_bin(target, "foo")),
      execs().with_status(0));
})

test!(simple_deps {
    if disabled() { return }

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

            [dependencies.bar]
            path = "../bar"
        "#)
        .file("src/main.rs", r#"
            extern crate bar;
            fn main() { bar::bar(); }
        "#);
    let p2 = project("bar")
        .file("Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.0.1"
            authors = []
        "#)
        .file("src/lib.rs", "pub fn bar() {}");
    p2.build();

    let target = alternate();
    assert_that(p.cargo_process("cargo-build").arg("--target").arg(target),
                execs().with_status(0));
    assert_that(&p.target_bin(target, "foo"), existing_file());

    assert_that(
      process(p.target_bin(target, "foo")),
      execs().with_status(0));
})

test!(plugin_deps {
    if disabled() { return }

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

            [dependencies.bar]
            path = "../bar"

            [dependencies.baz]
            path = "../baz"
        "#)
        .file("src/main.rs", r#"
            #![feature(phase)]
            #[phase(plugin)]
            extern crate bar;
            extern crate baz;
            fn main() {
                assert_eq!(bar!(), baz::baz());
            }
        "#);
    let bar = project("bar")
        .file("Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.0.1"
            authors = []

            [[lib]]
            name = "bar"
            plugin = true
        "#)
        .file("src/lib.rs", r#"
            #![feature(plugin_registrar, quote)]

            extern crate rustc;
            extern crate syntax;

            use rustc::plugin::Registry;
            use syntax::ast::TokenTree;
            use syntax::codemap::Span;
            use syntax::ext::base::{ExtCtxt, MacExpr, MacResult};

            #[plugin_registrar]
            pub fn foo(reg: &mut Registry) {
                reg.register_macro("bar", expand_bar);
            }

            fn expand_bar(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
                          -> Box<MacResult> {
                MacExpr::new(quote_expr!(cx, 1i))
            }
        "#);
    let baz = project("baz")
        .file("Cargo.toml", r#"
            [package]
            name = "baz"
            version = "0.0.1"
            authors = []
        "#)
        .file("src/lib.rs", "pub fn baz() -> int { 1 }");
    bar.build();
    baz.build();

    let target = alternate();
    assert_that(foo.cargo_process("cargo-build").arg("--target").arg(target),
                execs().with_status(0));
    assert_that(&foo.target_bin(target, "foo"), existing_file());

    assert_that(
      process(foo.target_bin(target, "foo")),
      execs().with_status(0));
})

test!(plugin_to_the_max {
    if disabled() { return }

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

            [dependencies.bar]
            path = "../bar"

            [dependencies.baz]
            path = "../baz"
        "#)
        .file("src/main.rs", r#"
            #![feature(phase)]
            #[phase(plugin)]
            extern crate bar;
            extern crate baz;
            fn main() {
                assert_eq!(bar!(), baz::baz());
            }
        "#);
    let bar = project("bar")
        .file("Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.0.1"
            authors = []

            [[lib]]
            name = "bar"
            plugin = true

            [dependencies.baz]
            path = "../baz"
        "#)
        .file("src/lib.rs", r#"
            #![feature(plugin_registrar, quote)]

            extern crate rustc;
            extern crate syntax;
            extern crate baz;

            use rustc::plugin::Registry;
            use syntax::ast::TokenTree;
            use syntax::codemap::Span;
            use syntax::ext::base::{ExtCtxt, MacExpr, MacResult};

            #[plugin_registrar]
            pub fn foo(reg: &mut Registry) {
                reg.register_macro("bar", expand_bar);
            }

            fn expand_bar(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
                          -> Box<MacResult> {
                MacExpr::new(quote_expr!(cx, baz::baz()))
            }
        "#);
    let baz = project("baz")
        .file("Cargo.toml", r#"
            [package]
            name = "baz"
            version = "0.0.1"
            authors = []
        "#)
        .file("src/lib.rs", "pub fn baz() -> int { 1 }");
    bar.build();
    baz.build();

    let target = alternate();
    assert_that(foo.cargo_process("cargo-build").arg("--target").arg(target),
                execs().with_status(0));
    assert_that(foo.process(cargo_dir().join("cargo-build"))
                   .arg("--target").arg(target),
                execs().with_status(0));
    assert_that(&foo.target_bin(target, "foo"), existing_file());

    assert_that(
      process(foo.target_bin(target, "foo")),
      execs().with_status(0));
})

test!(linker_and_ar {
    if disabled() { return }

    let target = alternate();
    let p = project("foo")
        .file(".cargo/config", format!(r#"
            [target.{}]
            ar = "my-ar-tool"
            linker = "my-linker-tool"
        "#, target).as_slice())
        .file("Cargo.toml", basic_bin_manifest("foo").as_slice())
        .file("src/foo.rs", r#"
            use std::os;
            fn main() {
                assert_eq!(os::consts::ARCH, "x86");
            }
        "#);

    assert_that(p.cargo_process("cargo-build").arg("--target").arg(target)
                                              .arg("-v"),
                execs().with_status(101)
                       .with_stdout(format!("\
{running} `rustc src/foo.rs --crate-name foo --crate-type bin \
    --out-dir {dir}{sep}target{sep}{target} \
    --dep-info [..] \
    --target {target} \
    -C ar=my-ar-tool -C linker=my-linker-tool \
    -L {dir}{sep}target{sep}{target} \
    -L {dir}{sep}target{sep}{target}{sep}deps`
{compiling} foo v0.5.0 ({url})
",
                            running = RUNNING,
                            compiling = COMPILING,
                            dir = p.root().display(),
                            url = p.url(),
                            target = target,
                            sep = path::SEP,
                            ).as_slice()));
})

test!(plugin_with_extra_dylib_dep {
    if disabled() { return }

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

            [dependencies.bar]
            path = "../bar"
        "#)
        .file("src/main.rs", r#"
            #![feature(phase)]
            #[phase(plugin)] extern crate bar;

            fn main() {}
        "#);
    let bar = project("bar")
        .file("Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.0.1"
            authors = []

            [[lib]]
            name = "bar"
            plugin = true

            [dependencies.baz]
            path = "../baz"
        "#)
        .file("src/lib.rs", r#"
            #![feature(plugin_registrar)]

            extern crate rustc;
            extern crate baz;

            use rustc::plugin::Registry;

            #[plugin_registrar]
            pub fn foo(reg: &mut Registry) {
                println!("{}", baz::baz());
            }
        "#);
    let baz = project("baz")
        .file("Cargo.toml", r#"
            [package]
            name = "baz"
            version = "0.0.1"
            authors = []

            [[lib]]
            name = "baz"
            crate_type = ["dylib"]
        "#)
        .file("src/lib.rs", "pub fn baz() -> int { 1 }");
    bar.build();
    baz.build();

    let target = alternate();
    assert_that(foo.cargo_process("cargo-build").arg("--target").arg(target),
                execs().with_status(0));
})

test!(cross_tests {
    if disabled() { return }

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

            [[bin]]
            name = "bar"
        "#)
        .file("src/main.rs", r#"
            extern crate foo;
            use std::os;
            fn main() {
                assert_eq!(os::consts::ARCH, "x86");
            }
            #[test] fn test() { main() }
        "#)
        .file("src/lib.rs", r#"
            use std::os;
            pub fn foo() { assert_eq!(os::consts::ARCH, "x86"); }
            #[test] fn test_foo() { foo() }
        "#);

    let target = alternate();
    assert_that(p.cargo_process("cargo-test").arg("--target").arg(target),
                execs().with_status(0)
                       .with_stdout(format!("\
{compiling} foo v0.0.0 ({foo})
{running} target[..]{triple}[..]test[..]bar-[..]

running 1 test
test test ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured

{running} target[..]{triple}[..]test[..]foo-[..]

running 1 test
test test_foo ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured

{doctest} foo

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured

", compiling = COMPILING, running = RUNNING, foo = p.url(), triple = target,
   doctest = DOCTEST)));
})
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

// Marauder is grid-less turn-based strategy game.

extern mod glfw;
extern mod gl;
extern mod cgmath;

use gl::types::{
  GLenum,
  GLuint,
  GLint,
  GLchar,
  GLfloat,
  GLsizeiptr,
  GLboolean
};
use cgmath::matrix::{Matrix, Mat4, Mat3, ToMat4};
use cgmath::projection;
use cgmath::angle;
use cgmath::vector::{Vec3, Vec2};

#[link(name = "glfw")]
#[link(name = "m")]
extern {}

/// usage: let s = mvp_matrix; println(type_of(&s));
fn type_of<T>(_: &T) -> &'static str {
  unsafe {
    (*std::unstable::intrinsics::get_tydesc::<T>()).name
  }
}

fn print_mat4(name: &str, mat: Mat4<f32>) {
  println!("{}:", name);
  for i in range(0u, 4) {
    for j in range(0u, 4) {
      print!("{} ", *mat.cr(i, j));
    }
    println("");
  }
  println("");
}

static mut MOUSE_POS: Vec2<f32> = Vec2{x: 0.0f32, y: 0.0};
static mut CAMERA_POS: Vec3<f32> = Vec3{x: 0.0f32, y: 0.0, z: 0.0};

static WIN_SIZE: Vec2<uint> = Vec2{x: 640, y: 480};
static VERTICES_COUNT: i32 = 3 * 2;

static VERTEX_DATA: [GLfloat, ..VERTICES_COUNT * 3] = [
   0.0,  1.0, 0.0,
   2.0, -1.0, 0.0,
  -2.0, -1.0, 0.0,

  0.0,  1.0,  0.0,
  0.0, -1.0,  2.0,
  0.0, -1.0, -2.0
];

static VERTEX_SHADER_SRC: &'static str = "
  #version 130
  in vec3 position;
  uniform mat4 model_view_proj_matrix;
  void main() {
    vec4 v = vec4(position, 1);
    gl_Position = model_view_proj_matrix * v;
  }
";

static FRAGMENT_SHADER_SRC: &'static str = "
  #version 130
  out vec4 out_color;
  void main() {
    out_color = vec4(1.0, 1.0, 1.0, 1.0);
  }
";

fn compile_shader(src: &str, ty: GLenum) -> GLuint {
  let shader = gl::CreateShader(ty);
  unsafe {
    // Attempt to compile the shader
    gl::ShaderSource(shader, 1, &src.to_c_str().unwrap(), std::ptr::null());
    gl::CompileShader(shader);

    // Get the compile status
    let mut status = gl::FALSE as GLint;
    gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);

    // Fail on error
    if status != (gl::TRUE as GLint) {
      let mut len = 0;
      gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
      // subtract 1 to skip the trailing null character
      let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
      gl::GetShaderInfoLog(shader, len, std::ptr::mut_null(),
        std::vec::raw::to_mut_ptr(buf) as *mut GLchar
      );
      fail!("compile_shader(): " + std::str::raw::from_utf8(buf));
    }
  }
  shader
}

fn link_program(vertex_shader: GLuint, fragment_shader: GLuint) -> GLuint {
  let program = gl::CreateProgram();
  gl::AttachShader(program, vertex_shader);
  gl::AttachShader(program, fragment_shader);
  gl::LinkProgram(program);
  unsafe {
    // Get the link status
    let mut status = gl::FALSE as GLint;
    gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);

    // Fail on error
    if status != (gl::TRUE as GLint) {
      let mut len: GLint = 0;
      gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
      // subtract 1 to skip the trailing null character
      let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
      gl::GetProgramInfoLog(program, len, std::ptr::mut_null(),
        std::vec::raw::to_mut_ptr(buf) as *mut GLchar
      );
      fail!("link_program(): " + std::str::raw::from_utf8(buf));
    }
  }
  program
}

fn tr(m: Mat4<f32>, v: Vec3<f32>) -> Mat4<f32> {
  let mut t = Mat4::<f32>::identity();
  *t.mut_cr(3, 0) = v.x;
  *t.mut_cr(3, 1) = v.y;
  *t.mut_cr(3, 2) = v.z;
  m.mul_m(&t)
}

fn rot_x(m: Mat4<f32>, angle: f32) -> Mat4<f32> {
  let r = Mat3::from_angle_x(angle::rad(angle)).to_mat4();
  m.mul_m(&r)
}

fn rot_y(m: Mat4<f32>, angle: f32) -> Mat4<f32> {
  let r = Mat3::from_angle_y(angle::rad(angle)).to_mat4();
  m.mul_m(&r)
}

struct Win {
  vertex_shader: GLuint,
  fragment_shader: GLuint,
  program: GLuint,
  vertex_array_obj: GLuint,
  vertex_buffer_obj: GLuint,
  matrix_id: GLint,
  window: glfw::Window
}

impl Win {
  fn new() -> Win {
    // TODO: Move to opengl_init method
    // glfw::window_hint::context_version(3, 2);

    let mut win =  Win{
      vertex_shader: 0,
      fragment_shader: 0,
      program: 0,
      vertex_array_obj: 0,
      vertex_buffer_obj: 0,
      matrix_id: 0,
      window: glfw::Window::create(
        WIN_SIZE.x,
        WIN_SIZE.y,
        "OpenGL",
        glfw::Windowed
      ).unwrap()
    };

    win.window.make_context_current();
    win.window.set_cursor_pos_callback(~CursorPosContext);
    win.window.set_key_callback(~KeyContext);

    // Load the OpenGL function pointers
    gl::load_with(glfw::get_proc_address);

    // Create GLSL shaders
    win.vertex_shader = compile_shader(
      VERTEX_SHADER_SRC, gl::VERTEX_SHADER);
    win.fragment_shader = compile_shader(
      FRAGMENT_SHADER_SRC, gl::FRAGMENT_SHADER);
    win.program = link_program(win.vertex_shader, win.fragment_shader);

    unsafe {
      // Create Vertex Array Object
      gl::GenVertexArrays(1, &mut win.vertex_array_obj);
      gl::BindVertexArray(win.vertex_array_obj);

      // Create a Vertex Buffer Object and copy the vertex data to it
      gl::GenBuffers(1, &mut win.vertex_buffer_obj);
      gl::BindBuffer(gl::ARRAY_BUFFER, win.vertex_buffer_obj);
      let float_size = std::mem::size_of::<GLfloat>();
      let vertices_ptr = (VERTEX_DATA.len() * float_size) as GLsizeiptr;
      gl::BufferData(
        gl::ARRAY_BUFFER,
        vertices_ptr,
        std::cast::transmute(&VERTEX_DATA[0]),
        gl::STATIC_DRAW
      );

      gl::UseProgram(win.program);
      gl::BindFragDataLocation(win.program, 0, "out_color".to_c_str().unwrap());

      // Specify the layout of the vertex data
      let pos_attr = gl::GetAttribLocation(
        win.program, "position".to_c_str().unwrap()) as GLuint;
      gl::EnableVertexAttribArray(pos_attr);
      let size = 3;
      let normalized = gl::FALSE as GLboolean;
      let stride = 0;
      gl::VertexAttribPointer(
        pos_attr,
        size,
        gl::FLOAT,
        normalized,
        stride,
        std::ptr::null()
      );

      // Get a handle for our "model_view_proj_matrix" uniform.
      // Only at initialisation time.
      win.matrix_id = gl::GetUniformLocation(
        win.program, "model_view_proj_matrix".to_c_str().unwrap()
      );
    }

    win
  }

  fn cleanup(&self) {
    // Cleanup
    gl::DeleteProgram(self.program);
    gl::DeleteShader(self.fragment_shader);
    gl::DeleteShader(self.vertex_shader);
    unsafe {
      gl::DeleteBuffers(1, &self.vertex_buffer_obj);
      gl::DeleteVertexArrays(1, &self.vertex_array_obj);
    }
  }

  fn update_matrices(&self) {
    let fov = angle::deg(45.0f32);
    let ratio = 4.0 / 3.0;
    let display_range_min = 0.1;
    let display_range_max = 100.0;
    let projection_matrix = projection::perspective(
      fov, ratio, display_range_min, display_range_max
    );

    let mut mvp_matrix = projection_matrix;
    unsafe {
      mvp_matrix = tr(mvp_matrix, Vec3{x: 0.0f32, y: 0.0, z: -10.0f32});
      mvp_matrix = rot_x(mvp_matrix, MOUSE_POS.y / 100.0);
      mvp_matrix = rot_y(mvp_matrix, MOUSE_POS.x / 100.0);
      mvp_matrix = tr(mvp_matrix, CAMERA_POS);
    }

    unsafe {
      // Send our transformation to the currently bound shader,
      // in the "model_view_proj_matrix" uniform.
      // For each model you render, since the model_view_proj_matrix
      // will be different (at least the M part).
      gl::UniformMatrix4fv(self.matrix_id, 1, gl::FALSE, mvp_matrix.cr(0, 0));
    }
  }

  fn draw(&self) {
    self.update_matrices();

    // Clear the screen to black
    gl::ClearColor(0.3, 0.3, 0.3, 1.0);
    gl::Clear(gl::COLOR_BUFFER_BIT);

    // Draw a triangle from the 3 vertices
    gl::DrawArrays(gl::TRIANGLES, 0, VERTICES_COUNT);

    self.window.swap_buffers();
  }

  fn is_running(&self) -> bool {
    return !self.window.should_close()
  }

  fn process_events(&self) {
    glfw::poll_events();
  }
}

struct CursorPosContext;
impl glfw::CursorPosCallback for CursorPosContext {
  fn call(&self, w: &glfw::Window, xpos: f64, ypos: f64) {
    if w.get_mouse_button(glfw::MouseButtonRight) == glfw::Press {
      // println!("Cursor position: ({}, {})", xpos, ypos);
      unsafe {
        MOUSE_POS.x = xpos as f32;
        MOUSE_POS.y = ypos as f32;
      }
    }
  }
}

struct ErrorContext;
impl glfw::ErrorCallback for ErrorContext {
  fn call(&self, _: glfw::Error, description: ~str) {
    println!("GLFW Error: {:s}", description);
  }
}

struct KeyContext;
impl glfw::KeyCallback for KeyContext {
  fn call(
    &self,
    window: &glfw::Window,
    key:    glfw::Key,
    _:      std::libc::c_int,
    action: glfw::Action,
    _:      glfw::Modifiers
  ) {
    match (action, key) {
      (glfw::Press, glfw::KeyEscape) | (glfw::Press, glfw::KeyQ) => {
        window.set_should_close(true)
      }
      (glfw::Press, glfw::KeySpace) => {
        println!("space")
      }
      (glfw::Press, glfw::KeyUp) => unsafe { CAMERA_POS.y -= 1.0f32 },
      (glfw::Press, glfw::KeyDown) => unsafe { CAMERA_POS.y += 1.0f32 },
      (glfw::Press, glfw::KeyRight) => unsafe { CAMERA_POS.x -= 1.0f32 },
      (glfw::Press, glfw::KeyLeft) => unsafe { CAMERA_POS.x += 1.0f32 },
      _ => {}
    }
  }
}

fn main() {
  glfw::set_error_callback(~ErrorContext);
  do glfw::start {
    let win =  Win::new();
    while win.is_running() {
      win.process_events();
      win.draw();
    }
    win.cleanup();
  }
}

#[start]
fn start(argc: int, argv: **u8) -> int {
  std::rt::start_on_main_thread(argc, argv, main)
}

// vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab:
<commit_msg>KeyCallback: let distance = 1<commit_after>// See LICENSE file for copyright and license details.

// Marauder is grid-less turn-based strategy game.

extern mod glfw;
extern mod gl;
extern mod cgmath;

use gl::types::{
  GLenum,
  GLuint,
  GLint,
  GLchar,
  GLfloat,
  GLsizeiptr,
  GLboolean
};
use cgmath::matrix::{Matrix, Mat4, Mat3, ToMat4};
use cgmath::projection;
use cgmath::angle;
use cgmath::vector::{Vec3, Vec2};

#[link(name = "glfw")]
#[link(name = "m")]
extern {}

/// usage: let s = mvp_matrix; println(type_of(&s));
fn type_of<T>(_: &T) -> &'static str {
  unsafe {
    (*std::unstable::intrinsics::get_tydesc::<T>()).name
  }
}

fn print_mat4(name: &str, mat: Mat4<f32>) {
  println!("{}:", name);
  for i in range(0u, 4) {
    for j in range(0u, 4) {
      print!("{} ", *mat.cr(i, j));
    }
    println("");
  }
  println("");
}

static mut MOUSE_POS: Vec2<f32> = Vec2{x: 0.0f32, y: 0.0};
static mut CAMERA_POS: Vec3<f32> = Vec3{x: 0.0f32, y: 0.0, z: 0.0};

static WIN_SIZE: Vec2<uint> = Vec2{x: 640, y: 480};
static VERTICES_COUNT: i32 = 3 * 2;

static VERTEX_DATA: [GLfloat, ..VERTICES_COUNT * 3] = [
   0.0,  1.0, 0.0,
   2.0, -1.0, 0.0,
  -2.0, -1.0, 0.0,

  0.0,  1.0,  0.0,
  0.0, -1.0,  2.0,
  0.0, -1.0, -2.0
];

static VERTEX_SHADER_SRC: &'static str = "
  #version 130
  in vec3 position;
  uniform mat4 model_view_proj_matrix;
  void main() {
    vec4 v = vec4(position, 1);
    gl_Position = model_view_proj_matrix * v;
  }
";

static FRAGMENT_SHADER_SRC: &'static str = "
  #version 130
  out vec4 out_color;
  void main() {
    out_color = vec4(1.0, 1.0, 1.0, 1.0);
  }
";

fn compile_shader(src: &str, ty: GLenum) -> GLuint {
  let shader = gl::CreateShader(ty);
  unsafe {
    // Attempt to compile the shader
    gl::ShaderSource(shader, 1, &src.to_c_str().unwrap(), std::ptr::null());
    gl::CompileShader(shader);

    // Get the compile status
    let mut status = gl::FALSE as GLint;
    gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);

    // Fail on error
    if status != (gl::TRUE as GLint) {
      let mut len = 0;
      gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
      // subtract 1 to skip the trailing null character
      let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
      gl::GetShaderInfoLog(shader, len, std::ptr::mut_null(),
        std::vec::raw::to_mut_ptr(buf) as *mut GLchar
      );
      fail!("compile_shader(): " + std::str::raw::from_utf8(buf));
    }
  }
  shader
}

fn link_program(vertex_shader: GLuint, fragment_shader: GLuint) -> GLuint {
  let program = gl::CreateProgram();
  gl::AttachShader(program, vertex_shader);
  gl::AttachShader(program, fragment_shader);
  gl::LinkProgram(program);
  unsafe {
    // Get the link status
    let mut status = gl::FALSE as GLint;
    gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);

    // Fail on error
    if status != (gl::TRUE as GLint) {
      let mut len: GLint = 0;
      gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
      // subtract 1 to skip the trailing null character
      let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
      gl::GetProgramInfoLog(program, len, std::ptr::mut_null(),
        std::vec::raw::to_mut_ptr(buf) as *mut GLchar
      );
      fail!("link_program(): " + std::str::raw::from_utf8(buf));
    }
  }
  program
}

fn tr(m: Mat4<f32>, v: Vec3<f32>) -> Mat4<f32> {
  let mut t = Mat4::<f32>::identity();
  *t.mut_cr(3, 0) = v.x;
  *t.mut_cr(3, 1) = v.y;
  *t.mut_cr(3, 2) = v.z;
  m.mul_m(&t)
}

fn rot_x(m: Mat4<f32>, angle: f32) -> Mat4<f32> {
  let r = Mat3::from_angle_x(angle::rad(angle)).to_mat4();
  m.mul_m(&r)
}

fn rot_y(m: Mat4<f32>, angle: f32) -> Mat4<f32> {
  let r = Mat3::from_angle_y(angle::rad(angle)).to_mat4();
  m.mul_m(&r)
}

struct Win {
  vertex_shader: GLuint,
  fragment_shader: GLuint,
  program: GLuint,
  vertex_array_obj: GLuint,
  vertex_buffer_obj: GLuint,
  matrix_id: GLint,
  window: glfw::Window
}

impl Win {
  fn new() -> Win {
    // TODO: Move to opengl_init method
    // glfw::window_hint::context_version(3, 2);

    let mut win =  Win{
      vertex_shader: 0,
      fragment_shader: 0,
      program: 0,
      vertex_array_obj: 0,
      vertex_buffer_obj: 0,
      matrix_id: 0,
      window: glfw::Window::create(
        WIN_SIZE.x,
        WIN_SIZE.y,
        "OpenGL",
        glfw::Windowed
      ).unwrap()
    };

    win.window.make_context_current();
    win.window.set_cursor_pos_callback(~CursorPosContext);
    win.window.set_key_callback(~KeyContext);

    // Load the OpenGL function pointers
    gl::load_with(glfw::get_proc_address);

    // Create GLSL shaders
    win.vertex_shader = compile_shader(
      VERTEX_SHADER_SRC, gl::VERTEX_SHADER);
    win.fragment_shader = compile_shader(
      FRAGMENT_SHADER_SRC, gl::FRAGMENT_SHADER);
    win.program = link_program(win.vertex_shader, win.fragment_shader);

    unsafe {
      // Create Vertex Array Object
      gl::GenVertexArrays(1, &mut win.vertex_array_obj);
      gl::BindVertexArray(win.vertex_array_obj);

      // Create a Vertex Buffer Object and copy the vertex data to it
      gl::GenBuffers(1, &mut win.vertex_buffer_obj);
      gl::BindBuffer(gl::ARRAY_BUFFER, win.vertex_buffer_obj);
      let float_size = std::mem::size_of::<GLfloat>();
      let vertices_ptr = (VERTEX_DATA.len() * float_size) as GLsizeiptr;
      gl::BufferData(
        gl::ARRAY_BUFFER,
        vertices_ptr,
        std::cast::transmute(&VERTEX_DATA[0]),
        gl::STATIC_DRAW
      );

      gl::UseProgram(win.program);
      gl::BindFragDataLocation(win.program, 0, "out_color".to_c_str().unwrap());

      // Specify the layout of the vertex data
      let pos_attr = gl::GetAttribLocation(
        win.program, "position".to_c_str().unwrap()) as GLuint;
      gl::EnableVertexAttribArray(pos_attr);
      let size = 3;
      let normalized = gl::FALSE as GLboolean;
      let stride = 0;
      gl::VertexAttribPointer(
        pos_attr,
        size,
        gl::FLOAT,
        normalized,
        stride,
        std::ptr::null()
      );

      // Get a handle for our "model_view_proj_matrix" uniform.
      // Only at initialisation time.
      win.matrix_id = gl::GetUniformLocation(
        win.program, "model_view_proj_matrix".to_c_str().unwrap()
      );
    }

    win
  }

  fn cleanup(&self) {
    // Cleanup
    gl::DeleteProgram(self.program);
    gl::DeleteShader(self.fragment_shader);
    gl::DeleteShader(self.vertex_shader);
    unsafe {
      gl::DeleteBuffers(1, &self.vertex_buffer_obj);
      gl::DeleteVertexArrays(1, &self.vertex_array_obj);
    }
  }

  fn update_matrices(&self) {
    let fov = angle::deg(45.0f32);
    let ratio = 4.0 / 3.0;
    let display_range_min = 0.1;
    let display_range_max = 100.0;
    let projection_matrix = projection::perspective(
      fov, ratio, display_range_min, display_range_max
    );

    let mut mvp_matrix = projection_matrix;
    unsafe {
      mvp_matrix = tr(mvp_matrix, Vec3{x: 0.0f32, y: 0.0, z: -10.0f32});
      mvp_matrix = rot_x(mvp_matrix, MOUSE_POS.y / 100.0);
      mvp_matrix = rot_y(mvp_matrix, MOUSE_POS.x / 100.0);
      mvp_matrix = tr(mvp_matrix, CAMERA_POS);
    }

    unsafe {
      // Send our transformation to the currently bound shader,
      // in the "model_view_proj_matrix" uniform.
      // For each model you render, since the model_view_proj_matrix
      // will be different (at least the M part).
      gl::UniformMatrix4fv(self.matrix_id, 1, gl::FALSE, mvp_matrix.cr(0, 0));
    }
  }

  fn draw(&self) {
    self.update_matrices();

    // Clear the screen to black
    gl::ClearColor(0.3, 0.3, 0.3, 1.0);
    gl::Clear(gl::COLOR_BUFFER_BIT);

    // Draw a triangle from the 3 vertices
    gl::DrawArrays(gl::TRIANGLES, 0, VERTICES_COUNT);

    self.window.swap_buffers();
  }

  fn is_running(&self) -> bool {
    return !self.window.should_close()
  }

  fn process_events(&self) {
    glfw::poll_events();
  }
}

struct CursorPosContext;
impl glfw::CursorPosCallback for CursorPosContext {
  fn call(&self, w: &glfw::Window, xpos: f64, ypos: f64) {
    if w.get_mouse_button(glfw::MouseButtonRight) == glfw::Press {
      // println!("Cursor position: ({}, {})", xpos, ypos);
      unsafe {
        MOUSE_POS.x = xpos as f32;
        MOUSE_POS.y = ypos as f32;
      }
    }
  }
}

struct ErrorContext;
impl glfw::ErrorCallback for ErrorContext {
  fn call(&self, _: glfw::Error, description: ~str) {
    println!("GLFW Error: {:s}", description);
  }
}

struct KeyContext;
impl glfw::KeyCallback for KeyContext {
  fn call(
    &self,
    window: &glfw::Window,
    key:    glfw::Key,
    _:      std::libc::c_int,
    action: glfw::Action,
    _:      glfw::Modifiers
  ) {
    let distance = 1.0;
    match (action, key) {
      (glfw::Press, glfw::KeyEscape) | (glfw::Press, glfw::KeyQ) => {
        window.set_should_close(true)
      }
      (glfw::Press, glfw::KeySpace) => {
        println!("space")
      }
      (glfw::Press, glfw::KeyUp)    => unsafe { CAMERA_POS.y -= distance },
      (glfw::Press, glfw::KeyDown)  => unsafe { CAMERA_POS.y += distance },
      (glfw::Press, glfw::KeyRight) => unsafe { CAMERA_POS.x -= distance },
      (glfw::Press, glfw::KeyLeft)  => unsafe { CAMERA_POS.x += distance },
      _ => {}
    }
  }
}

fn main() {
  glfw::set_error_callback(~ErrorContext);
  do glfw::start {
    let win =  Win::new();
    while win.is_running() {
      win.process_events();
      win.draw();
    }
    win.cleanup();
  }
}

#[start]
fn start(argc: int, argv: **u8) -> int {
  std::rt::start_on_main_thread(argc, argv, main)
}

// vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab:
<|endoftext|>


<commit_before>// https://leetcode.com/problems/construct-smallest-number-from-di-string/
pub fn smallest_number(pattern: String) -> String {
    todo!()
}

fn main() {
    println!("{}", smallest_number("IIIDIDDD".to_string())); // "123549876"
    println!("{}", smallest_number("DDD".to_string())); // "4321"
}
<commit_msg>Update problem 2375<commit_after>// https://leetcode.com/problems/construct-smallest-number-from-di-string/
pub fn smallest_number(pattern: String) -> String {
    todo!()
}

fn main() {
    println!("{}", smallest_number("IIIDIDDD".to_string())); // "123549876"
    println!("{}", smallest_number("DDD".to_string())); // "4321"
    println!("{}", smallest_number("IDIDIDID".to_string())); // "132547698"
    println!("{}", smallest_number("DIDIDIDI".to_string())); // "214365879"
}
<|endoftext|>


<commit_before>// https://leetcode.com/problems/maximum-rows-covered-by-columns/
pub fn maximum_rows(mat: Vec<Vec<i32>>, cols: i32) -> i32 {
    todo!()
}

fn main() {
    println!(
        "{}",
        maximum_rows(
            vec![vec![0, 0, 0], vec![1, 0, 1], vec![0, 1, 1], vec![0, 0, 1]],
            2
        )
    ); // 3
    println!("{}", maximum_rows(vec![vec![1], vec![0]], 1)); // 2
}
<commit_msg>Update problem 2397<commit_after>// https://leetcode.com/problems/maximum-rows-covered-by-columns/
pub fn maximum_rows(mat: Vec<Vec<i32>>, cols: i32) -> i32 {
    todo!()
}

fn main() {
    println!(
        "{}",
        maximum_rows(
            vec![vec![0, 0, 0], vec![1, 0, 1], vec![0, 1, 1], vec![0, 0, 1]],
            2
        )
    ); // 3
    println!(
        "{}",
        maximum_rows(
            vec![
                vec![0, 0, 0],
                vec![1, 0, 1],
                vec![0, 1, 1],
                vec![0, 0, 1],
                vec![1, 1, 1]
            ],
            2
        )
    ); // 3
    println!(
        "{}",
        maximum_rows(
            vec![
                vec![0, 0, 0],
                vec![1, 0, 1],
                vec![0, 1, 1],
                vec![0, 0, 1],
                vec![1, 1, 1]
            ],
            3
        )
    ); // 5
    println!("{}", maximum_rows(vec![vec![1], vec![0]], 1)); // 2
}
<|endoftext|>


<commit_before>use bit_field::BitField;
use enum_set::CLike;
use std::fmt;
use std::mem;

pub enum StackPointer {
    MSP(u32),
    PSP(u32),
}

pub struct PSR {
    pub value: u32,
}

pub trait Apsr {
    fn get_n(&self) -> bool;
    fn set_n(&mut self, result: u32);

    fn get_z(&self) -> bool;
    fn set_z(&mut self, result: u32);

    fn get_c(&self) -> bool;
    fn set_c(&mut self, c: bool);

    fn get_v(&self) -> bool;
    fn set_v(&mut self, v: bool);

    fn get_q(&self) -> bool;
    fn set_q(&mut self, q: bool);
}

pub trait Ipsr {
    fn get_exception_number(&self) -> u8;
    fn set_exception_number(&mut self, exception_number: u8);
}

// Execution Program Status register
//
// A view to PSR register containing the data.
pub trait Epsr {
    fn set_t(&mut self, t: bool);
    fn get_t(&self) -> bool;
}

impl Apsr for PSR {
    fn get_n(&self) -> bool {
        (*self).value.get_bit(31)
    }

    fn set_n(&mut self, result: u32) {
        (*self).value &= 0x7fff_ffff;
        (*self).value |= result & 0x8000_0000;
    }

    fn get_z(&self) -> bool {
        (*self).value.get_bit(30)
    }
    fn set_z(&mut self, result: u32) {
        if result == 0 {
            (*self).value |= 0x4000_0000;
        } else {
            (*self).value &= 0x4000_0000 ^ 0xffff_ffff;
        }
    }

    fn get_c(&self) -> bool {
        (*self).value.get_bit(29)
    }
    fn set_c(&mut self, c: bool) {
        if c {
            (*self).value |= 0x2000_0000;
        } else {
            (*self).value &= 0x2000_0000 ^ 0xffff_ffff;
        }
    }
    fn get_v(&self) -> bool {
        (*self).value.get_bit(28)
    }
    fn set_v(&mut self, v: bool) {
        if v {
            (*self).value |= 0x1000_0000;
        } else {
            (*self).value &= 0x1000_0000 ^ 0xffff_ffff;
        }
    }

    fn get_q(&self) -> bool {
        (*self).value.get_bit(27)
    }
    fn set_q(&mut self, q: bool) {
        (*self).value.set_bit(27, q);
    }
}

impl Epsr for PSR {
    fn get_t(&self) -> bool {
        (*self).value.get_bit(24)
    }
    fn set_t(&mut self, n: bool) {
        (*self).value.set_bit(24, n);
    }
}

impl Ipsr for PSR {
    fn get_exception_number(&self) -> u8 {
        (*self).value.get_bits(0..6) as u8
    }
    fn set_exception_number(&mut self, exception_number: u8) {
        self.value = (self.value & 0xffff_ffc0) | u32::from(exception_number & 0b11_1111);
    }
}

/// TODO: remove Copy to improve performance
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u32)]
pub enum Reg {
    R0,
    R1,
    R2,
    R3,
    R4,
    R5,
    R6,
    R7,
    R8,
    R9,
    R10,
    R11,
    R12,
    SP,
    LR,
    PC,
}

#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u32)]
pub enum SpecialReg {
    APSR,
    IAPSR,
    EAPSR,
    XPSR,
    IPSR,
    EPSR,
    IEPSR,
    MSP,
    PSP,
    PRIMASK,
    CONTROL,
}

impl CLike for Reg {
    fn to_u32(&self) -> u32 {
        *self as u32
    }

    unsafe fn from_u32(v: u32) -> Reg {
        mem::transmute(v)
    }
}

impl Reg {
    pub fn value(self) -> usize {
        match self {
            Reg::R0 => 0,
            Reg::R1 => 1,
            Reg::R2 => 2,
            Reg::R3 => 3,
            Reg::R4 => 4,
            Reg::R5 => 5,
            Reg::R6 => 6,
            Reg::R7 => 7,
            Reg::R8 => 8,
            Reg::R9 => 9,
            Reg::R10 => 10,
            Reg::R11 => 11,
            Reg::R12 => 12,
            Reg::SP => 13,
            Reg::LR => 14,
            Reg::PC => 15,
        }
    }

    pub fn from_u16(n: u16) -> Option<Reg> {
        match n {
            0 => Some(Reg::R0),
            1 => Some(Reg::R1),
            2 => Some(Reg::R2),
            3 => Some(Reg::R3),
            4 => Some(Reg::R4),
            5 => Some(Reg::R5),
            6 => Some(Reg::R6),
            7 => Some(Reg::R7),
            8 => Some(Reg::R8),
            9 => Some(Reg::R9),
            10 => Some(Reg::R10),
            11 => Some(Reg::R11),
            12 => Some(Reg::R12),
            13 => Some(Reg::SP),
            14 => Some(Reg::LR),
            15 => Some(Reg::PC),
            _ => None,
        }
    }
}

impl From<u8> for Reg {
    fn from(value: u8) -> Self {
        match value & 0xf {
            0 => Reg::R0,
            1 => Reg::R1,
            2 => Reg::R2,
            3 => Reg::R3,
            4 => Reg::R4,
            5 => Reg::R5,
            6 => Reg::R6,
            7 => Reg::R7,
            8 => Reg::R8,
            9 => Reg::R9,
            10 => Reg::R10,
            11 => Reg::R11,
            12 => Reg::R12,
            13 => Reg::SP,
            14 => Reg::LR,
            15 => Reg::PC,
            _ => Reg::R0,
        }
    }
}

impl From<u32> for Reg {
    fn from(value: u32) -> Self {
        match value & 0xf {
            0 => Reg::R0,
            1 => Reg::R1,
            2 => Reg::R2,
            3 => Reg::R3,
            4 => Reg::R4,
            5 => Reg::R5,
            6 => Reg::R6,
            7 => Reg::R7,
            8 => Reg::R8,
            9 => Reg::R9,
            10 => Reg::R10,
            11 => Reg::R11,
            12 => Reg::R12,
            13 => Reg::SP,
            14 => Reg::LR,
            15 => Reg::PC,
            _ => Reg::R0,
        }
    }
}

impl From<Reg> for u8 {
    fn from(value: Reg) -> Self {
        match value {
            Reg::R0 => 0,
            Reg::R1 => 1,
            Reg::R2 => 2,
            Reg::R3 => 3,
            Reg::R4 => 4,
            Reg::R5 => 5,
            Reg::R6 => 6,
            Reg::R7 => 7,
            Reg::R8 => 8,
            Reg::R9 => 9,
            Reg::R10 => 10,
            Reg::R11 => 11,
            Reg::R12 => 12,
            Reg::SP => 13,
            Reg::LR => 14,
            Reg::PC => 15,
        }
    }
}

impl From<Reg> for usize {
    fn from(value: Reg) -> Self {
        match value {
            Reg::R0 => 0,
            Reg::R1 => 1,
            Reg::R2 => 2,
            Reg::R3 => 3,
            Reg::R4 => 4,
            Reg::R5 => 5,
            Reg::R6 => 6,
            Reg::R7 => 7,
            Reg::R8 => 8,
            Reg::R9 => 9,
            Reg::R10 => 10,
            Reg::R11 => 11,
            Reg::R12 => 12,
            Reg::SP => 13,
            Reg::LR => 14,
            Reg::PC => 15,
        }
    }
}

impl SpecialReg {
    pub fn from_u16(n: u16) -> Option<SpecialReg> {
        match n {
            0 => Some(SpecialReg::APSR),
            1 => Some(SpecialReg::IAPSR),
            2 => Some(SpecialReg::EAPSR),
            3 => Some(SpecialReg::XPSR),
            5 => Some(SpecialReg::IPSR),
            6 => Some(SpecialReg::EPSR),
            7 => Some(SpecialReg::IEPSR),
            8 => Some(SpecialReg::MSP),
            9 => Some(SpecialReg::PSP),
            16 => Some(SpecialReg::PRIMASK),
            20 => Some(SpecialReg::CONTROL),
            _ => None,
        }
    }
}

impl From<u8> for SpecialReg {
    fn from(value: u8) -> Self {
        match value & 0x1f {
            0 => SpecialReg::APSR,
            1 => SpecialReg::IAPSR,
            2 => SpecialReg::EAPSR,
            3 => SpecialReg::XPSR,
            5 => SpecialReg::IPSR,
            6 => SpecialReg::EPSR,
            7 => SpecialReg::IEPSR,
            8 => SpecialReg::MSP,
            9 => SpecialReg::PSP,
            16 => SpecialReg::PRIMASK,
            20 => SpecialReg::CONTROL,
            _ => SpecialReg::APSR,
        }
    }
}

impl fmt::Display for Reg {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Reg::R0 => write!(f, "r0"),
            Reg::R1 => write!(f, "r1"),
            Reg::R2 => write!(f, "r2"),
            Reg::R3 => write!(f, "r3"),
            Reg::R4 => write!(f, "r4"),
            Reg::R5 => write!(f, "r5"),
            Reg::R6 => write!(f, "r6"),
            Reg::R7 => write!(f, "r7"),
            Reg::R8 => write!(f, "r8"),
            Reg::R9 => write!(f, "r9"),
            Reg::R10 => write!(f, "r10"),
            Reg::R11 => write!(f, "r11"),
            Reg::R12 => write!(f, "r12"),
            Reg::SP => write!(f, "sp"),
            Reg::LR => write!(f, "lr"),
            Reg::PC => write!(f, "pc"),
        }
    }
}

impl fmt::Display for SpecialReg {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            SpecialReg::APSR => write!(f, "APSR"),
            SpecialReg::IAPSR => write!(f, "IAPSR"),
            SpecialReg::EAPSR => write!(f, "EAPSR"),
            SpecialReg::XPSR => write!(f, "XPSR"),
            SpecialReg::IPSR => write!(f, "IPSR"),
            SpecialReg::EPSR => write!(f, "EPSR"),
            SpecialReg::IEPSR => write!(f, "IEPSR"),
            SpecialReg::MSP => write!(f, "MSP"),
            SpecialReg::PSP => write!(f, "PSP"),
            SpecialReg::PRIMASK => write!(f, "PRIMASK"),
            SpecialReg::CONTROL => write!(f, "CONTROL"),
        }
    }
}

pub struct Control {
    pub n_priv: bool,
    pub sp_sel: bool,
}

impl From<Control> for u8 {
    fn from(control: Control) -> Self {
        control.n_priv as u8 + ((control.sp_sel as u8) << 1)
    }
}
<commit_msg>impl fromu16 for Reg: Make it easier to convert values<commit_after>use bit_field::BitField;
use enum_set::CLike;
use std::fmt;
use std::mem;

pub enum StackPointer {
    MSP(u32),
    PSP(u32),
}

pub struct PSR {
    pub value: u32,
}

pub trait Apsr {
    fn get_n(&self) -> bool;
    fn set_n(&mut self, result: u32);

    fn get_z(&self) -> bool;
    fn set_z(&mut self, result: u32);

    fn get_c(&self) -> bool;
    fn set_c(&mut self, c: bool);

    fn get_v(&self) -> bool;
    fn set_v(&mut self, v: bool);

    fn get_q(&self) -> bool;
    fn set_q(&mut self, q: bool);
}

pub trait Ipsr {
    fn get_exception_number(&self) -> u8;
    fn set_exception_number(&mut self, exception_number: u8);
}

// Execution Program Status register
//
// A view to PSR register containing the data.
pub trait Epsr {
    fn set_t(&mut self, t: bool);
    fn get_t(&self) -> bool;
}

impl Apsr for PSR {
    fn get_n(&self) -> bool {
        (*self).value.get_bit(31)
    }

    fn set_n(&mut self, result: u32) {
        (*self).value &= 0x7fff_ffff;
        (*self).value |= result & 0x8000_0000;
    }

    fn get_z(&self) -> bool {
        (*self).value.get_bit(30)
    }
    fn set_z(&mut self, result: u32) {
        if result == 0 {
            (*self).value |= 0x4000_0000;
        } else {
            (*self).value &= 0x4000_0000 ^ 0xffff_ffff;
        }
    }

    fn get_c(&self) -> bool {
        (*self).value.get_bit(29)
    }
    fn set_c(&mut self, c: bool) {
        if c {
            (*self).value |= 0x2000_0000;
        } else {
            (*self).value &= 0x2000_0000 ^ 0xffff_ffff;
        }
    }
    fn get_v(&self) -> bool {
        (*self).value.get_bit(28)
    }
    fn set_v(&mut self, v: bool) {
        if v {
            (*self).value |= 0x1000_0000;
        } else {
            (*self).value &= 0x1000_0000 ^ 0xffff_ffff;
        }
    }

    fn get_q(&self) -> bool {
        (*self).value.get_bit(27)
    }
    fn set_q(&mut self, q: bool) {
        (*self).value.set_bit(27, q);
    }
}

impl Epsr for PSR {
    fn get_t(&self) -> bool {
        (*self).value.get_bit(24)
    }
    fn set_t(&mut self, n: bool) {
        (*self).value.set_bit(24, n);
    }
}

impl Ipsr for PSR {
    fn get_exception_number(&self) -> u8 {
        (*self).value.get_bits(0..6) as u8
    }
    fn set_exception_number(&mut self, exception_number: u8) {
        self.value = (self.value & 0xffff_ffc0) | u32::from(exception_number & 0b11_1111);
    }
}

/// TODO: remove Copy to improve performance
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u32)]
pub enum Reg {
    R0,
    R1,
    R2,
    R3,
    R4,
    R5,
    R6,
    R7,
    R8,
    R9,
    R10,
    R11,
    R12,
    SP,
    LR,
    PC,
}

#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u32)]
pub enum SpecialReg {
    APSR,
    IAPSR,
    EAPSR,
    XPSR,
    IPSR,
    EPSR,
    IEPSR,
    MSP,
    PSP,
    PRIMASK,
    CONTROL,
}

impl CLike for Reg {
    fn to_u32(&self) -> u32 {
        *self as u32
    }

    unsafe fn from_u32(v: u32) -> Reg {
        mem::transmute(v)
    }
}

impl Reg {
    pub fn value(self) -> usize {
        match self {
            Reg::R0 => 0,
            Reg::R1 => 1,
            Reg::R2 => 2,
            Reg::R3 => 3,
            Reg::R4 => 4,
            Reg::R5 => 5,
            Reg::R6 => 6,
            Reg::R7 => 7,
            Reg::R8 => 8,
            Reg::R9 => 9,
            Reg::R10 => 10,
            Reg::R11 => 11,
            Reg::R12 => 12,
            Reg::SP => 13,
            Reg::LR => 14,
            Reg::PC => 15,
        }
    }

    pub fn from_u16(n: u16) -> Option<Reg> {
        match n {
            0 => Some(Reg::R0),
            1 => Some(Reg::R1),
            2 => Some(Reg::R2),
            3 => Some(Reg::R3),
            4 => Some(Reg::R4),
            5 => Some(Reg::R5),
            6 => Some(Reg::R6),
            7 => Some(Reg::R7),
            8 => Some(Reg::R8),
            9 => Some(Reg::R9),
            10 => Some(Reg::R10),
            11 => Some(Reg::R11),
            12 => Some(Reg::R12),
            13 => Some(Reg::SP),
            14 => Some(Reg::LR),
            15 => Some(Reg::PC),
            _ => None,
        }
    }
}

impl From<u8> for Reg {
    fn from(value: u8) -> Self {
        match value & 0xf {
            0 => Reg::R0,
            1 => Reg::R1,
            2 => Reg::R2,
            3 => Reg::R3,
            4 => Reg::R4,
            5 => Reg::R5,
            6 => Reg::R6,
            7 => Reg::R7,
            8 => Reg::R8,
            9 => Reg::R9,
            10 => Reg::R10,
            11 => Reg::R11,
            12 => Reg::R12,
            13 => Reg::SP,
            14 => Reg::LR,
            15 => Reg::PC,
            _ => Reg::R0,
        }
    }
}

impl From<u16> for Reg {
    fn from(value: u16) -> Self {
        match value & 0xf {
            0 => Reg::R0,
            1 => Reg::R1,
            2 => Reg::R2,
            3 => Reg::R3,
            4 => Reg::R4,
            5 => Reg::R5,
            6 => Reg::R6,
            7 => Reg::R7,
            8 => Reg::R8,
            9 => Reg::R9,
            10 => Reg::R10,
            11 => Reg::R11,
            12 => Reg::R12,
            13 => Reg::SP,
            14 => Reg::LR,
            15 => Reg::PC,
            _ => Reg::R0,
        }
    }
}

impl From<u32> for Reg {
    fn from(value: u32) -> Self {
        match value & 0xf {
            0 => Reg::R0,
            1 => Reg::R1,
            2 => Reg::R2,
            3 => Reg::R3,
            4 => Reg::R4,
            5 => Reg::R5,
            6 => Reg::R6,
            7 => Reg::R7,
            8 => Reg::R8,
            9 => Reg::R9,
            10 => Reg::R10,
            11 => Reg::R11,
            12 => Reg::R12,
            13 => Reg::SP,
            14 => Reg::LR,
            15 => Reg::PC,
            _ => Reg::R0,
        }
    }
}

impl From<Reg> for u8 {
    fn from(value: Reg) -> Self {
        match value {
            Reg::R0 => 0,
            Reg::R1 => 1,
            Reg::R2 => 2,
            Reg::R3 => 3,
            Reg::R4 => 4,
            Reg::R5 => 5,
            Reg::R6 => 6,
            Reg::R7 => 7,
            Reg::R8 => 8,
            Reg::R9 => 9,
            Reg::R10 => 10,
            Reg::R11 => 11,
            Reg::R12 => 12,
            Reg::SP => 13,
            Reg::LR => 14,
            Reg::PC => 15,
        }
    }
}

impl From<Reg> for usize {
    fn from(value: Reg) -> Self {
        match value {
            Reg::R0 => 0,
            Reg::R1 => 1,
            Reg::R2 => 2,
            Reg::R3 => 3,
            Reg::R4 => 4,
            Reg::R5 => 5,
            Reg::R6 => 6,
            Reg::R7 => 7,
            Reg::R8 => 8,
            Reg::R9 => 9,
            Reg::R10 => 10,
            Reg::R11 => 11,
            Reg::R12 => 12,
            Reg::SP => 13,
            Reg::LR => 14,
            Reg::PC => 15,
        }
    }
}

impl SpecialReg {
    pub fn from_u16(n: u16) -> Option<SpecialReg> {
        match n {
            0 => Some(SpecialReg::APSR),
            1 => Some(SpecialReg::IAPSR),
            2 => Some(SpecialReg::EAPSR),
            3 => Some(SpecialReg::XPSR),
            5 => Some(SpecialReg::IPSR),
            6 => Some(SpecialReg::EPSR),
            7 => Some(SpecialReg::IEPSR),
            8 => Some(SpecialReg::MSP),
            9 => Some(SpecialReg::PSP),
            16 => Some(SpecialReg::PRIMASK),
            20 => Some(SpecialReg::CONTROL),
            _ => None,
        }
    }
}

impl From<u8> for SpecialReg {
    fn from(value: u8) -> Self {
        match value & 0x1f {
            0 => SpecialReg::APSR,
            1 => SpecialReg::IAPSR,
            2 => SpecialReg::EAPSR,
            3 => SpecialReg::XPSR,
            5 => SpecialReg::IPSR,
            6 => SpecialReg::EPSR,
            7 => SpecialReg::IEPSR,
            8 => SpecialReg::MSP,
            9 => SpecialReg::PSP,
            16 => SpecialReg::PRIMASK,
            20 => SpecialReg::CONTROL,
            _ => SpecialReg::APSR,
        }
    }
}

impl fmt::Display for Reg {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Reg::R0 => write!(f, "r0"),
            Reg::R1 => write!(f, "r1"),
            Reg::R2 => write!(f, "r2"),
            Reg::R3 => write!(f, "r3"),
            Reg::R4 => write!(f, "r4"),
            Reg::R5 => write!(f, "r5"),
            Reg::R6 => write!(f, "r6"),
            Reg::R7 => write!(f, "r7"),
            Reg::R8 => write!(f, "r8"),
            Reg::R9 => write!(f, "r9"),
            Reg::R10 => write!(f, "r10"),
            Reg::R11 => write!(f, "r11"),
            Reg::R12 => write!(f, "r12"),
            Reg::SP => write!(f, "sp"),
            Reg::LR => write!(f, "lr"),
            Reg::PC => write!(f, "pc"),
        }
    }
}

impl fmt::Display for SpecialReg {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            SpecialReg::APSR => write!(f, "APSR"),
            SpecialReg::IAPSR => write!(f, "IAPSR"),
            SpecialReg::EAPSR => write!(f, "EAPSR"),
            SpecialReg::XPSR => write!(f, "XPSR"),
            SpecialReg::IPSR => write!(f, "IPSR"),
            SpecialReg::EPSR => write!(f, "EPSR"),
            SpecialReg::IEPSR => write!(f, "IEPSR"),
            SpecialReg::MSP => write!(f, "MSP"),
            SpecialReg::PSP => write!(f, "PSP"),
            SpecialReg::PRIMASK => write!(f, "PRIMASK"),
            SpecialReg::CONTROL => write!(f, "CONTROL"),
        }
    }
}

pub struct Control {
    pub n_priv: bool,
    pub sp_sel: bool,
}

impl From<Control> for u8 {
    fn from(control: Control) -> Self {
        control.n_priv as u8 + ((control.sp_sel as u8) << 1)
    }
}
<|endoftext|>


<commit_before>use std::mem;
use std::slice;

extern crate libc;
use self::libc::{c_void};

#[repr(C)]
pub struct Array {
    pub data: *const c_void,
    pub len: libc::size_t,
}

use super::convert_to_bng_threaded_vec;
use super::convert_to_lonlat_threaded_vec;
use super::convert_to_osgb36_threaded_vec;
use super::convert_to_etrs89_threaded_vec;
use super::convert_etrs89_to_osgb36_threaded_vec;
use super::convert_etrs89_to_ll_threaded_vec;
use super::convert_osgb36_to_ll_threaded_vec;
use super::convert_osgb36_to_etrs89_threaded_vec;
use super::convert_epsg3857_to_wgs84_threaded_vec;

/// Free memory which Rust has allocated across the FFI boundary (f64 values)
///
/// # Examples
///
/// ```
/// # extern crate libc;
/// let lon_vec: Vec<f64> = vec![-2.0183041005533306];
/// let lat_vec: Vec<f64> = vec![54.589097162646141];
/// let lon_arr = Array {
///     data: lon_vec.as_ptr() as *const libc::c_void,
///     len: lon_vec.len() as libc::size_t,
/// };
/// let lat_arr = Array {
///     data: lat_vec.as_ptr() as *const libc::c_void,
///     len: lat_vec.len() as libc::size_t,
/// };
/// let (eastings, northings) = convert_to_bng_threaded(lon_arr, lat_arr);
/// drop_float_array(eastings, northings);
/// ```
/// An example FFI implementation is available at [Convertbng](https://github.com/urschrei/convertbng/blob/master/convertbng/util.py), specifically in the `_void_array_to_list` function.
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn drop_float_array(lons: Array, lats: Array) {
    if lons.data.is_null() {
        return;
    }
    if lats.data.is_null() {
        return;
    }
    unsafe {
        lons.as_f64_slice();
    }
    unsafe {
        lats.as_f64_slice();
    }
}

// Convert Array to mutable [f64] slice
impl Array {
    pub unsafe fn as_f64_slice(&self) -> &mut [f64] {
        assert!(!self.data.is_null());
        slice::from_raw_parts_mut(self.data as *mut f64, self.len as usize)
    }
}

// Build an Array from &mut[T], so it can be leaked across the FFI boundary
impl<'a, T> From<&'a mut [T]> for Array {
    fn from(sl: &mut [T]) -> Self {
        let array = Array {
            data: sl.as_ptr() as *const libc::c_void,
            len: sl.len() as libc::size_t,
        };
        mem::forget(sl);
        array
    }
}

// Build an Array from a Vec, so it can be leaked across the FFI boundary
impl<T> From<Vec<T>> for Array {
    fn from(vec: Vec<T>) -> Self {
        let array = Array {
            data: vec.as_ptr() as *const libc::c_void,
            len: vec.len() as libc::size_t,
        };
        mem::forget(vec);
        array
    }
}

// Build a Vec from an Array, so it can be dropped
impl From<Array> for Vec<f64> {
    fn from(arr: Array) -> Self {
        unsafe { Vec::from_raw_parts(arr.data as *mut f64, arr.len, arr.len) }
    }
}

/// A threaded, FFI-compatible wrapper for `lonlat_bng::convert_osgb36`
///
/// # Examples
///
/// ```
/// extern crate libc;
/// let lon_vec: Vec<f64> = vec![-2.0183041005533306,
///                              0.95511887434519682,
///                              0.44975855518383501,
///                              -0.096813621191803811,
///                              -0.36807065656416427,
///                              0.63486335458665621];
/// let lat_vec: Vec<f64> = vec![54.589097162646141,
///                              51.560873800587828,
///                              50.431429161121699,
///                              54.535021436247419,
///                              50.839059313135706,
///                              55.412189281234419];
/// let lon_arr = Array {
///     data: lon_vec.as_ptr() as *const libc::c_void,
///     len: lon_vec.len() as libc::size_t,
/// };
/// let lat_arr = Array {
///     data: lat_vec.as_ptr() as *const libc::c_void,
///     len: lat_vec.len() as libc::size_t,
/// };
/// let (eastings, northings) = convert_to_bng_threaded(lon_arr, lat_arr);
/// ```
/// For an FFI implementation, see the code at [Convertbng](https://github.com/urschrei/convertbng/blob/master/convertbng/util.py).
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_to_bng_threaded(longitudes: Array, latitudes: Array) -> (Array, Array) {
    let mut longitudes_v = unsafe { longitudes.as_f64_slice() };
    let mut latitudes_v = unsafe { latitudes.as_f64_slice() };
    convert_to_bng_threaded_vec(&mut longitudes_v, &mut latitudes_v);
    (Array::from(longitudes_v), Array::from(latitudes_v))
}

/// A threaded, FFI-compatible wrapper for [`lonlat_bng::convert_osgb36_to_ll`](fn.convert_osgb36_to_ll.html)
///
/// # Examples
///
/// See [`lonlat_bng::convert_to_bng_threaded`](fn.convert_to_bng_threaded.html)
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_to_lonlat_threaded(eastings: Array, northings: Array) -> (Array, Array) {
    let mut eastings_vec = unsafe { eastings.as_f64_slice() };
    let mut northings_vec = unsafe { northings.as_f64_slice() };
    convert_to_lonlat_threaded_vec(&mut eastings_vec, &mut northings_vec);
    (Array::from(eastings_vec), Array::from(northings_vec))
}

/// A threaded, FFI-compatible wrapper for [`lonlat_bng::convert_osgb36`](fn.convert_osgb36.html)
///
/// # Examples
///
/// See [`lonlat_bng::convert_to_bng_threaded`](fn.convert_to_bng_threaded.html) for examples, substituting f64 vectors
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_to_osgb36_threaded(longitudes: Array,
                                             latitudes: Array)
                                             -> (Array, Array) {
    let mut longitudes_v = unsafe { longitudes.as_f64_slice() };
    let mut latitudes_v = unsafe { latitudes.as_f64_slice() };
    convert_to_osgb36_threaded_vec(&mut longitudes_v, &mut latitudes_v);
    (Array::from(longitudes_v), Array::from(latitudes_v))
}

/// A threaded, FFI-compatible wrapper for [`lonlat_bng::convert_etrs89`](fn.convert_etrs89.html)
///
/// # Examples
///
/// See `lonlat_bng::convert_to_bng_threaded` for examples, substituting f64 vectors
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_to_etrs89_threaded(longitudes: Array,
                                             latitudes: Array)
                                             -> (Array, Array) {
    let mut longitudes_v = unsafe { longitudes.as_f64_slice() };
    let mut latitudes_v = unsafe { latitudes.as_f64_slice() };
    convert_to_etrs89_threaded_vec(&mut longitudes_v, &mut latitudes_v);
    (Array::from(longitudes_v), Array::from(latitudes_v))
}

/// A threaded, FFI-compatible wrapper for [`lonlat_bng::convert_etrs89_to_osgb36`](fn.convert_etrs89_to_osgb36.html)
///
/// # Examples
///
/// See `lonlat_bng::convert_to_bng_threaded` for examples
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_etrs89_to_osgb36_threaded(eastings: Array,
                                                    northings: Array)
                                                    -> (Array, Array) {
    let mut eastings_vec = unsafe { eastings.as_f64_slice() };
    let mut northings_vec = unsafe { northings.as_f64_slice() };
    convert_etrs89_to_osgb36_threaded_vec(&mut eastings_vec, &mut northings_vec);
    (Array::from(eastings_vec), Array::from(northings_vec))
}

/// A threaded, FFI-compatible wrapper for [`lonlat_bng::convert_etrs89_to_ll`](fn.convert_etrs89_to_ll.html)
///
/// # Examples
///
/// See `lonlat_bng::convert_to_bng_threaded` for examples
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_etrs89_to_ll_threaded(eastings: Array,
                                                northings: Array)
                                                -> (Array, Array) {
    let mut eastings_vec = unsafe { eastings.as_f64_slice() };
    let mut northings_vec = unsafe { northings.as_f64_slice() };
    convert_etrs89_to_ll_threaded_vec(&mut eastings_vec, &mut northings_vec);
    (Array::from(eastings_vec), Array::from(northings_vec))
}

/// A threaded, FFI-compatible wrapper for [`lonlat_bng::convert_osgb36_to_ll`](fn.convert_osgb36_to_ll.html)
///
/// # Examples
///
/// See `lonlat_bng::convert_to_bng_threaded` for examples
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_osgb36_to_ll_threaded(eastings: Array,
                                                northings: Array)
                                                -> (Array, Array) {
    let mut eastings_vec = unsafe { eastings.as_f64_slice() };
    let mut northings_vec = unsafe { northings.as_f64_slice() };
    convert_osgb36_to_ll_threaded_vec(&mut eastings_vec, &mut northings_vec);
    (Array::from(eastings_vec), Array::from(northings_vec))
}

/// A threaded, FFI-compatible wrapper for [`lonlat_bng::convert_osgb36_to_etrs89`](fn.convert_osgb36_to_etrs89.html)
///
/// # Examples
///
/// See `lonlat_bng::convert_to_bng_threaded` for examples
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_osgb36_to_etrs89_threaded(eastings: Array,
                                                    northings: Array)
                                                    -> (Array, Array) {
    let mut eastings_vec = unsafe { eastings.as_f64_slice() };
    let mut northings_vec = unsafe { northings.as_f64_slice() };
    convert_osgb36_to_etrs89_threaded_vec(&mut eastings_vec, &mut northings_vec);
    (Array::from(eastings_vec), Array::from(northings_vec))
}

/// A threaded, FFI-compatible wrapper for [`lonlat_bng::convert_epsg3857_to_wgs84`](fn.convert_epsg3857_to_wgs84.html)
///
/// # Examples
///
/// See `lonlat_bng::convert_to_bng_threaded` for examples
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_epsg3857_to_wgs84_threaded(x: Array, y: Array) -> (Array, Array) {
    let mut x_vec = unsafe { x.as_f64_slice() };
    let mut y_vec = unsafe { y.as_f64_slice() };
    convert_epsg3857_to_wgs84_threaded_vec(&mut x_vec, &mut y_vec);
    (Array::from(x_vec), Array::from(y_vec))
}
<commit_msg>Implement From for Array --> &mut[f64]<commit_after>use std::mem;
use std::slice;

extern crate libc;
use self::libc::c_void;

#[repr(C)]
pub struct Array {
    pub data: *const c_void,
    pub len: libc::size_t,
}

use super::convert_to_bng_threaded_vec;
use super::convert_to_lonlat_threaded_vec;
use super::convert_to_osgb36_threaded_vec;
use super::convert_to_etrs89_threaded_vec;
use super::convert_etrs89_to_osgb36_threaded_vec;
use super::convert_etrs89_to_ll_threaded_vec;
use super::convert_osgb36_to_ll_threaded_vec;
use super::convert_osgb36_to_etrs89_threaded_vec;
use super::convert_epsg3857_to_wgs84_threaded_vec;

/// Free memory which Rust has allocated across the FFI boundary (f64 values)
///
/// # Examples
///
/// ```
/// # extern crate libc;
/// let lon_vec: Vec<f64> = vec![-2.0183041005533306];
/// let lat_vec: Vec<f64> = vec![54.589097162646141];
/// let lon_arr = Array {
///     data: lon_vec.as_ptr() as *const libc::c_void,
///     len: lon_vec.len() as libc::size_t,
/// };
/// let lat_arr = Array {
///     data: lat_vec.as_ptr() as *const libc::c_void,
///     len: lat_vec.len() as libc::size_t,
/// };
/// let (eastings, northings) = convert_to_bng_threaded(lon_arr, lat_arr);
/// drop_float_array(eastings, northings);
/// ```
/// An example FFI implementation is available at [Convertbng](https://github.com/urschrei/convertbng/blob/master/convertbng/util.py), specifically in the `_void_array_to_list` function.
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn drop_float_array(lons: Array, lats: Array) {
    if lons.data.is_null() {
        return;
    }
    if lats.data.is_null() {
        return;
    }
    let _: &mut [f64] = lons.into();
    let _: &mut [f64] = lats.into();
}

// Convert Array to mutable [f64] slice
impl Array {
    pub unsafe fn as_f64_slice(&self) -> &mut [f64] {
        assert!(!self.data.is_null());
        slice::from_raw_parts_mut(self.data as *mut f64, self.len as usize)
    }
}

// Build an Array from &mut[T], so it can be leaked across the FFI boundary
impl<'a, T> From<&'a mut [T]> for Array {
    fn from(sl: &mut [T]) -> Self {
        let array = Array {
            data: sl.as_ptr() as *const libc::c_void,
            len: sl.len() as libc::size_t,
        };
        mem::forget(sl);
        array
    }
}

// Build &mut[f64] from an Array, so it can be dropped
impl<'a> From<Array> for &'a mut [f64] {
    fn from(arr: Array) -> Self {
        unsafe { slice::from_raw_parts_mut(arr.data as *mut f64, arr.len) }
    }
}

// Build an Array from a Vec, so it can be leaked across the FFI boundary
impl<T> From<Vec<T>> for Array {
    fn from(vec: Vec<T>) -> Self {
        let array = Array {
            data: vec.as_ptr() as *const libc::c_void,
            len: vec.len() as libc::size_t,
        };
        mem::forget(vec);
        array
    }
}

// Build a Vec from an Array, so it can be dropped
impl From<Array> for Vec<f64> {
    fn from(arr: Array) -> Self {
        unsafe { Vec::from_raw_parts(arr.data as *mut f64, arr.len, arr.len) }
    }
}

/// A threaded, FFI-compatible wrapper for `lonlat_bng::convert_osgb36`
///
/// # Examples
///
/// ```
/// extern crate libc;
/// let lon_vec: Vec<f64> = vec![-2.0183041005533306,
///                              0.95511887434519682,
///                              0.44975855518383501,
///                              -0.096813621191803811,
///                              -0.36807065656416427,
///                              0.63486335458665621];
/// let lat_vec: Vec<f64> = vec![54.589097162646141,
///                              51.560873800587828,
///                              50.431429161121699,
///                              54.535021436247419,
///                              50.839059313135706,
///                              55.412189281234419];
/// let lon_arr = Array {
///     data: lon_vec.as_ptr() as *const libc::c_void,
///     len: lon_vec.len() as libc::size_t,
/// };
/// let lat_arr = Array {
///     data: lat_vec.as_ptr() as *const libc::c_void,
///     len: lat_vec.len() as libc::size_t,
/// };
/// let (eastings, northings) = convert_to_bng_threaded(lon_arr, lat_arr);
/// ```
/// For an FFI implementation, see the code at [Convertbng](https://github.com/urschrei/convertbng/blob/master/convertbng/util.py).
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_to_bng_threaded(longitudes: Array, latitudes: Array) -> (Array, Array) {
    let mut longitudes_v: &mut [f64] = longitudes.into();
    let mut latitudes_v: &mut [f64] = latitudes.into();
    convert_to_bng_threaded_vec(&mut longitudes_v, &mut latitudes_v);
    (Array::from(longitudes_v), Array::from(latitudes_v))
}

/// A threaded, FFI-compatible wrapper for [`lonlat_bng::convert_osgb36_to_ll`](fn.convert_osgb36_to_ll.html)
///
/// # Examples
///
/// See [`lonlat_bng::convert_to_bng_threaded`](fn.convert_to_bng_threaded.html)
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_to_lonlat_threaded(eastings: Array, northings: Array) -> (Array, Array) {
    let mut eastings_vec: &mut [f64] = eastings.into();
    let mut northings_vec: &mut [f64] = northings.into();
    convert_to_lonlat_threaded_vec(&mut eastings_vec, &mut northings_vec);
    (Array::from(eastings_vec), Array::from(northings_vec))
}

/// A threaded, FFI-compatible wrapper for [`lonlat_bng::convert_osgb36`](fn.convert_osgb36.html)
///
/// # Examples
///
/// See [`lonlat_bng::convert_to_bng_threaded`](fn.convert_to_bng_threaded.html) for examples, substituting f64 vectors
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_to_osgb36_threaded(longitudes: Array,
                                             latitudes: Array)
                                             -> (Array, Array) {
    let mut longitudes_v: &mut [f64] = longitudes.into();
    let mut latitudes_v: &mut [f64] = latitudes.into();
    convert_to_osgb36_threaded_vec(&mut longitudes_v, &mut latitudes_v);
    (Array::from(longitudes_v), Array::from(latitudes_v))
}

/// A threaded, FFI-compatible wrapper for [`lonlat_bng::convert_etrs89`](fn.convert_etrs89.html)
///
/// # Examples
///
/// See `lonlat_bng::convert_to_bng_threaded` for examples, substituting f64 vectors
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_to_etrs89_threaded(longitudes: Array,
                                             latitudes: Array)
                                             -> (Array, Array) {
    let mut longitudes_v: &mut [f64] = longitudes.into();
    let mut latitudes_v: &mut [f64] = latitudes.into();
    convert_to_etrs89_threaded_vec(&mut longitudes_v, &mut latitudes_v);
    (Array::from(longitudes_v), Array::from(latitudes_v))
}

/// A threaded, FFI-compatible wrapper for [`lonlat_bng::convert_etrs89_to_osgb36`](fn.convert_etrs89_to_osgb36.html)
///
/// # Examples
///
/// See `lonlat_bng::convert_to_bng_threaded` for examples
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_etrs89_to_osgb36_threaded(eastings: Array,
                                                    northings: Array)
                                                    -> (Array, Array) {
    let mut eastings_vec: &mut [f64] = eastings.into();
    let mut northings_vec: &mut [f64] = northings.into();
    convert_etrs89_to_osgb36_threaded_vec(&mut eastings_vec, &mut northings_vec);
    (Array::from(eastings_vec), Array::from(northings_vec))
}

/// A threaded, FFI-compatible wrapper for [`lonlat_bng::convert_etrs89_to_ll`](fn.convert_etrs89_to_ll.html)
///
/// # Examples
///
/// See `lonlat_bng::convert_to_bng_threaded` for examples
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_etrs89_to_ll_threaded(eastings: Array,
                                                northings: Array)
                                                -> (Array, Array) {
    let mut eastings_vec: &mut [f64] = eastings.into();
    let mut northings_vec: &mut [f64] = northings.into();
    convert_etrs89_to_ll_threaded_vec(&mut eastings_vec, &mut northings_vec);
    (Array::from(eastings_vec), Array::from(northings_vec))
}

/// A threaded, FFI-compatible wrapper for [`lonlat_bng::convert_osgb36_to_ll`](fn.convert_osgb36_to_ll.html)
///
/// # Examples
///
/// See `lonlat_bng::convert_to_bng_threaded` for examples
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_osgb36_to_ll_threaded(eastings: Array,
                                                northings: Array)
                                                -> (Array, Array) {
    let mut eastings_vec: &mut [f64] = eastings.into();
    let mut northings_vec: &mut [f64] = northings.into();
    convert_osgb36_to_ll_threaded_vec(&mut eastings_vec, &mut northings_vec);
    (Array::from(eastings_vec), Array::from(northings_vec))
}

/// A threaded, FFI-compatible wrapper for [`lonlat_bng::convert_osgb36_to_etrs89`](fn.convert_osgb36_to_etrs89.html)
///
/// # Examples
///
/// See `lonlat_bng::convert_to_bng_threaded` for examples
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_osgb36_to_etrs89_threaded(eastings: Array,
                                                    northings: Array)
                                                    -> (Array, Array) {
    let mut eastings_vec: &mut [f64] = eastings.into();
    let mut northings_vec: &mut [f64] = northings.into();
    convert_osgb36_to_etrs89_threaded_vec(&mut eastings_vec, &mut northings_vec);
    (Array::from(eastings_vec), Array::from(northings_vec))
}

/// A threaded, FFI-compatible wrapper for [`lonlat_bng::convert_epsg3857_to_wgs84`](fn.convert_epsg3857_to_wgs84.html)
///
/// # Examples
///
/// See `lonlat_bng::convert_to_bng_threaded` for examples
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_epsg3857_to_wgs84_threaded(x: Array, y: Array) -> (Array, Array) {
    let mut x_vec: &mut [f64] = x.into();
    let mut y_vec: &mut [f64] = y.into();
    convert_epsg3857_to_wgs84_threaded_vec(&mut x_vec, &mut y_vec);
    (Array::from(x_vec), Array::from(y_vec))
}
<|endoftext|>


<commit_before>use pulldown_cmark::{Event, Tag};

#[derive(Debug)]
struct Consumer<'a, I> {
    iter: I,
    buffer: String,
    current: Option<Tag<'a>>,
}

impl<'a, I: Iterator<Item = Event<'a>>> Consumer<'a, I> {
    fn consume(&mut self) -> String {
        while let Some(event) = self.iter.next() {
            debug!("{:?}", event);
            match event {
                Event::Start(tag) => {
                    self.buffer.push_str(&print_start_elem(&tag));
                    self.current = Some(tag);
                }
                Event::End(tag) => self.buffer.push_str(&print_end_elem(&tag)),
                Event::Text(text) => {
                    if let Some(tag) = self.current.clone() {
                        match tag {
                            Tag::Header(_) => {
                                let to_add =
                                    format!("{}\"> {}", name_to_id(&text.to_string()), text);
                                self.buffer.push_str(&to_add)
                            }
                            Tag::Image(_, _) => self.buffer.push_str(&format!(" alt=\"{}\"", text)),
                            _ => self.buffer.push_str(&text),
                        }
                    } else {
                        self.buffer.push_str(&text)
                    }
                }
                Event::Html(content) => self.buffer.push_str(&content.to_string()),
                Event::SoftBreak => self.buffer.push_str(" "),
                elem => warn!("Unhandled type: {:?}", elem),
            }
        }
        self.buffer.clone()
    }
}

fn print_start_elem(tag: &Tag) -> String {
    let result = match tag {
        &Tag::Header(int) => format!("<h{} id=\"", int),
        &Tag::Strong => "".to_string(),
        &Tag::Emphasis => "".to_string(),
        &Tag::Item => "
".to_string(),
        &Tag::List(_) => "
".to_string(),
        &Tag::Paragraph => "
".to_string(),
        &Tag::Image(ref src, _) => format!(" "".to_string(),
        &Tag::CodeBlock(ref lang) => format!("
", lang),
        &Tag::Link(ref href, _) => format!("", href),
        // TODO Handle alignment
        &Tag::Table(_) => "
".to_string(),
        &Tag::TableHead => "
".to_string(),
        &Tag::TableCell => "".to_string(),
        &Tag::TableRow => "
".to_string(),
        tag => {
            warn!("{:?} tag is unimplemented", tag);
            unimplemented!();
        }
    };

    debug!("{:?}", result);
    result
}

fn print_end_elem(tag: &Tag) -> String {
    let result = match tag {
        &Tag::Header(int) => format!("</h{}>\n", int),
        &Tag::Strong => "\n".to_string(),
        &Tag::Emphasis => "\n".to_string(),
        &Tag::Item => "
\n".to_string(),
        &Tag::List(_) => "
\n".to_string(),
        &Tag::Paragraph => "
\n".to_string(),
        &Tag::Image(_, _) => "/>\n".to_string(),
        &Tag::Code => "\n".to_string(),
        &Tag::CodeBlock(_) => "
\n".to_string(),
        &Tag::Link(_, _) => "\n".to_string(),
        // TODO Handle alignment
        &Tag::Table(_) => "
\n".to_string(),
        &Tag::TableHead => "
\n".to_string(),
        &Tag::TableCell => "	\n".to_string(),
        &Tag::TableRow => "
\n".to_string(),
        tag => {
            warn!("{:?} tag is unimplemented", tag);
            unimplemented!();
        }
    };

    debug!("{:?}", result);
    result
}

fn name_to_id(name: &str) -> String {
    name.to_lowercase().replace(" ", "-")
}

pub fn consume<'a, I: Iterator<Item = Event<'a>>>(iter: I) -> String {
    let mut consumer = Consumer {
        iter: iter,
        buffer: String::new(),
        current: None,
    };
    consumer.consume()
}

#[cfg(test)]
mod tests {
    use test_utils;
    #[test]
    fn test_name_to_id() {
        let actual = super::name_to_id("A very lOng name or Heading");
        assert_eq!("a-very-long-name-or-heading", actual);
    }

    #[test]
    fn test_consume() {
        use pulldown_cmark::Parser;
        use pulldown_cmark::OPTION_ENABLE_TABLES;
        use std::fs::File;
        use std::io::Read;

        let mut content = String::new();
        File::open("resources/all_test.md")
            .and_then(|mut x| x.read_to_string(&mut content))
            .unwrap();
        let parser = Parser::new_ext(&content, OPTION_ENABLE_TABLES);

        let actual = super::consume(parser);
        let expected = include_str!("../tests/resources/all_test_raw_good.html");
        test_utils::compare_string_content(expected, &actual);
    }
}
<commit_msg>Fix nested link in headings<commit_after>use pulldown_cmark::{Event, Tag};

#[derive(Debug)]
struct Consumer<'a, I> {
    iter: I,
    buffer: String,
    current: Option<Tag<'a>>,
}

impl<'a, I: Iterator<Item = Event<'a>>> Consumer<'a, I> {
    /// Consume the pull parser to produce the HTML string output
    fn consume(&mut self) -> String {
        while let Some(event) = self.iter.next() {
            debug!("{:?}", event);
            match event {
                Event::Start(tag) => {
                    self.buffer.push_str(&print_start_elem(&tag));
                    self.current = Some(tag);
                }
                Event::End(tag) => self.buffer.push_str(&print_end_elem(&tag)),
                Event::Text(text) => {
                    if let Some(tag) = self.current.clone() {
                        match tag {
                            // Add the ID
                            Tag::Header(_) => {
                                let to_add =
                                    format!(" id=\"{}\"> {}", name_to_id(&text.to_string()), text);
                                self.buffer.pop();
                                self.buffer.push_str(&to_add)
                            }
                            Tag::Image(_, _) => self.buffer.push_str(&format!(" alt=\"{}\"", text)),
                            _ => self.buffer.push_str(&text),
                        }
                    } else {
                        self.buffer.push_str(&text)
                    }
                }
                Event::Html(content) => self.buffer.push_str(&content.to_string()),
                Event::SoftBreak => self.buffer.push_str(" "),
                elem => warn!("Unhandled type: {:?}", elem),
            }
        }
        self.buffer.clone()
    }
}

/// Mapping of opening Markdown tag to HTML tag
fn print_start_elem(tag: &Tag) -> String {
    let result = match tag {
        // &Tag::Header(int) => format!("<h{} id=\"", int),
        &Tag::Header(int) => format!("<h{}>", int),
        &Tag::Strong => "".to_string(),
        &Tag::Emphasis => "".to_string(),
        &Tag::Item => "
".to_string(),
        &Tag::List(_) => "
".to_string(),
        &Tag::Paragraph => "
".to_string(),
        &Tag::Image(ref src, _) => format!(" "".to_string(),
        &Tag::CodeBlock(ref lang) => format!("
", lang),
        &Tag::Link(ref href, _) => format!("", href),
        // TODO Handle alignment
        &Tag::Table(_) => "
".to_string(),
        &Tag::TableHead => "
".to_string(),
        &Tag::TableCell => "".to_string(),
        &Tag::TableRow => "
".to_string(),
        &Tag::Rule => "
".to_string(),
        tag => {
            warn!("{:?} tag is unimplemented", tag);
            unimplemented!();
        }
    };

    debug!("{:?}", result);
    result
}

/// Mapping of closing Markdown tag to HTML tag
fn print_end_elem(tag: &Tag) -> String {
    let result = match tag {
        &Tag::Header(int) => format!("</h{}>\n", int),
        &Tag::Strong => "\n".to_string(),
        &Tag::Emphasis => "\n".to_string(),
        &Tag::Item => "
\n".to_string(),
        &Tag::List(_) => "
\n".to_string(),
        &Tag::Paragraph => "
\n".to_string(),
        &Tag::Image(_, _) => "/>\n".to_string(),
        &Tag::Code => "\n".to_string(),
        &Tag::CodeBlock(_) => "
\n".to_string(),
        &Tag::Link(_, _) => "\n".to_string(),
        // TODO Handle alignment
        &Tag::Table(_) => "
\n".to_string(),
        &Tag::TableHead => "
\n".to_string(),
        &Tag::TableCell => "	\n".to_string(),
        &Tag::TableRow => "
\n".to_string(),
        &Tag::Rule => "
".to_string(),
        tag => {
            warn!("{:?} tag is unimplemented", tag);
            unimplemented!();
        }
    };

    debug!("{:?}", result);
    result
}

/// Convert the given string to defined standard for ID
/// * All lower case
/// * Spaces replaces with hyphens
fn name_to_id(name: &str) -> String {
    name.to_lowercase().replace(" ", "-")
}

pub fn consume<'a, I: Iterator<Item = Event<'a>>>(iter: I) -> String {
    let mut consumer = Consumer {
        iter: iter,
        buffer: String::new(),
        current: None,
    };
    consumer.consume()
}

#[cfg(test)]
mod tests {
    use test_utils;
    #[test]
    fn test_name_to_id() {
        let actual = super::name_to_id("A very lOng name or Heading");
        assert_eq!("a-very-long-name-or-heading", actual);
    }

    #[test]
    fn test_consume() {
        use pulldown_cmark::Parser;
        use pulldown_cmark::OPTION_ENABLE_TABLES;
        use std::fs::File;
        use std::io::Read;

        let mut content = String::new();
        File::open("resources/all_test.md")
            .and_then(|mut x| x.read_to_string(&mut content))
            .unwrap();
        let parser = Parser::new_ext(&content, OPTION_ENABLE_TABLES);

        let actual = super::consume(parser);
        let expected = include_str!("../tests/resources/all_test_raw_good.html");
        test_utils::compare_string_content(expected, &actual);
    }
}
<|endoftext|>