<commit_before>//! A (WIP) C API allowing use of gluon in other langauges than Rust.

extern crate gluon;

use std::str;
use std::slice;

use gluon::vm::api::generic::A;
use gluon::vm::api::{Getable, Pushable, Generic, CPrimitive};
use gluon::vm::types::{VMIndex, VMInt};
use gluon::vm::thread::{RootedThread, Thread, ThreadInternal, Status};

use gluon::Compiler;

pub type Function = extern "C" fn(&Thread) -> Status;

// TODO What should the c api return as errors
// TODO How should error messages be returned
#[repr(C)]
#[derive(Debug, PartialEq)]
pub enum Error {
    Ok,
    Unknown,
}

pub extern "C" fn glu_new_vm() -> *const Thread {
    let vm = RootedThread::new();
    vm.into_raw()
}

pub unsafe extern "C" fn glu_free_vm(vm: &Thread) {
    RootedThread::from_raw(vm);
}

pub unsafe extern "C" fn glu_run_expr(vm: &Thread,
                                      module: &u8,
                                      module_len: usize,
                                      expr: &u8,
                                      expr_len: usize)
                                      -> Error {
    let module = match str::from_utf8(slice::from_raw_parts(module, module_len)) {
        Ok(s) => s,
        Err(_) => return Error::Unknown,
    };
    let expr = match str::from_utf8(slice::from_raw_parts(expr, expr_len)) {
        Ok(s) => s,
        Err(_) => return Error::Unknown,
    };
    let result: Result<Generic<A>, _> = Compiler::new().run_expr(&vm, module, expr);
    match result {
        Ok(_) => Error::Ok,
        Err(_) => Error::Unknown,
    }
}

pub unsafe extern "C" fn glu_load_script(vm: &Thread,
                                         module: &u8,
                                         module_len: usize,
                                         expr: &u8,
                                         expr_len: usize)
                                         -> Error {
    let module = match str::from_utf8(slice::from_raw_parts(module, module_len)) {
        Ok(s) => s,
        Err(_) => return Error::Unknown,
    };
    let expr = match str::from_utf8(slice::from_raw_parts(expr, expr_len)) {
        Ok(s) => s,
        Err(_) => return Error::Unknown,
    };
    let result = Compiler::new().load_script(vm, module, expr);
    match result {
        Ok(_) => Error::Ok,
        Err(_) => Error::Unknown,
    }
}

pub extern "C" fn glu_call_function(thread: &Thread, arguments: VMIndex) -> Error {
    let stack = thread.current_frame();
    match thread.call_function(stack, arguments) {
        Ok(_) => Error::Ok,
        Err(_) => Error::Unknown,
    }
}

pub extern "C" fn glu_len(vm: &Thread) -> usize {
    vm.current_frame().len() as usize
}

pub extern "C" fn glu_pop(vm: &Thread, n: usize) {
    let mut stack = vm.current_frame();
    for _ in 0..n {
        stack.pop();
    }
}

pub extern "C" fn glu_push_int(vm: &Thread, int: VMInt) {
    Thread::push(vm, int);
}

pub extern "C" fn glu_push_float(vm: &Thread, float: f64) {
    Thread::push(vm, float);
}

pub unsafe extern "C" fn glu_push_function(vm: &Thread,
                                           name: &u8,
                                           len: usize,
                                           function: Function,
                                           arguments: VMIndex)
                                           -> Error {
    let s = match str::from_utf8(slice::from_raw_parts(name, len)) {
        Ok(s) => s,
        Err(_) => return Error::Unknown,
    };
    Thread::push(vm, CPrimitive::new(function, arguments, s));
    Error::Ok
}

/// Push a string to the stack. The string must be valid utf-8 or an error will be returned
pub unsafe extern "C" fn glu_push_string(vm: &Thread, s: &u8, len: usize) -> Error {
    let s = match str::from_utf8(slice::from_raw_parts(s, len)) {
        Ok(s) => s,
        Err(_) => return Error::Unknown,
    };
    s.push(vm, &mut vm.get_stack());
    Error::Ok
}

/// Push a string to the stack. If the string is not utf-8 this function will trigger undefined
/// behaviour.
pub unsafe extern "C" fn glu_push_string_unchecked(vm: &Thread, s: &u8, len: usize) {
    let s = str::from_utf8_unchecked(slice::from_raw_parts(s, len));
    s.push(vm, &mut vm.get_stack());
}

pub extern "C" fn glu_get_int(vm: &Thread, index: VMIndex, out: &mut VMInt) -> Error {
    get_value(vm, index, out)
}

pub extern "C" fn glu_get_float(vm: &Thread, index: VMIndex, out: &mut f64) -> Error {
    get_value(vm, index, out)
}

/// The returned string is garbage collected and may not be valid after the string is removed from
/// its slot in the stack
pub unsafe extern "C" fn glu_get_string(vm: &Thread,
                                        index: VMIndex,
                                        out: &mut *const u8,
                                        out_len: &mut usize)
                                        -> Error {
    let stack = vm.current_frame();
    match stack.get_variants(index).and_then(|value| <&str>::from_value(vm, value)) {
        Some(value) => {
            *out = &*value.as_ptr();
            *out_len = value.len();
            Error::Ok
        }
        None => Error::Unknown,
    }
}

fn get_value<T>(vm: &Thread, index: VMIndex, out: &mut T) -> Error
    where T: for<'vm> Getable<'vm>
{
    let stack = vm.current_frame();
    match stack.get_variants(index).and_then(|value| T::from_value(vm, value)) {
        Some(value) => {
            *out = value;
            Error::Ok
        }
        None => Error::Unknown,
    }
}

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

    use gluon::vm::thread::{Status, Thread};

    use std::ptr;
    use std::str;
    use std::slice;

    #[test]
    fn push_pop() {
        unsafe {
            let vm = &*glu_new_vm();

            glu_push_int(vm, 123);
            glu_push_float(vm, 3.14);
            let s = "test";
            glu_push_string(vm, &s.as_bytes()[0], s.len());

            let mut int = 0;
            assert_eq!(glu_get_int(vm, 0, &mut int), Error::Ok);
            assert_eq!(int, 123);

            let mut float = 0.0;
            assert_eq!(glu_get_float(vm, 1, &mut float), Error::Ok);
            assert_eq!(float, 3.14);

            let mut string_ptr = ptr::null();
            let mut string_len = 0;
            assert_eq!(glu_get_string(vm, 2, &mut string_ptr, &mut string_len),
                       Error::Ok);
            assert_eq!(str::from_utf8(slice::from_raw_parts(string_ptr, string_len)),
                       Ok("test"));

            assert_eq!(glu_len(vm), 3);

            glu_pop(vm, 3);

            glu_free_vm(vm);
        }
    }

    #[test]
    fn call_function() {
        extern "C" fn mult(vm: &Thread) -> Status {
            let mut l = 0.0;
            assert_eq!(glu_get_float(vm, 0, &mut l), Error::Ok);
            let mut r = 0.0;
            assert_eq!(glu_get_float(vm, 1, &mut r), Error::Ok);
            glu_push_float(vm, l * r);
            Status::Ok
        }

        unsafe {
            let vm = &*glu_new_vm();
            let name = "mult";
            glu_push_function(vm, &name.as_bytes()[0], name.len(), mult, 2);
            glu_push_float(vm, 12.0);
            glu_push_float(vm, 3.0);

            assert_eq!(glu_call_function(vm, 2), Error::Ok);
            let mut result = 0.0;
            assert_eq!(glu_get_float(vm, 0, &mut result), Error::Ok);
            assert_eq!(result, 36.0);

            glu_free_vm(vm);
        }
    }
}
<commit_msg>feat(c-api): Add get and push functions for booleans<commit_after>//! A (WIP) C API allowing use of gluon in other langauges than Rust.

extern crate gluon;

use std::str;
use std::slice;

use gluon::vm::api::generic::A;
use gluon::vm::api::{Getable, Pushable, Generic, CPrimitive};
use gluon::vm::types::{VMIndex, VMInt};
use gluon::vm::thread::{RootedThread, Thread, ThreadInternal, Status};

use gluon::Compiler;

pub type Function = extern "C" fn(&Thread) -> Status;

// TODO What should the c api return as errors
// TODO How should error messages be returned
#[repr(C)]
#[derive(Debug, PartialEq)]
pub enum Error {
    Ok,
    Unknown,
}

pub extern "C" fn glu_new_vm() -> *const Thread {
    let vm = RootedThread::new();
    vm.into_raw()
}

pub unsafe extern "C" fn glu_free_vm(vm: &Thread) {
    RootedThread::from_raw(vm);
}

pub unsafe extern "C" fn glu_run_expr(vm: &Thread,
                                      module: &u8,
                                      module_len: usize,
                                      expr: &u8,
                                      expr_len: usize)
                                      -> Error {
    let module = match str::from_utf8(slice::from_raw_parts(module, module_len)) {
        Ok(s) => s,
        Err(_) => return Error::Unknown,
    };
    let expr = match str::from_utf8(slice::from_raw_parts(expr, expr_len)) {
        Ok(s) => s,
        Err(_) => return Error::Unknown,
    };
    let result: Result<Generic<A>, _> = Compiler::new().run_expr(&vm, module, expr);
    match result {
        Ok(_) => Error::Ok,
        Err(_) => Error::Unknown,
    }
}

pub unsafe extern "C" fn glu_load_script(vm: &Thread,
                                         module: &u8,
                                         module_len: usize,
                                         expr: &u8,
                                         expr_len: usize)
                                         -> Error {
    let module = match str::from_utf8(slice::from_raw_parts(module, module_len)) {
        Ok(s) => s,
        Err(_) => return Error::Unknown,
    };
    let expr = match str::from_utf8(slice::from_raw_parts(expr, expr_len)) {
        Ok(s) => s,
        Err(_) => return Error::Unknown,
    };
    let result = Compiler::new().load_script(vm, module, expr);
    match result {
        Ok(_) => Error::Ok,
        Err(_) => Error::Unknown,
    }
}

pub extern "C" fn glu_call_function(thread: &Thread, arguments: VMIndex) -> Error {
    let stack = thread.current_frame();
    match thread.call_function(stack, arguments) {
        Ok(_) => Error::Ok,
        Err(_) => Error::Unknown,
    }
}

pub extern "C" fn glu_len(vm: &Thread) -> usize {
    vm.current_frame().len() as usize
}

pub extern "C" fn glu_pop(vm: &Thread, n: usize) {
    let mut stack = vm.current_frame();
    for _ in 0..n {
        stack.pop();
    }
}

pub extern "C" fn glu_push_int(vm: &Thread, int: VMInt) {
    Thread::push(vm, int);
}

pub extern "C" fn glu_push_float(vm: &Thread, float: f64) {
    Thread::push(vm, float);
}

pub extern "C" fn glu_push_bool(vm: &Thread, b: i8) {
    Thread::push(vm, b != 0);
}

pub unsafe extern "C" fn glu_push_function(vm: &Thread,
                                           name: &u8,
                                           len: usize,
                                           function: Function,
                                           arguments: VMIndex)
                                           -> Error {
    let s = match str::from_utf8(slice::from_raw_parts(name, len)) {
        Ok(s) => s,
        Err(_) => return Error::Unknown,
    };
    Thread::push(vm, CPrimitive::new(function, arguments, s));
    Error::Ok
}

/// Push a string to the stack. The string must be valid utf-8 or an error will be returned
pub unsafe extern "C" fn glu_push_string(vm: &Thread, s: &u8, len: usize) -> Error {
    let s = match str::from_utf8(slice::from_raw_parts(s, len)) {
        Ok(s) => s,
        Err(_) => return Error::Unknown,
    };
    s.push(vm, &mut vm.get_stack());
    Error::Ok
}

/// Push a string to the stack. If the string is not utf-8 this function will trigger undefined
/// behaviour.
pub unsafe extern "C" fn glu_push_string_unchecked(vm: &Thread, s: &u8, len: usize) {
    let s = str::from_utf8_unchecked(slice::from_raw_parts(s, len));
    s.push(vm, &mut vm.get_stack());
}

pub extern "C" fn glu_get_int(vm: &Thread, index: VMIndex, out: &mut VMInt) -> Error {
    get_value(vm, index, out)
}

pub extern "C" fn glu_get_float(vm: &Thread, index: VMIndex, out: &mut f64) -> Error {
    get_value(vm, index, out)
}

pub extern "C" fn glu_get_bool(vm: &Thread, index: VMIndex, out: &mut i8) -> Error {
    let mut b = false;
    let err = get_value(vm, index, &mut b);
    if err == Error::Ok {
        *out = b as i8;
    }
    err
}

/// The returned string is garbage collected and may not be valid after the string is removed from
/// its slot in the stack
pub unsafe extern "C" fn glu_get_string(vm: &Thread,
                                        index: VMIndex,
                                        out: &mut *const u8,
                                        out_len: &mut usize)
                                        -> Error {
    let stack = vm.current_frame();
    match stack.get_variants(index).and_then(|value| <&str>::from_value(vm, value)) {
        Some(value) => {
            *out = &*value.as_ptr();
            *out_len = value.len();
            Error::Ok
        }
        None => Error::Unknown,
    }
}

fn get_value<T>(vm: &Thread, index: VMIndex, out: &mut T) -> Error
    where T: for<'vm> Getable<'vm>
{
    let stack = vm.current_frame();
    match stack.get_variants(index).and_then(|value| T::from_value(vm, value)) {
        Some(value) => {
            *out = value;
            Error::Ok
        }
        None => Error::Unknown,
    }
}

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

    use gluon::vm::thread::{Status, Thread};

    use std::ptr;
    use std::str;
    use std::slice;

    #[test]
    fn push_pop() {
        unsafe {
            let vm = &*glu_new_vm();

            glu_push_int(vm, 123);
            glu_push_float(vm, 3.14);
            let s = "test";
            glu_push_string(vm, &s.as_bytes()[0], s.len());
            glu_push_bool(vm, 1);

            let mut int = 0;
            assert_eq!(glu_get_int(vm, 0, &mut int), Error::Ok);
            assert_eq!(int, 123);

            let mut float = 0.0;
            assert_eq!(glu_get_float(vm, 1, &mut float), Error::Ok);
            assert_eq!(float, 3.14);

            let mut string_ptr = ptr::null();
            let mut string_len = 0;
            assert_eq!(glu_get_string(vm, 2, &mut string_ptr, &mut string_len),
                       Error::Ok);
            assert_eq!(str::from_utf8(slice::from_raw_parts(string_ptr, string_len)),
                       Ok("test"));

            let mut b = 0;
            assert_eq!(glu_get_bool(vm, 3, &mut b), Error::Ok);
            assert_eq!(b, 1);

            assert_eq!(glu_len(vm), 4);

            glu_pop(vm, 4);

            glu_free_vm(vm);
        }
    }

    #[test]
    fn call_function() {
        extern "C" fn mult(vm: &Thread) -> Status {
            let mut l = 0.0;
            assert_eq!(glu_get_float(vm, 0, &mut l), Error::Ok);
            let mut r = 0.0;
            assert_eq!(glu_get_float(vm, 1, &mut r), Error::Ok);
            glu_push_float(vm, l * r);
            Status::Ok
        }

        unsafe {
            let vm = &*glu_new_vm();
            let name = "mult";
            glu_push_function(vm, &name.as_bytes()[0], name.len(), mult, 2);
            glu_push_float(vm, 12.0);
            glu_push_float(vm, 3.0);

            assert_eq!(glu_call_function(vm, 2), Error::Ok);
            let mut result = 0.0;
            assert_eq!(glu_get_float(vm, 0, &mut result), Error::Ok);
            assert_eq!(result, 36.0);

            glu_free_vm(vm);
        }
    }
}
<|endoftext|>


<commit_before>extern crate pkg_config;

use std::env;
use std::fs::{self, File};
use std::io::ErrorKind;
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use std::process::Command;

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(n) => n,
        Err(e) => fail(&format!("\n{} failed with {}\n", stringify!($e), e)),
    })
}

fn main() {
    register_dep("SSH2");
    register_dep("OPENSSL");

    if env::var("LIBSSH2_SYS_USE_PKG_CONFIG").is_ok() {
        if pkg_config::find_library("libgit2").is_ok() {
            return
        }
    }

    let mut cflags = env::var("CFLAGS").unwrap_or(String::new());
    let target = env::var("TARGET").unwrap();
    let mingw = target.contains("windows-gnu");
    let msvc = target.contains("msvc");

    if msvc {
        // libgit2 passes the /GL flag to enable whole program optimization, but
        // this requires that the /LTCG flag is passed to the linker later on,
        // and currently the compiler does not do that, so we disable whole
        // program optimization entirely.
        cflags.push_str(" /GL-");
    } else {
        cflags.push_str(" -ffunction-sections -fdata-sections");

        if target.contains("i686") {
            cflags.push_str(" -m32");
        } else if target.contains("x86_64") {
            cflags.push_str(" -m64");
        }
        if !target.contains("i686") {
            cflags.push_str(" -fPIC");
        }
    }

    // libgit2 uses pkg-config to discover libssh2, but this doesn't work on
    // windows as libssh2 doesn't come with a libssh2.pc file in that install.
    // As a result we just manually turn on SSH support in libgit2 (a little
    // jankily) here...
    if mingw {
        cflags.push_str(" -DGIT_SSH");
        let libssh2_root = env::var("DEP_SSH2_ROOT").unwrap();
        cflags.push_str(&format!(" -I{}/include", libssh2_root));
    } else if msvc {
        cflags.push_str(" /DGIT_SSH");
        let libssh2_root = env::var("DEP_SSH2_ROOT").unwrap();
        cflags.push_str(&format!(" /I{}\\include", libssh2_root));
    }

    let src = PathBuf::from(&env::var("CARGO_MANIFEST_DIR").unwrap());
    let dst = PathBuf::from(&env::var("OUT_DIR").unwrap());
    let _ = fs::create_dir(&dst.join("build"));

    let mut cmd = Command::new("cmake");
    cmd.arg(&src.join("libgit2"))
       .current_dir(&dst.join("build"));
    if mingw {
        cmd.arg("-G").arg("Unix Makefiles");
    } else if msvc {
        // If we don't pass this unfortunately cmake produces 32-bit builds
        cmd.arg("-G").arg("Visual Studio 12 2013 Win64");

        // Currently liblibc links to msvcrt which apparently is a dynamic CRT,
        // so we need to turn this off to get it to link right.
        cmd.arg("-DSTATIC_CRT=OFF");
    }
    let profile = match &env::var("PROFILE").unwrap()[..] {
        "bench" | "release" => "Release",
        _ if msvc => "Release", // currently we need to always use the same CRT
        _ => "Debug",
    };
    run(cmd.arg("-DBUILD_SHARED_LIBS=OFF")
           .arg("-DBUILD_CLAR=OFF")
           .arg(&format!("-DCMAKE_BUILD_TYPE={}", profile))
           .arg(&format!("-DCMAKE_INSTALL_PREFIX={}", dst.display()))
           .arg(&format!("-DCMAKE_C_FLAGS={}", cflags)), "cmake");

    let flags = dst.join("build/CMakeFiles/git2.dir/flags.make");
    let mut contents = String::new();

    // Make sure libssh2 was detected on unix systems, because it definitely
    // should have been!
    if !msvc {
        t!(t!(File::open(flags)).read_to_string(&mut contents));
        if !contents.contains("-DGIT_SSH") {
            fail("libgit2 failed to find libssh2, and SSH support is required");
        }
    }

    run(Command::new("cmake")
                .arg("--build").arg(".")
                .arg("--target").arg("install")
                .arg("--config").arg(profile)
                .current_dir(&dst.join("build")), "cmake");

    println!("cargo:root={}", dst.display());
    if mingw || target.contains("windows") {
        println!("cargo:rustc-flags=-l winhttp -l rpcrt4 -l ole32 \
                                    -l static=git2");
        println!("cargo:rustc-link-search=native={}/lib", dst.display());
        return
    }

    if env::var("HOST") == env::var("TARGET") {
        prepend("PKG_CONFIG_PATH", dst.join("lib/pkgconfig"));
        if pkg_config::Config::new().statik(true).find("libgit2").is_ok() {
            return
        }
    }

    println!("cargo:rustc-flags=-l static=git2");
    println!("cargo:rustc-flags=-L {}", dst.join("lib").display());
    if target.contains("apple") {
        println!("cargo:rustc-flags=-l iconv");
    }
}

fn run(cmd: &mut Command, program: &str) {
    println!("running: {:?}", cmd);
    let status = match cmd.status() {
        Ok(status) => status,
        Err(ref e) if e.kind() == ErrorKind::NotFound => {
            fail(&format!("failed to execute command: {}\nis `{}` not installed?",
                          e, program));
        }
        Err(e) => fail(&format!("failed to execute command: {}", e)),
    };
    if !status.success() {
        fail(&format!("command did not execute successfully, got: {}", status));
    }
}

fn register_dep(dep: &str) {
    match env::var(&format!("DEP_{}_ROOT", dep)) {
        Ok(s) => {
            prepend("CMAKE_PREFIX_PATH", PathBuf::from(&s));
            prepend("PKG_CONFIG_PATH", Path::new(&s).join("lib/pkgconfig"));
        }
        Err(..) => {}
    }
}

fn prepend(var: &str, val: PathBuf) {
    let prefix = env::var(var).unwrap_or(String::new());
    let mut v = vec![val];
    v.extend(env::split_paths(&prefix));
    env::set_var(var, &env::join_paths(v).unwrap());
}

fn fail(s: &str) -> ! {
    panic!("\n{}\n\nbuild script failed, must exit now", s)
}
<commit_msg>Use DEP_SSH2_INCLUDE instead of ROOT<commit_after>extern crate pkg_config;

use std::env;
use std::fs::{self, File};
use std::io::ErrorKind;
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use std::process::Command;

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(n) => n,
        Err(e) => fail(&format!("\n{} failed with {}\n", stringify!($e), e)),
    })
}

fn main() {
    register_dep("SSH2");
    register_dep("OPENSSL");

    if env::var("LIBSSH2_SYS_USE_PKG_CONFIG").is_ok() {
        if pkg_config::find_library("libgit2").is_ok() {
            return
        }
    }

    let mut cflags = env::var("CFLAGS").unwrap_or(String::new());
    let target = env::var("TARGET").unwrap();
    let mingw = target.contains("windows-gnu");
    let msvc = target.contains("msvc");

    if msvc {
        // libgit2 passes the /GL flag to enable whole program optimization, but
        // this requires that the /LTCG flag is passed to the linker later on,
        // and currently the compiler does not do that, so we disable whole
        // program optimization entirely.
        cflags.push_str(" /GL-");
    } else {
        cflags.push_str(" -ffunction-sections -fdata-sections");

        if target.contains("i686") {
            cflags.push_str(" -m32");
        } else if target.contains("x86_64") {
            cflags.push_str(" -m64");
        }
        if !target.contains("i686") {
            cflags.push_str(" -fPIC");
        }
    }

    // libgit2 uses pkg-config to discover libssh2, but this doesn't work on
    // windows as libssh2 doesn't come with a libssh2.pc file in that install.
    // As a result we just manually turn on SSH support in libgit2 (a little
    // jankily) here...
    if mingw {
        cflags.push_str(" -DGIT_SSH");
    } else if msvc {
        cflags.push_str(" /DGIT_SSH");
    }
    if let Ok(libssh2_include) = env::var("DEP_SSH2_INCLUDE") {
        if mingw {
            cflags.push_str(&format!(" -I{}", libssh2_include));
        } else if msvc {
            cflags.push_str(&format!(" /I{}", libssh2_include));
        }
    }

    let src = PathBuf::from(&env::var("CARGO_MANIFEST_DIR").unwrap());
    let dst = PathBuf::from(&env::var("OUT_DIR").unwrap());
    let _ = fs::create_dir(&dst.join("build"));

    let mut cmd = Command::new("cmake");
    cmd.arg(&src.join("libgit2"))
       .current_dir(&dst.join("build"));
    if mingw {
        cmd.arg("-G").arg("Unix Makefiles");
    } else if msvc {
        // If we don't pass this unfortunately cmake produces 32-bit builds
        cmd.arg("-G").arg("Visual Studio 12 2013 Win64");

        // Currently liblibc links to msvcrt which apparently is a dynamic CRT,
        // so we need to turn this off to get it to link right.
        cmd.arg("-DSTATIC_CRT=OFF");
    }
    let profile = match &env::var("PROFILE").unwrap()[..] {
        "bench" | "release" => "Release",
        _ if msvc => "Release", // currently we need to always use the same CRT
        _ => "Debug",
    };
    run(cmd.arg("-DBUILD_SHARED_LIBS=OFF")
           .arg("-DBUILD_CLAR=OFF")
           .arg(&format!("-DCMAKE_BUILD_TYPE={}", profile))
           .arg(&format!("-DCMAKE_INSTALL_PREFIX={}", dst.display()))
           .arg(&format!("-DCMAKE_C_FLAGS={}", cflags)), "cmake");

    let flags = dst.join("build/CMakeFiles/git2.dir/flags.make");
    let mut contents = String::new();

    // Make sure libssh2 was detected on unix systems, because it definitely
    // should have been!
    if !msvc {
        t!(t!(File::open(flags)).read_to_string(&mut contents));
        if !contents.contains("-DGIT_SSH") {
            fail("libgit2 failed to find libssh2, and SSH support is required");
        }
    }

    run(Command::new("cmake")
                .arg("--build").arg(".")
                .arg("--target").arg("install")
                .arg("--config").arg(profile)
                .current_dir(&dst.join("build")), "cmake");

    println!("cargo:root={}", dst.display());
    if mingw || target.contains("windows") {
        println!("cargo:rustc-flags=-l winhttp -l rpcrt4 -l ole32 \
                                    -l static=git2");
        println!("cargo:rustc-link-search=native={}/lib", dst.display());
        return
    }

    if env::var("HOST") == env::var("TARGET") {
        prepend("PKG_CONFIG_PATH", dst.join("lib/pkgconfig"));
        if pkg_config::Config::new().statik(true).find("libgit2").is_ok() {
            return
        }
    }

    println!("cargo:rustc-flags=-l static=git2");
    println!("cargo:rustc-flags=-L {}", dst.join("lib").display());
    if target.contains("apple") {
        println!("cargo:rustc-flags=-l iconv");
    }
}

fn run(cmd: &mut Command, program: &str) {
    println!("running: {:?}", cmd);
    let status = match cmd.status() {
        Ok(status) => status,
        Err(ref e) if e.kind() == ErrorKind::NotFound => {
            fail(&format!("failed to execute command: {}\nis `{}` not installed?",
                          e, program));
        }
        Err(e) => fail(&format!("failed to execute command: {}", e)),
    };
    if !status.success() {
        fail(&format!("command did not execute successfully, got: {}", status));
    }
}

fn register_dep(dep: &str) {
    match env::var(&format!("DEP_{}_ROOT", dep)) {
        Ok(s) => {
            prepend("CMAKE_PREFIX_PATH", PathBuf::from(&s));
            prepend("PKG_CONFIG_PATH", Path::new(&s).join("lib/pkgconfig"));
        }
        Err(..) => {}
    }
}

fn prepend(var: &str, val: PathBuf) {
    let prefix = env::var(var).unwrap_or(String::new());
    let mut v = vec![val];
    v.extend(env::split_paths(&prefix));
    env::set_var(var, &env::join_paths(v).unwrap());
}

fn fail(s: &str) -> ! {
    panic!("\n{}\n\nbuild script failed, must exit now", s)
}
<|endoftext|>


<commit_before>//! A Netherrack buffer backed by a VecDeque\<u8\>

use std::collections::VecDeque;

extern crate varint;
use self::varint::{Varint, encode_unsigned_varint32};

extern crate bit_utils;
use self::bit_utils::BitInformation;

/// A buffer that is backed by a VecDeque\<u8\>
pub struct DequeBuffer {

    pub data: VecDeque<u8>

}

impl DequeBuffer {

    /// Creates a DequeBuffer from a VecDeque
    ///
    /// After this method, we own the VecDeque
    pub fn from(deque: VecDeque<u8>) -> DequeBuffer {
        DequeBuffer { data: deque }
    }

    /// Creates a new empty DequeBuffer
    pub fn new() -> DequeBuffer {
        DequeBuffer { data: VecDeque::<u8>::new() }
    }

    /// Creates a new empty DequeBuffer with the specified initial capacity
    pub fn with_capacity(capacity: usize) -> DequeBuffer {
        DequeBuffer { data: VecDeque::<u8>::with_capacity(capacity) }
    }

    /// Gets the remaining bytes in this DequeBuffer
    pub fn remaining(&self) -> usize {
        self.data.len()
    }

    /// Reads a UTF-8 string from the buffer
    pub fn read_utf8_string(&mut self) -> String {
        let size_result = self.read_unsigned_varint_32();

        if size_result.is_err() {
            return String::from("!!!BAD_SIZE!!!");
        } else {
            let mut size: u32 = size_result.unwrap();

            let mut bytes: Vec<u8> = Vec::<u8>::with_capacity(size as usize);

            while size > 0 {
                bytes.push(self.read_unsigned_byte());
                size -= 1;
            }

            let result = String::from_utf8(bytes);

            if result.is_ok() {
                return result.unwrap();
            } else {
                return String::from("!!!INVALID_UTF8!!!");
            }

        }
    }

    /// Writes a UTF-8 string into the buffer
    pub fn write_utf8_string(&mut self, value: String) {

        let mut bytes = value.as_bytes();

        self.write_unsigned_varint_32(bytes.len() as u32);

        info!("Length is {}", bytes.len() as u32);

        for &byte in bytes {
            self.write_unsigned_byte(byte);
        }

    }

    /// Reads an unsigned byte from the buffer, returning 0 if no data is available
    pub fn read_unsigned_byte(&mut self) -> u8 {
        match self.data.pop_front() {
            Some(value) => value,
            None => 0
        }
    }

    /// Reads an unsigned byte from the buffer, returning -127 if no data is available
    pub fn read_signed_byte(&mut self) -> i8 {
        match self.data.pop_front() {
            Some(value) => value as i8,
            None => -127
        }
    }

    /// Reads an unsigned short from the buffer
    pub fn read_unsigned_short(&mut self) -> u16 {

        let high: u8 = self.read_unsigned_byte();
        let low: u8 = self.read_unsigned_byte();

        ((high as u16) << 8) | low as u16

    }

    /// Writes an unsigned byte to the buffer
    pub fn write_unsigned_byte(&mut self, value: u8) {
        self.data.push_back(value);
    }

    /// Writes a signed byte to the buffer
    pub fn write_signed_byte(&mut self, value: i8) {
        self.data.push_back(value as u8);
    }

    /// Writes a signed varint 32 to the buffer
    pub fn write_signed_varint_32(&mut self, value: i32) {

        self.write_unsigned_varint_32(self::varint::zigzag_signed_int(value));

    }

    /// Writes an unsigned 32-bit Varint from the buffer
    pub fn write_unsigned_varint_32(&mut self, value: u32) {

        let mut varint = encode_unsigned_varint32(150);

        info!("Varint has {} bytes", varint.number_of_bytes());

        info!("Was {:?}", varint.data);

        //TODO: Once stable, do: self.data.append(&mut varint.data);

        while (varint.data.len() > 0) {

            match varint.data.pop_front() {
                Some(value) => {
                    self.data.push_back(value);
                }
                None => {
                    error!("No data left in Varint's buffer");
                }
            }

        }

        info!("Is now {:?}", self.data);

        /*if value == 0 {
            self.write_unsigned_byte(0);
        } else {

            while _value >= 0b10000000 {

                debug!("Value is {}, writing {}", (_value & 0xff) as u8, _value as u8);

                let next_byte: u8 = ((_value & 0b01111111) as u8) | 0b10000000;

                _value = _value >> 7;

                self.write_unsigned_byte(next_byte);

            }

            debug!("Writing last byte of value: {} is {}", _value, _value & 0b01111111);
            self.write_unsigned_byte((_value & 0b01111111) as u8);

        }*/

    }

    /// Reads an unsigned Varint from the buffer
    pub fn read_unsigned_varint_32(&mut self) -> Result<u32, &'static str> {
        if self.remaining() == 0 {
            return Err("Cannot read a Varint with no data to read.");
        } else {
            // The number of bits to shift by. <<0, <<7, <<14, etc
            let mut shift_amount: u32 = 0;

            // The decoded value
            let mut decoded_value: u32 = 0;

            while self.remaining() >= 1 {

                let byte_value: u8 = self.read_unsigned_byte(); //Yay for this existing!

                decoded_value |= ((byte_value & 0b01111111) as u32) << shift_amount; // We're not shifting for the first byte ;)

                // See if we're still reading bytes
                if byte_value.has_most_signifigant_bit() {
                    shift_amount += 7;
                } else {
                    return Ok(decoded_value);
                }

            }

            return Err("Reached end of buffer while reading a varint32");

        }
    }

}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn new_contains_no_elements() {
        let new = DequeBuffer::new();

        assert_eq!(0, new.remaining());
    }

    #[test]
    fn new_with_capacity_contains_no_elements() {
        let new = DequeBuffer::with_capacity(25000); //WOW, MUCH BIG PACKET

        assert_eq!(0, new.remaining());
    }

    #[test]
    fn unsigned_byte() {
        let mut buffer = DequeBuffer::with_capacity(2);

        buffer.write_unsigned_byte(1);
        buffer.write_unsigned_byte(15);

        assert_eq!(2, buffer.remaining());

        assert_eq!(1, buffer.read_unsigned_byte());
        assert_eq!(15, buffer.read_unsigned_byte());
    }

    #[test]
    fn signed_byte() {
        let mut buffer = DequeBuffer::with_capacity(2);

        buffer.write_signed_byte(-50);
        buffer.write_signed_byte(0);

        assert_eq!(2, buffer.remaining());

        assert_eq!(-50, buffer.read_signed_byte());
        assert_eq!(-0, buffer.read_signed_byte());
    }

    #[test]
    fn unsigned_varint_32() {

        let mut buffer = DequeBuffer::new();

        let var1: u32 = 0;

        let var2: u32 = 4003254234;

        let var3: u32 = 200;

        buffer.write_unsigned_varint_32(var1);
        buffer.write_unsigned_varint_32(var2);
        buffer.write_unsigned_varint_32(var3);

        assert_eq!(8, buffer.remaining());

        // No need to check for okay here, we know it will be. If you're getting it from the client, always check!
        assert_eq!(var1, buffer.read_unsigned_varint_32().unwrap());
        assert_eq!(var2, buffer.read_unsigned_varint_32().unwrap());
        assert_eq!(var3, buffer.read_unsigned_varint_32().unwrap());

    }

}<commit_msg>Revert "Use Varint for writing varints. Need to fix the reference encoding in that crate"<commit_after>//! A Netherrack buffer backed by a VecDeque\<u8\>

use std::collections::VecDeque;

extern crate varint;

extern crate bit_utils;
use self::bit_utils::BitInformation;

/// A buffer that is backed by a VecDeque\<u8\>
pub struct DequeBuffer {

    pub data: VecDeque<u8>

}

impl DequeBuffer {

    /// Creates a DequeBuffer from a VecDeque
    ///
    /// After this method, we own the VecDeque
    pub fn from(deque: VecDeque<u8>) -> DequeBuffer {
        DequeBuffer { data: deque }
    }

    /// Creates a new empty DequeBuffer
    pub fn new() -> DequeBuffer {
        DequeBuffer { data: VecDeque::<u8>::new() }
    }

    /// Creates a new empty DequeBuffer with the specified initial capacity
    pub fn with_capacity(capacity: usize) -> DequeBuffer {
        DequeBuffer { data: VecDeque::<u8>::with_capacity(capacity) }
    }

    /// Gets the remaining bytes in this DequeBuffer
    pub fn remaining(&self) -> usize {
        self.data.len()
    }

    /// Reads a UTF-8 string from the buffer
    pub fn read_utf8_string(&mut self) -> String {
        let size_result = self.read_unsigned_varint_32();

        if size_result.is_err() {
            return String::from("!!!BAD_SIZE!!!");
        } else {
            let mut size: u32 = size_result.unwrap();

            let mut bytes: Vec<u8> = Vec::<u8>::with_capacity(size as usize);

            while size > 0 {
                bytes.push(self.read_unsigned_byte());
                size -= 1;
            }

            let result = String::from_utf8(bytes);

            if result.is_ok() {
                return result.unwrap();
            } else {
                return String::from("!!!INVALID_UTF8!!!");
            }

        }
    }

    /// Writes a UTF-8 string into the buffer
    pub fn write_utf8_string(&mut self, value: String) {

        let mut bytes = value.as_bytes();

        self.write_unsigned_varint_32(bytes.len() as u32);

        info!("Length is {}", bytes.len() as u32);

        for &byte in bytes {
            self.write_unsigned_byte(byte);
        }

    }

    /// Reads an unsigned byte from the buffer, returning 0 if no data is available
    pub fn read_unsigned_byte(&mut self) -> u8 {
        match self.data.pop_front() {
            Some(value) => value,
            None => 0
        }
    }

    /// Reads an unsigned byte from the buffer, returning -127 if no data is available
    pub fn read_signed_byte(&mut self) -> i8 {
        match self.data.pop_front() {
            Some(value) => value as i8,
            None => -127
        }
    }

    /// Reads an unsigned short from the buffer
    pub fn read_unsigned_short(&mut self) -> u16 {

        let high: u8 = self.read_unsigned_byte();
        let low: u8 = self.read_unsigned_byte();

        ((high as u16) << 8) | low as u16

    }

    /// Writes an unsigned byte to the buffer
    pub fn write_unsigned_byte(&mut self, value: u8) {
        self.data.push_back(value);
    }

    /// Writes a signed byte to the buffer
    pub fn write_signed_byte(&mut self, value: i8) {
        self.data.push_back(value as u8);
    }

    /// Writes a signed varint 32 to the buffer
    pub fn write_signed_varint_32(&mut self, value: i32) {

        self.write_unsigned_varint_32(self::varint::zigzag_signed_int(value));

    }

    /// Writes an unsigned 32-bit Varint from the buffer
    pub fn write_unsigned_varint_32(&mut self, value: u32) {

        let mut _value: u32 = value;

        if value == 0 {
            self.write_unsigned_byte(0);
        } else {

            while _value >= 0b10000000 {

                debug!("Value is {}, writing {}", (_value & 0xff) as u8, _value as u8);

                let next_byte: u8 = ((_value & 0b01111111) as u8) | 0b10000000;

                _value = _value >> 7;

                self.write_unsigned_byte(next_byte);

            }

            debug!("Writing last byte of value: {} is {}", _value, _value & 0b01111111);
            self.write_unsigned_byte((_value & 0b01111111) as u8);

        }

    }

    /// Reads an unsigned Varint from the buffer
    pub fn read_unsigned_varint_32(&mut self) -> Result<u32, &'static str> {
        if self.remaining() == 0 {
            return Err("Cannot read a Varint with no data to read.");
        } else {
            // The number of bits to shift by. <<0, <<7, <<14, etc
            let mut shift_amount: u32 = 0;

            // The decoded value
            let mut decoded_value: u32 = 0;

            while self.remaining() >= 1 {

                let byte_value: u8 = self.read_unsigned_byte(); //Yay for this existing!

                decoded_value |= ((byte_value & 0b01111111) as u32) << shift_amount; // We're not shifting for the first byte ;)

                // See if we're still reading bytes
                if byte_value.has_most_signifigant_bit() {
                    shift_amount += 7;
                } else {
                    return Ok(decoded_value);
                }

            }

            return Err("Reached end of buffer while reading a varint32");

        }
    }

}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn new_contains_no_elements() {
        let new = DequeBuffer::new();

        assert_eq!(0, new.remaining());
    }

    #[test]
    fn new_with_capacity_contains_no_elements() {
        let new = DequeBuffer::with_capacity(25000); //WOW, MUCH BIG PACKET

        assert_eq!(0, new.remaining());
    }

    #[test]
    fn unsigned_byte() {
        let mut buffer = DequeBuffer::with_capacity(2);

        buffer.write_unsigned_byte(1);
        buffer.write_unsigned_byte(15);

        assert_eq!(2, buffer.remaining());

        assert_eq!(1, buffer.read_unsigned_byte());
        assert_eq!(15, buffer.read_unsigned_byte());
    }

    #[test]
    fn signed_byte() {
        let mut buffer = DequeBuffer::with_capacity(2);

        buffer.write_signed_byte(-50);
        buffer.write_signed_byte(0);

        assert_eq!(2, buffer.remaining());

        assert_eq!(-50, buffer.read_signed_byte());
        assert_eq!(-0, buffer.read_signed_byte());
    }

    #[test]
    fn unsigned_varint_32() {

        let mut buffer = DequeBuffer::new();

        let var1: u32 = 0;

        let var2: u32 = 4003254234;

        let var3: u32 = 200;

        buffer.write_unsigned_varint_32(var1);
        buffer.write_unsigned_varint_32(var2);
        buffer.write_unsigned_varint_32(var3);

        assert_eq!(8, buffer.remaining());

        // No need to check for okay here, we know it will be. If you're getting it from the client, always check!
        assert_eq!(var1, buffer.read_unsigned_varint_32().unwrap());
        assert_eq!(var2, buffer.read_unsigned_varint_32().unwrap());
        assert_eq!(var3, buffer.read_unsigned_varint_32().unwrap());

    }

}<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use schema::*;

use rustc::hir::def_id::{DefId, DefIndex};
use std::io::{Cursor, Write};
use std::slice;
use std::u32;

/// While we are generating the metadata, we also track the position
/// of each DefIndex. It is not required that all definitions appear
/// in the metadata, nor that they are serialized in order, and
/// therefore we first allocate the vector here and fill it with
/// `u32::MAX`. Whenever an index is visited, we fill in the
/// appropriate spot by calling `record_position`. We should never
/// visit the same index twice.
pub struct Index {
    positions: Vec<u32>,
}

impl Index {
    pub fn new(max_index: usize) -> Index {
        Index { positions: vec![u32::MAX; max_index] }
    }

    pub fn record(&mut self, def_id: DefId, entry: Lazy<Entry>) {
        assert!(def_id.is_local());
        self.record_index(def_id.index, entry);
    }

    pub fn record_index(&mut self, item: DefIndex, entry: Lazy<Entry>) {
        let item = item.as_usize();

        assert!(entry.position < (u32::MAX as usize));
        let position = entry.position as u32;

        assert!(self.positions[item] == u32::MAX,
                "recorded position for item {:?} twice, first at {:?} and now at {:?}",
                item,
                self.positions[item],
                position);

        self.positions[item] = position.to_le();
    }

    pub fn write_index(&self, buf: &mut Cursor<Vec<u8>>) -> LazySeq<Index> {
        let pos = buf.position();
        buf.write_all(words_to_bytes(&self.positions)).unwrap();
        LazySeq::with_position_and_length(pos as usize, self.positions.len())
    }
}

impl<'tcx> LazySeq<Index> {
    /// Given the metadata, extract out the offset of a particular
    /// DefIndex (if any).
    #[inline(never)]
    pub fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option<Lazy<Entry<'tcx>>> {
        let words = &bytes_to_words(&bytes[self.position..])[..self.len];
        let index = def_index.as_usize();

        debug!("Index::lookup: index={:?} words.len={:?}",
               index,
               words.len());

        let position = u32::from_le(words[index].get());
        if position == u32::MAX {
            debug!("Index::lookup: position=u32::MAX");
            None
        } else {
            debug!("Index::lookup: position={:?}", position);
            Some(Lazy::with_position(position as usize))
        }
    }

    pub fn iter_enumerated<'a>(&self,
                               bytes: &'a [u8])
                               -> impl Iterator<Item = (DefIndex, Lazy<Entry<'tcx>>)> + 'a {
        let words = &bytes_to_words(&bytes[self.position..])[..self.len];
        words.iter().map(|word| word.get()).enumerate().filter_map(|(index, position)| {
            if position == u32::MAX {
                None
            } else {
                let position = u32::from_le(position) as usize;
                Some((DefIndex::new(index), Lazy::with_position(position)))
            }
        })
    }
}

#[repr(packed)]
#[derive(Copy, Clone)]
struct Unaligned<T>(T);

impl<T> Unaligned<T> {
    fn get(self) -> T { self.0 }
}

fn bytes_to_words(b: &[u8]) -> &[Unaligned<u32>] {
    unsafe { slice::from_raw_parts(b.as_ptr() as *const Unaligned<u32>, b.len() / 4) }
}

fn words_to_bytes(w: &[u32]) -> &[u8] {
    unsafe { slice::from_raw_parts(w.as_ptr() as *const u8, w.len() * 4) }
}
<commit_msg>Fix unaligned load in librustc_metadata::index.<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use schema::*;

use rustc::hir::def_id::{DefId, DefIndex};
use std::io::{Cursor, Write};
use std::slice;
use std::u32;

/// While we are generating the metadata, we also track the position
/// of each DefIndex. It is not required that all definitions appear
/// in the metadata, nor that they are serialized in order, and
/// therefore we first allocate the vector here and fill it with
/// `u32::MAX`. Whenever an index is visited, we fill in the
/// appropriate spot by calling `record_position`. We should never
/// visit the same index twice.
pub struct Index {
    positions: Vec<u32>,
}

impl Index {
    pub fn new(max_index: usize) -> Index {
        Index { positions: vec![u32::MAX; max_index] }
    }

    pub fn record(&mut self, def_id: DefId, entry: Lazy<Entry>) {
        assert!(def_id.is_local());
        self.record_index(def_id.index, entry);
    }

    pub fn record_index(&mut self, item: DefIndex, entry: Lazy<Entry>) {
        let item = item.as_usize();

        assert!(entry.position < (u32::MAX as usize));
        let position = entry.position as u32;

        assert!(self.positions[item] == u32::MAX,
                "recorded position for item {:?} twice, first at {:?} and now at {:?}",
                item,
                self.positions[item],
                position);

        self.positions[item] = position.to_le();
    }

    pub fn write_index(&self, buf: &mut Cursor<Vec<u8>>) -> LazySeq<Index> {
        let pos = buf.position();
        buf.write_all(words_to_bytes(&self.positions)).unwrap();
        LazySeq::with_position_and_length(pos as usize, self.positions.len())
    }
}

impl<'tcx> LazySeq<Index> {
    /// Given the metadata, extract out the offset of a particular
    /// DefIndex (if any).
    #[inline(never)]
    pub fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option<Lazy<Entry<'tcx>>> {
        let words = &bytes_to_words(&bytes[self.position..])[..self.len];
        let index = def_index.as_usize();

        debug!("Index::lookup: index={:?} words.len={:?}",
               index,
               words.len());

        let position = u32::from_le(words[index].get());
        if position == u32::MAX {
            debug!("Index::lookup: position=u32::MAX");
            None
        } else {
            debug!("Index::lookup: position={:?}", position);
            Some(Lazy::with_position(position as usize))
        }
    }

    pub fn iter_enumerated<'a>(&self,
                               bytes: &'a [u8])
                               -> impl Iterator<Item = (DefIndex, Lazy<Entry<'tcx>>)> + 'a {
        let words = &bytes_to_words(&bytes[self.position..])[..self.len];
        words.iter().map(|word| word.get()).enumerate().filter_map(|(index, position)| {
            if position == u32::MAX {
                None
            } else {
                let position = u32::from_le(position) as usize;
                Some((DefIndex::new(index), Lazy::with_position(position)))
            }
        })
    }
}

#[repr(packed)]
#[derive(Copy)]
struct Unaligned<T>(T);

// The derived Clone impl is unsafe for this packed struct since it needs to pass a reference to
// the field to `T::clone`, but this reference may not be properly aligned.
impl<T: Copy> Clone for Unaligned<T> {
    fn clone(&self) -> Self {
        *self
    }
}

impl<T> Unaligned<T> {
    fn get(self) -> T { self.0 }
}

fn bytes_to_words(b: &[u8]) -> &[Unaligned<u32>] {
    unsafe { slice::from_raw_parts(b.as_ptr() as *const Unaligned<u32>, b.len() / 4) }
}

fn words_to_bytes(w: &[u32]) -> &[u8] {
    unsafe { slice::from_raw_parts(w.as_ptr() as *const u8, w.len() * 4) }
}
<|endoftext|>


<commit_before>extern crate ratel;

pub use ratel::*;
pub use ratel::grammar::*;
pub use ratel::parser::parse;
pub use ratel::grammar::OperatorType::*;

fn output_program(input_program: &str) -> String {
    let mut ast = parser::parse(input_program.to_string()).expect("Must compile");
    transformer::transform(&mut ast, transformer::Settings::target_es5());
    codegen::generate_code(ast, true)
}

macro_rules! assert_compile {
    ($string:expr, $expect:expr) => {
        println!("{:?}", output_program($string));
        assert_eq!(output_program($string), $expect.to_string());
    }
}

#[test]
fn convert_const_to_var_in_global_scope() {
    assert_compile!("const pi = 314;", "var pi=314;");
}

#[test]
fn convert_let_to_var_in_global_scope() {
    assert_compile!("let pi = 314;", "var pi=314;");
}

#[test]
fn dont_touch_var_in_global_scope() {
    assert_compile!("var pi = 314;", "var pi=314;");
}

#[test]
fn convert_let_to_var_in_block() {
    let program = "if(true) {
      let pi = 3.14;
    }";

    let expected = "if(!0){var pi=3.14;}";

    assert_compile!(program, expected);
}

<commit_msg>Take ast by reference in tests<commit_after>extern crate ratel;

pub use ratel::*;
pub use ratel::grammar::*;
pub use ratel::parser::parse;
pub use ratel::grammar::OperatorType::*;

fn output_program(input_program: &str) -> String {
    let mut ast = parser::parse(input_program.to_string()).expect("Must compile");
    transformer::transform(&mut ast, transformer::Settings::target_es5());
    codegen::generate_code(&ast, true)
}

macro_rules! assert_compile {
    ($string:expr, $expect:expr) => {
        println!("{:?}", output_program($string));
        assert_eq!(output_program($string), $expect.to_string());
    }
}

#[test]
fn convert_const_to_var_in_global_scope() {
    assert_compile!("const pi = 314;", "var pi=314;");
}

#[test]
fn convert_let_to_var_in_global_scope() {
    assert_compile!("let pi = 314;", "var pi=314;");
}

#[test]
fn dont_touch_var_in_global_scope() {
    assert_compile!("var pi = 314;", "var pi=314;");
}

#[test]
fn convert_let_to_var_in_block() {
    let program = "if(true) {
      let pi = 3.14;
    }";

    let expected = "if(!0){var pi=3.14;}";

    assert_compile!(program, expected);
}

<|endoftext|>


<commit_before>#![feature(track_caller)]
use std::fmt::Debug;

// Helper function to avoid promotion so that this tests "run-time" casts, not CTFE.
// Doesn't make a big difference when running this in Miri, but it means we can compare this
// with the LLVM backend by running `rustc -Zmir-opt-level=0 -Zsaturating-float-casts`.
#[track_caller]
#[inline(never)]
fn assert_eq<T: PartialEq + Debug>(x: T, y: T) {
    assert_eq!(x, y);
}

fn main() {
    // basic arithmetic
    assert_eq(6.0_f32*6.0_f32, 36.0_f32);
    assert_eq(6.0_f64*6.0_f64, 36.0_f64);
    assert_eq(-{5.0_f32}, -5.0_f32);
    assert_eq(-{5.0_f64}, -5.0_f64);
    // infinities, NaN
    assert!((5.0_f32/0.0).is_infinite());
    assert!((5.0_f64/0.0).is_infinite());
    assert!((-5.0_f32).sqrt().is_nan());
    assert!((-5.0_f64).sqrt().is_nan());
    // byte-level transmute
    let x: u64 = unsafe { std::mem::transmute(42.0_f64) };
    let y: f64 = unsafe { std::mem::transmute(x) };
    assert_eq(y, 42.0_f64);
    let x: u32 = unsafe { std::mem::transmute(42.0_f32) };
    let y: f32 = unsafe { std::mem::transmute(x) };
    assert_eq(y, 42.0_f32);

    // f32 <-> int casts
    assert_eq(5.0f32 as u32, 5);
    assert_eq(-5.0f32 as u32, 0);
    assert_eq(5.0f32 as i32, 5);
    assert_eq(-5.0f32 as i32, -5);
    assert_eq(f32::MAX as i32, i32::MAX);
    assert_eq(f32::INFINITY as i32, i32::MAX);
    assert_eq(f32::MAX as u32, u32::MAX);
    assert_eq(f32::INFINITY as u32, u32::MAX);
    assert_eq(f32::MIN as i32, i32::MIN);
    assert_eq(f32::NEG_INFINITY as i32, i32::MIN);
    assert_eq(f32::MIN as u32, 0);
    assert_eq(f32::NEG_INFINITY as u32, 0);
    assert_eq(f32::NAN as i32, 0);
    assert_eq(f32::NAN as u32, 0);
    assert_eq((u32::MAX-127) as f32 as u32, u32::MAX); // rounding loss
    assert_eq((u32::MAX-128) as f32 as u32, u32::MAX-255); // rounding loss
    assert_eq(127i8 as f32, 127.0f32);
    assert_eq(i128::MIN as f32, -170141183460469231731687303715884105728.0f32);
    assert_eq(u128::MAX as f32, f32::INFINITY); // saturation

    // f64 <-> int casts
    assert_eq(5.0f64 as u64, 5);
    assert_eq(-5.0f64 as u64, 0);
    assert_eq(5.0f64 as i64, 5);
    assert_eq(-5.0f64 as i64, -5);
    assert_eq(f64::MAX as i64, i64::MAX);
    assert_eq(f64::INFINITY as i64, i64::MAX);
    assert_eq(f64::MAX as u64, u64::MAX);
    assert_eq(f64::INFINITY as u64, u64::MAX);
    assert_eq(f64::MIN as i64, i64::MIN);
    assert_eq(f64::NEG_INFINITY as i64, i64::MIN);
    assert_eq(f64::MIN as u64, 0);
    assert_eq(f64::NEG_INFINITY as u64, 0);
    assert_eq(f64::NAN as i64, 0);
    assert_eq(f64::NAN as u64, 0);
    assert_eq((u64::MAX-1023) as f64 as u64, u64::MAX); // rounding loss
    assert_eq((u64::MAX-1024) as f64 as u64, u64::MAX-2047); // rounding loss
    assert_eq(u128::MAX as f64 as u128, u128::MAX);
    assert_eq(i16::MIN as f64, -32768.0f64);
    assert_eq(u128::MAX as f64, 340282366920938463463374607431768211455.0f64); // even that fits...

    // f32 <-> f64 casts
    assert_eq(5.0f64 as f32, 5.0f32);
    assert_eq(5.0f32 as f64, 5.0f64);
    assert_eq(f64::MAX as f32, f32::INFINITY);
    assert_eq(f64::MIN as f32, f32::NEG_INFINITY);
    assert_eq(f32::INFINITY as f64, f64::INFINITY);
    assert_eq(f32::NEG_INFINITY as f64, f64::NEG_INFINITY);

    // f32 min/max
    assert_eq((1.0 as f32).max(-1.0), 1.0);
    assert_eq((1.0 as f32).min(-1.0), -1.0);
    assert_eq(f32::NAN.min(9.0), 9.0);
    assert_eq(f32::NAN.max(-9.0), -9.0);
    assert_eq((9.0 as f32).min(f32::NAN), 9.0);
    assert_eq((-9.0 as f32).max(f32::NAN), -9.0);

    // f64 min/max
    assert_eq((1.0 as f64).max(-1.0), 1.0);
    assert_eq((1.0 as f64).min(-1.0), -1.0);
    assert_eq(f64::NAN.min(9.0), 9.0);
    assert_eq(f64::NAN.max(-9.0), -9.0);
    assert_eq((9.0 as f64).min(f64::NAN), 9.0);
    assert_eq((-9.0 as f64).max(f64::NAN), -9.0);

    // f32 copysign
    assert_eq(3.5_f32.copysign(0.42), 3.5_f32);
    assert_eq(3.5_f32.copysign(-0.42), -3.5_f32);
    assert_eq((-3.5_f32).copysign(0.42), 3.5_f32);
    assert_eq((-3.5_f32).copysign(-0.42), -3.5_f32);
    assert!(f32::NAN.copysign(1.0).is_nan());

    // f64 copysign
    assert_eq(3.5_f64.copysign(0.42), 3.5_f64);
    assert_eq(3.5_f64.copysign(-0.42), -3.5_f64);
    assert_eq((-3.5_f64).copysign(0.42), 3.5_f64);
    assert_eq((-3.5_f64).copysign(-0.42), -3.5_f64);
    assert!(f64::NAN.copysign(1.0).is_nan());
}
<commit_msg>a few more inf/nan/negz tests<commit_after>#![feature(track_caller)]
use std::fmt::Debug;

// Helper function to avoid promotion so that this tests "run-time" casts, not CTFE.
// Doesn't make a big difference when running this in Miri, but it means we can compare this
// with the LLVM backend by running `rustc -Zmir-opt-level=0 -Zsaturating-float-casts`.
#[track_caller]
#[inline(never)]
fn assert_eq<T: PartialEq + Debug>(x: T, y: T) {
    assert_eq!(x, y);
}

fn main() {
    // basic arithmetic
    assert_eq(6.0_f32*6.0_f32, 36.0_f32);
    assert_eq(6.0_f64*6.0_f64, 36.0_f64);
    assert_eq(-{5.0_f32}, -5.0_f32);
    assert_eq(-{5.0_f64}, -5.0_f64);
    // infinities, NaN
    assert!((5.0_f32/0.0).is_infinite());
    assert_ne!({5.0_f32/0.0}, {-5.0_f32/0.0});
    assert!((5.0_f64/0.0).is_infinite());
    assert_ne!({5.0_f64/0.0}, {5.0_f64/-0.0});
    assert!((-5.0_f32).sqrt().is_nan());
    assert!((-5.0_f64).sqrt().is_nan());
    assert_ne!(f32::NAN, f32::NAN);
    assert_ne!(f64::NAN, f64::NAN);
    // negative zero
    let posz = 0.0f32;
    let negz = -0.0f32;
    assert_eq(posz, negz);
    assert_ne!(posz.to_bits(), negz.to_bits());
    let posz = 0.0f64;
    let negz = -0.0f64;
    assert_eq(posz, negz);
    assert_ne!(posz.to_bits(), negz.to_bits());
    // byte-level transmute
    let x: u64 = unsafe { std::mem::transmute(42.0_f64) };
    let y: f64 = unsafe { std::mem::transmute(x) };
    assert_eq(y, 42.0_f64);
    let x: u32 = unsafe { std::mem::transmute(42.0_f32) };
    let y: f32 = unsafe { std::mem::transmute(x) };
    assert_eq(y, 42.0_f32);

    // f32 <-> int casts
    assert_eq(5.0f32 as u32, 5);
    assert_eq(-5.0f32 as u32, 0);
    assert_eq(5.0f32 as i32, 5);
    assert_eq(-5.0f32 as i32, -5);
    assert_eq(f32::MAX as i32, i32::MAX);
    assert_eq(f32::INFINITY as i32, i32::MAX);
    assert_eq(f32::MAX as u32, u32::MAX);
    assert_eq(f32::INFINITY as u32, u32::MAX);
    assert_eq(f32::MIN as i32, i32::MIN);
    assert_eq(f32::NEG_INFINITY as i32, i32::MIN);
    assert_eq(f32::MIN as u32, 0);
    assert_eq(f32::NEG_INFINITY as u32, 0);
    assert_eq(f32::NAN as i32, 0);
    assert_eq(f32::NAN as u32, 0);
    assert_eq((u32::MAX-127) as f32 as u32, u32::MAX); // rounding loss
    assert_eq((u32::MAX-128) as f32 as u32, u32::MAX-255); // rounding loss
    assert_eq(127i8 as f32, 127.0f32);
    assert_eq(i128::MIN as f32, -170141183460469231731687303715884105728.0f32);
    assert_eq(u128::MAX as f32, f32::INFINITY); // saturation

    // f64 <-> int casts
    assert_eq(5.0f64 as u64, 5);
    assert_eq(-5.0f64 as u64, 0);
    assert_eq(5.0f64 as i64, 5);
    assert_eq(-5.0f64 as i64, -5);
    assert_eq(f64::MAX as i64, i64::MAX);
    assert_eq(f64::INFINITY as i64, i64::MAX);
    assert_eq(f64::MAX as u64, u64::MAX);
    assert_eq(f64::INFINITY as u64, u64::MAX);
    assert_eq(f64::MIN as i64, i64::MIN);
    assert_eq(f64::NEG_INFINITY as i64, i64::MIN);
    assert_eq(f64::MIN as u64, 0);
    assert_eq(f64::NEG_INFINITY as u64, 0);
    assert_eq(f64::NAN as i64, 0);
    assert_eq(f64::NAN as u64, 0);
    assert_eq((u64::MAX-1023) as f64 as u64, u64::MAX); // rounding loss
    assert_eq((u64::MAX-1024) as f64 as u64, u64::MAX-2047); // rounding loss
    assert_eq(u128::MAX as f64 as u128, u128::MAX);
    assert_eq(i16::MIN as f64, -32768.0f64);
    assert_eq(u128::MAX as f64, 340282366920938463463374607431768211455.0f64); // even that fits...

    // f32 <-> f64 casts
    assert_eq(5.0f64 as f32, 5.0f32);
    assert_eq(5.0f32 as f64, 5.0f64);
    assert_eq(f64::MAX as f32, f32::INFINITY);
    assert_eq(f64::MIN as f32, f32::NEG_INFINITY);
    assert_eq(f32::INFINITY as f64, f64::INFINITY);
    assert_eq(f32::NEG_INFINITY as f64, f64::NEG_INFINITY);

    // f32 min/max
    assert_eq((1.0 as f32).max(-1.0), 1.0);
    assert_eq((1.0 as f32).min(-1.0), -1.0);
    assert_eq(f32::NAN.min(9.0), 9.0);
    assert_eq(f32::NAN.max(-9.0), -9.0);
    assert_eq((9.0 as f32).min(f32::NAN), 9.0);
    assert_eq((-9.0 as f32).max(f32::NAN), -9.0);

    // f64 min/max
    assert_eq((1.0 as f64).max(-1.0), 1.0);
    assert_eq((1.0 as f64).min(-1.0), -1.0);
    assert_eq(f64::NAN.min(9.0), 9.0);
    assert_eq(f64::NAN.max(-9.0), -9.0);
    assert_eq((9.0 as f64).min(f64::NAN), 9.0);
    assert_eq((-9.0 as f64).max(f64::NAN), -9.0);

    // f32 copysign
    assert_eq(3.5_f32.copysign(0.42), 3.5_f32);
    assert_eq(3.5_f32.copysign(-0.42), -3.5_f32);
    assert_eq((-3.5_f32).copysign(0.42), 3.5_f32);
    assert_eq((-3.5_f32).copysign(-0.42), -3.5_f32);
    assert!(f32::NAN.copysign(1.0).is_nan());

    // f64 copysign
    assert_eq(3.5_f64.copysign(0.42), 3.5_f64);
    assert_eq(3.5_f64.copysign(-0.42), -3.5_f64);
    assert_eq((-3.5_f64).copysign(0.42), 3.5_f64);
    assert_eq((-3.5_f64).copysign(-0.42), -3.5_f64);
    assert!(f64::NAN.copysign(1.0).is_nan());
}
<|endoftext|>


<commit_before>pub fn score(string: &str) -> usize {
    string
        .chars()
        .map(|c| match c {
            'A' | 'E' | 'I' | 'O' | 'U' | 'L' | 'N' | 'R' | 'S' | 'T' => 1,
            'a' | 'e' | 'i' | 'o' | 'u' | 'l' | 'n' | 'r' | 's' | 't' => 1,
            'D' | 'G' => 2,
            'd' | 'g' => 2,
            'B' | 'C' | 'M' | 'P' => 3,
            'b' | 'c' | 'm' | 'p' => 3,
            'F' | 'H' | 'V' | 'W' | 'Y' => 4,
            'f' | 'h' | 'v' | 'w' | 'y' => 4,
            'K' => 5,
            'k' => 5,
            'J' | 'X' => 8,
            'j' | 'x' => 8,
            'Q' | 'Z' => 10,
            'q' | 'z' => 10,
            _ => 0,
        })
        .sum()
}
<commit_msg>Use lookup table to simplify code<commit_after>#![feature(ascii_ctype)]
use std::ascii::AsciiExt;

const SCORETABLE: [usize; 26] = [
//  a,  b,  c,  d,  e,  f,  g,  h,  i,  j,  k,  l,  m
    1,  3,  3,  2,  1,  4,  2,  4,  1,  8,  5,  1,  3,
//  n,  o,  p,  q,  r,  s,  t,  u,  v,  w,  x,  y,  z
    1,  1,  3, 10,  1,  1,  1,  1,  4,  4,  8,  4, 10,
];

pub fn score(string: &str) -> usize {
    string
        .chars()
        .map(|c| match c {
            _ if c.is_ascii_uppercase() => SCORETABLE[c as usize - 'A' as usize],
            _ if c.is_ascii_lowercase() => SCORETABLE[c as usize - 'a' as usize],
            _ => 0,
        })
        .sum()
}
<|endoftext|>


<commit_before>extern crate fitsio;
extern crate tempdir;

/* This example docuents the following things:
 *
 * creating a new file
 * writing header keys
 * writing an image into the primary hdu
 * creating a table
 * adding data to a table
 * closing the file
 * re-opening it
 * reading an image region
 * reading some rows from a table column
 */

use std::error::Error;
use tempdir::TempDir;
use fitsio::FitsFile;
use fitsio::fitsfile::ImageDescription;
use fitsio::types::ImageType;
use fitsio::columndescription::{ColumnDataType, ColumnDescription};

fn run() -> Result<(), Box<Error>> {
    /* Create a temporary directory to work from */
    let tmp_dir = TempDir::new("fitsio")?;
    let file_path = tmp_dir.path().join("example.fits");

    // creating a new file with 512 rows and 1024 columns
    let primary_hdu_description = ImageDescription {
        data_type: ImageType::DOUBLE_IMG,
        dimensions: &[512, 1024],
    };

    {
        let mut fitsfile = FitsFile::create(file_path.to_str().unwrap())
            .with_custom_primary(&primary_hdu_description)
            .open()?;

        /* We will now add some dummy header keys. We add:
         * - the name of the project (String)
         * - the exposure time (f32)
         * - the image id (i64)
         */

        /* First we get the primary HDU */
        let hdu = fitsfile.hdu(0)?;

        /* Now we add the header keys */
        hdu.write_key(
            &mut fitsfile,
            "PROJECT",
            "My First Astronomy Project".to_string(),
        )?;

        /* Now the exposure time */
        hdu.write_key(&mut fitsfile, "EXPTIME", 15.2f32)?;

        /* And finally the image id */
        hdu.write_key(&mut fitsfile, "IMAGE_ID", 20180101010005i64)?;

        /* Now we write some dummy data to the primary HDU. We write the full image in this case.
         * */

        let dummy_data: Vec<f32> = (0..(1024 * 512))
            .map(|val| (val as f32) * 12.5 + 102.5)
            .collect();

        hdu.write_image(&mut fitsfile, &dummy_data)?;

        /* We can create a new image with the following */
        let image_description = ImageDescription {
            data_type: ImageType::LONG_IMG,
            dimensions: &[256, 256],
        };
        fitsfile.create_image("IMG".to_string(), &image_description)?;

        /* Now we add a new table HDU called "DATA"
         *
         * We add three columns:
         *
         * 1. Object id (i32)
         * 2. Object name (String, up to 10 characters)
         * 3. Object magnitude (f32)
         * */
        let col1 = ColumnDescription::new("OBJ_ID")
            .with_type(ColumnDataType::Int)
            .create()?;
        let col2 = ColumnDescription::new("NAME")
            .with_type(ColumnDataType::String)
            .that_repeats(10)
            .create()?;
        let col3 = ColumnDescription::new("MAG")
            .with_type(ColumnDataType::Float)
            .create()?;
        let columns = &[col1, col2, col3];
        let table_hdu = fitsfile.create_table("DATA".to_string(), columns)?;

        /* Add some data to the columns */
        let n_rows = 10;
        let obj_id_data: Vec<i32> = (0..n_rows).collect();
        let name_data: Vec<String> = (0..n_rows).map(|idx| format!("N{}", idx)).collect();
        let mag_data: Vec<f32> = (0..n_rows).map(|idx| -0.2 * idx as f32).collect();

        table_hdu.write_col(&mut fitsfile, "OBJ_ID", &obj_id_data)?;
        table_hdu.write_col(&mut fitsfile, "NAME", &name_data)?;
        table_hdu.write_col(&mut fitsfile, "MAG", &mag_data)?;

        /* `fitsfile` is dropped here at the end of the scope, which closes fhe file on disk */
    }

    /* Here we re-open the file. We want to adjust things, so we use the `edit` method */
    let mut fitsfile = FitsFile::edit(file_path.to_str().unwrap())?;

    /* Get the primary HDU and read a section of the image data */

    let phdu = fitsfile.hdu(0)?;

    /* Let's say we have a region around a star that we want to extract. The star is at (25, 25,
     * 1-indexed) and we want to extract a 5x5 box around it. This means we want to read rows 19 to
     * 19, and columns 19 to 29 (0-indexed). The range arguments are exclusive of the upper bound,
     * so we must use 19..29 for each axis.
     *
     * Note: this is not performant, and if this is the desired use of `fitsio`, I would not
     * suggest this approach. */
    let image_data: Vec<f32> = phdu.read_region(&mut fitsfile, &[&(19..29), &(19..29)])?;
    assert_eq!(image_data.len(), 100);

    /* We can now get the column data. Let's assume we want all of the magnitudes for objects near
     * this one (by index). This object is at index 4 (0-indexed) and we want to read one value
     * before and after it. */
    let table_hdu = fitsfile.hdu("DATA")?;
    let magnitudes: Vec<f32> = table_hdu.read_col_range(&mut fitsfile, "MAG", &(3..6))?;
    assert_eq!(magnitudes.len(), 3);

    /* The file is closed when it is dropped here */

    Ok(())
}

fn main() {
    run().unwrap();
}
<commit_msg>Use primary_hdu in full_example<commit_after>extern crate fitsio;
extern crate tempdir;

/* This example docuents the following things:
 *
 * creating a new file
 * writing header keys
 * writing an image into the primary hdu
 * creating a table
 * adding data to a table
 * closing the file
 * re-opening it
 * reading an image region
 * reading some rows from a table column
 */

use std::error::Error;
use tempdir::TempDir;
use fitsio::FitsFile;
use fitsio::fitsfile::ImageDescription;
use fitsio::types::ImageType;
use fitsio::columndescription::{ColumnDataType, ColumnDescription};

fn run() -> Result<(), Box<Error>> {
    /* Create a temporary directory to work from */
    let tmp_dir = TempDir::new("fitsio")?;
    let file_path = tmp_dir.path().join("example.fits");

    // creating a new file with 512 rows and 1024 columns
    let primary_hdu_description = ImageDescription {
        data_type: ImageType::DOUBLE_IMG,
        dimensions: &[512, 1024],
    };

    {
        let mut fitsfile = FitsFile::create(file_path.to_str().unwrap())
            .with_custom_primary(&primary_hdu_description)
            .open()?;

        /* We will now add some dummy header keys. We add:
         * - the name of the project (String)
         * - the exposure time (f32)
         * - the image id (i64)
         */

        /* First we get the primary HDU */
        let hdu = fitsfile.primary_hdu()?;

        /* Now we add the header keys */
        hdu.write_key(
            &mut fitsfile,
            "PROJECT",
            "My First Astronomy Project".to_string(),
        )?;

        /* Now the exposure time */
        hdu.write_key(&mut fitsfile, "EXPTIME", 15.2f32)?;

        /* And finally the image id */
        hdu.write_key(&mut fitsfile, "IMAGE_ID", 20180101010005i64)?;

        /* Now we write some dummy data to the primary HDU. We write the full image in this case.
         * */

        let dummy_data: Vec<f32> = (0..(1024 * 512))
            .map(|val| (val as f32) * 12.5 + 102.5)
            .collect();

        hdu.write_image(&mut fitsfile, &dummy_data)?;

        /* We can create a new image with the following */
        let image_description = ImageDescription {
            data_type: ImageType::LONG_IMG,
            dimensions: &[256, 256],
        };
        fitsfile.create_image("IMG".to_string(), &image_description)?;

        /* Now we add a new table HDU called "DATA"
         *
         * We add three columns:
         *
         * 1. Object id (i32)
         * 2. Object name (String, up to 10 characters)
         * 3. Object magnitude (f32)
         * */
        let col1 = ColumnDescription::new("OBJ_ID")
            .with_type(ColumnDataType::Int)
            .create()?;
        let col2 = ColumnDescription::new("NAME")
            .with_type(ColumnDataType::String)
            .that_repeats(10)
            .create()?;
        let col3 = ColumnDescription::new("MAG")
            .with_type(ColumnDataType::Float)
            .create()?;
        let columns = &[col1, col2, col3];
        let table_hdu = fitsfile.create_table("DATA".to_string(), columns)?;

        /* Add some data to the columns */
        let n_rows = 10;
        let obj_id_data: Vec<i32> = (0..n_rows).collect();
        let name_data: Vec<String> = (0..n_rows).map(|idx| format!("N{}", idx)).collect();
        let mag_data: Vec<f32> = (0..n_rows).map(|idx| -0.2 * idx as f32).collect();

        table_hdu.write_col(&mut fitsfile, "OBJ_ID", &obj_id_data)?;
        table_hdu.write_col(&mut fitsfile, "NAME", &name_data)?;
        table_hdu.write_col(&mut fitsfile, "MAG", &mag_data)?;

        /* `fitsfile` is dropped here at the end of the scope, which closes fhe file on disk */
    }

    /* Here we re-open the file. We want to adjust things, so we use the `edit` method */
    let mut fitsfile = FitsFile::edit(file_path.to_str().unwrap())?;

    /* Get the primary HDU and read a section of the image data */

    let phdu = fitsfile.primary_hdu()?;

    /* Let's say we have a region around a star that we want to extract. The star is at (25, 25,
     * 1-indexed) and we want to extract a 5x5 box around it. This means we want to read rows 19 to
     * 19, and columns 19 to 29 (0-indexed). The range arguments are exclusive of the upper bound,
     * so we must use 19..29 for each axis.
     *
     * Note: this is not performant, and if this is the desired use of `fitsio`, I would not
     * suggest this approach. */
    let image_data: Vec<f32> = phdu.read_region(&mut fitsfile, &[&(19..29), &(19..29)])?;
    assert_eq!(image_data.len(), 100);

    /* We can now get the column data. Let's assume we want all of the magnitudes for objects near
     * this one (by index). This object is at index 4 (0-indexed) and we want to read one value
     * before and after it. */
    let table_hdu = fitsfile.hdu("DATA")?;
    let magnitudes: Vec<f32> = table_hdu.read_col_range(&mut fitsfile, "MAG", &(3..6))?;
    assert_eq!(magnitudes.len(), 3);

    /* The file is closed when it is dropped here */

    Ok(())
}

fn main() {
    run().unwrap();
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate milagro_crypto;
use self::milagro_crypto::randapi::Random;
use self::milagro_crypto::big::wrappers::MODBYTES;
use self::milagro_crypto::ff::FF;
use self::milagro_crypto::hash::wrappers::hash256;
use self::rand::os::OsRng;
use self::rand::Rng;
use services::crypto::constants::{
    BIG_SIZE,
    BN_MASK,
    PRIMES,
    NUM_PRIMES,
    LARGE_PRIME
};
use services::crypto::types::{ByteOrder};

pub fn generate_random_seed() -> [u8; 32] {
    let mut seed: [u8; 32] = [0; 32];
    let mut rng = OsRng::new().unwrap();
    rng.fill_bytes(&mut seed);
    seed
}

pub fn generate_big_random(size: usize) -> FF {
    let seed = generate_random_seed();
    let mut rng = Random::new(seed);

    let b_size: usize = size / 8 + 1; // number of bytes for mod value
    let big_size: usize = (b_size + MODBYTES - 1) / MODBYTES; // number of BIGs for mod value

    // init mod bytes with 0 and set 1 in proper place
    let mut bytes = vec![0; big_size * MODBYTES];
    bytes[big_size * MODBYTES - b_size] = (1 as u8).wrapping_shl((size - (b_size - 1) * 8) as u32);

    let bv = FF::from_bytes(&bytes[0..], big_size * MODBYTES, BIG_SIZE);
    let r = FF::randomnum(&bv, &mut rng);
    r
}

pub fn generate_prime(size: usize) -> FF {
    let seed = generate_random_seed();
    let mut rng = Random::new(seed);
    let mut iteration = 0;
    let mut is_prime = false;

    let mut prime = generate_big_random(size);
    let mut prime_bytes = prime.to_bytes();
    let length = prime_bytes.len();
    let last_byte = prime_bytes[length - 1];
    prime_bytes[length - 1] = last_byte | 3;
    prime = FF::from_bytes(&prime_bytes, length, BIG_SIZE);
    while !is_prime {
        prime.inc(4);
        iteration += 1;
        is_prime = FF::is_prime(&prime, &mut rng);
    }
    debug!("Iteration: {}\nFound prime: {}", iteration, prime);

    prime
}

pub fn generate_prime_2p_plus_1(size: usize) -> FF {
    let seed = generate_random_seed();
    let mut rng = Random::new(seed);
    let (mut is_prime, mut iteration) = (false, 0);
    let mut prime = FF::new(BIG_SIZE);

    while !is_prime {
        iteration += 1;
        prime = generate_prime(size);
        let mut prime_for_check = FF::mul(&prime, &FF::from_hex("2", BIG_SIZE));
        prime_for_check.inc(1);
        is_prime = FF::is_prime(&prime_for_check, &mut rng);
        debug!("Iteration: {}\nFound prime: {}\nis_prime: {}\n", iteration, prime, is_prime);
    }
    prime
}

pub fn random_qr(n: &FF){
    println!("n :{}", n);
    let mut random = random_in_range(&FF::from_hex("0", BIG_SIZE), n);
    println!("random :{}", random);
    random = FF::sqr(&random);
    println!("random sqr :{}", random);
//    let mut nn = n.clone();
//    nn.set_size(32);
//    random.set_size(32);
    let random1 = FF::modulus(&random, &n);
    println!("random1 :{}", random1);
//    let (mut ctx, mut random_qr) = (BigNumContext::new().unwrap(), BigNum::new().unwrap());
//    random_qr.sqr(&AnoncredsService::random_in_range(&BigNum::from_u32(0).unwrap(), &n), &mut ctx);
//    random_qr
}

fn random_in_range(start: &FF, end: &FF) -> FF {
    let sub = end - start;
    let size = significant_bits(&sub);
    let mut random_number = generate_big_random(size);

    while (&random_number + start) > *end {
        random_number = generate_big_random(size);
    }

    random_number = &random_number + start;
    debug!("start: {}\nend: {}\nsub: {}\nrandom: {}", start, end, sub, random_number);
    random_number
}

pub fn encode_attribute(attribute: &str, byte_order: ByteOrder) {
    let array_bytes = attribute.as_bytes();
    let mut sha256: hash256 = hash256::new();
    println!("array_bytes{:?}", array_bytes);
    for byte in array_bytes[..].iter() {
        sha256.process(*byte);
    }

    let mut hashed_array: Vec<u8> =
        sha256.hash().iter()
            .map(|v| *v as u8)
            .collect();

    if let ByteOrder::Little = byte_order {
        hashed_array.reverse();
    }
    println!("hashedarr{:?}", hashed_array);
    let hex = FF::from_bytes(&hashed_array[..], hashed_array.len(), BIG_SIZE);
    println!("asby{}", hex);
    //    let mut result = hash(MessageDigest::sha256(), attribute.as_bytes()).unwrap();
    //    let index = result.iter().position(|&value| value == 0);
    //    if let Some(position) = index {
    //        result.truncate(position);
    //    }
    //    if let ByteOrder::Little = byte_order {
    //        result.reverse();
    //    }
    //    let encoded_attribute = AnoncredsService::transform_byte_array_to_big_integer(&result);
    //    encoded_attribute.to_dec_str().unwrap().to_string()
}

fn significant_bytes(n: &FF) -> Vec<u8> {
    let mut bytes = n.to_bytes();
    let length = bytes.len();
    let index = bytes.iter().position(|&value| value != 0);
    if let Some(index) = index {
        bytes.reverse();
        bytes.truncate(length - index);
        bytes.reverse();
    }
    bytes
}

fn significant_bits(n: &FF) -> usize {
    let bytes = significant_bytes(n);
    let mut result = (bytes.len() - 1) * 8;
    result += format!("{:b}", bytes[0]).len();
    result
}

fn generate_probable_prime(size: usize) {
    let mut random_number = generate_big_random(size);
    let mut mods: Vec<FF> = Vec::new();
    for i in 1..NUM_PRIMES {
        debug!("{}", i);
        let bytes = random_number.to_bytes();
        let mut new_random = FF::from_bytes(&bytes, size, BIG_SIZE);
        let prime = FF::from_hex(&format!("{:x}", PRIMES[i])[..], BIG_SIZE);
        FF::modulus(&mut new_random, &prime);
        mods.push(new_random);
    }
    //TODO loop for mods check
}

pub fn get_hash_as_int(num: FF) -> FF {
    let array_bytes: Vec<u8> = num.to_bytes();

    let index = array_bytes.iter().position(|&value| value != 0).unwrap_or(array_bytes.len());

    let mut sha256: hash256 = hash256::new();

    for byte in array_bytes[index..].iter() {
        sha256.process(*byte);
    }

    let mut hashed_array: Vec<u8> =
        sha256.hash().iter()
            .map(|v| *v as u8)
            .collect();

    hashed_array.reverse();

    FF::from_bytes(&hashed_array[..], hashed_array.len(), 2)
}

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

    #[test]
    fn random_in_range_works() {
        ::env_logger::init().unwrap();

        let start = generate_big_random(100);
        let mut end = generate_big_random(120);

        while end < start {
            end = generate_big_random(30);
        }

        let random = random_in_range(&start, &end);
        assert!((random > start) && (random < end));
    }

    #[test]
    fn test_random_qr() {
//        let n = generate_big_random(10);
//        random_qr(&n);
    }

    #[test]
    fn encode_attribute_works() {
        let test_str_one = "Alexer5435";
        let test_str_two = "Alexer";
        let test_answer_one = "f54a";
        let test_answer_two = "cf76920dae32802476cc5e8d2518fd21c16b5f83e713a684db1aeb7089c67091";
        encode_attribute(test_str_one, ByteOrder::Big);
//        assert_eq!(test_answer_one, AnoncredsService::encode_attribute(test_str_one, ByteOrder::Big));
//        assert_eq!(test_answer_two, AnoncredsService::encode_attribute(test_str_two, ByteOrder::Big));
    }
}<commit_msg>added test for encode attribute<commit_after>extern crate rand;
extern crate milagro_crypto;
use self::milagro_crypto::randapi::Random;
use self::milagro_crypto::big::wrappers::MODBYTES;
use self::milagro_crypto::ff::FF;
use self::milagro_crypto::hash::wrappers::hash256;
use self::rand::os::OsRng;
use self::rand::Rng;
use services::crypto::constants::{
    BIG_SIZE,
    BN_MASK,
    PRIMES,
    NUM_PRIMES,
    LARGE_PRIME
};
use services::crypto::types::{ByteOrder};

pub fn generate_random_seed() -> [u8; 32] {
    let mut seed: [u8; 32] = [0; 32];
    let mut rng = OsRng::new().unwrap();
    rng.fill_bytes(&mut seed);
    seed
}

pub fn generate_big_random(size: usize) -> FF {
    let seed = generate_random_seed();
    let mut rng = Random::new(seed);

    let b_size: usize = size / 8 + 1; // number of bytes for mod value
    let big_size: usize = (b_size + MODBYTES - 1) / MODBYTES; // number of BIGs for mod value

    // init mod bytes with 0 and set 1 in proper place
    let mut bytes = vec![0; big_size * MODBYTES];
    bytes[big_size * MODBYTES - b_size] = (1 as u8).wrapping_shl((size - (b_size - 1) * 8) as u32);

    let bv = FF::from_bytes(&bytes[0..], big_size * MODBYTES, BIG_SIZE);
    let r = FF::randomnum(&bv, &mut rng);
    r
}

pub fn generate_prime(size: usize) -> FF {
    let seed = generate_random_seed();
    let mut rng = Random::new(seed);
    let mut iteration = 0;
    let mut is_prime = false;

    let mut prime = generate_big_random(size);
    let mut prime_bytes = prime.to_bytes();
    let length = prime_bytes.len();
    let last_byte = prime_bytes[length - 1];
    prime_bytes[length - 1] = last_byte | 3;
    prime = FF::from_bytes(&prime_bytes, length, BIG_SIZE);
    while !is_prime {
        prime.inc(4);
        iteration += 1;
        is_prime = FF::is_prime(&prime, &mut rng);
    }
    debug!("Iteration: {}\nFound prime: {}", iteration, prime);

    prime
}

pub fn generate_prime_2p_plus_1(size: usize) -> FF {
    let seed = generate_random_seed();
    let mut rng = Random::new(seed);
    let (mut is_prime, mut iteration) = (false, 0);
    let mut prime = FF::new(BIG_SIZE);

    while !is_prime {
        iteration += 1;
        prime = generate_prime(size);
        let mut prime_for_check = FF::mul(&prime, &FF::from_hex("2", BIG_SIZE));
        prime_for_check.inc(1);
        is_prime = FF::is_prime(&prime_for_check, &mut rng);
        debug!("Iteration: {}\nFound prime: {}\nis_prime: {}\n", iteration, prime, is_prime);
    }
    prime
}

pub fn random_qr(n: &FF){
    println!("n :{}", n);
    let mut random = random_in_range(&FF::from_hex("0", BIG_SIZE), n);
    println!("random :{}", random);
    random = FF::sqr(&random);
    println!("random sqr :{}", random);
//    let mut nn = n.clone();
//    nn.set_size(32);
//    random.set_size(32);
    let random1 = FF::modulus(&random, &n);
    println!("random1 :{}", random1);
//    let (mut ctx, mut random_qr) = (BigNumContext::new().unwrap(), BigNum::new().unwrap());
//    random_qr.sqr(&AnoncredsService::random_in_range(&BigNum::from_u32(0).unwrap(), &n), &mut ctx);
//    random_qr
}

fn random_in_range(start: &FF, end: &FF) -> FF {
    let sub = end - start;
    let size = significant_bits(&sub);
    let mut random_number = generate_big_random(size);

    while (&random_number + start) > *end {
        random_number = generate_big_random(size);
    }

    random_number = &random_number + start;
    debug!("start: {}\nend: {}\nsub: {}\nrandom: {}", start, end, sub, random_number);
    random_number
}

pub fn encode_attribute(attribute: &str, byte_order: ByteOrder) -> FF {
    let array_bytes = attribute.as_bytes();
    let mut sha256: hash256 = hash256::new();

    for byte in array_bytes[..].iter() {
        sha256.process(*byte);
    }

    let mut hashed_array: Vec<u8> =
        sha256.hash().iter()
            .map(|v| *v as u8)
            .collect();

    let index = hashed_array.iter().position(|&value| value == 0);
    if let Some(position) = index {
        hashed_array.truncate(position);
    }

    if let ByteOrder::Little = byte_order {
        hashed_array.reverse();
    }

    if hashed_array.len() < 32 {
        for i in 0..(32 - hashed_array.len()) {
            hashed_array.insert(0, 0);
        }
    }
    FF::from_bytes(&hashed_array, MODBYTES, 32)
}

fn significant_bytes(n: &FF) -> Vec<u8> {
    let mut bytes = n.to_bytes();
    let length = bytes.len();
    let index = bytes.iter().position(|&value| value != 0);
    if let Some(index) = index {
        bytes.reverse();
        bytes.truncate(length - index);
        bytes.reverse();
    }
    bytes
}

fn significant_bits(n: &FF) -> usize {
    let bytes = significant_bytes(n);
    let mut result = (bytes.len() - 1) * 8;
    result += format!("{:b}", bytes[0]).len();
    result
}

fn generate_probable_prime(size: usize) {
    let mut random_number = generate_big_random(size);
    let mut mods: Vec<FF> = Vec::new();
    for i in 1..NUM_PRIMES {
        debug!("{}", i);
        let bytes = random_number.to_bytes();
        let mut new_random = FF::from_bytes(&bytes, size, BIG_SIZE);
        let prime = FF::from_hex(&format!("{:x}", PRIMES[i])[..], BIG_SIZE);
        FF::modulus(&mut new_random, &prime);
        mods.push(new_random);
    }
    //TODO loop for mods check
}

pub fn get_hash_as_int(num: FF) -> FF {
    let array_bytes: Vec<u8> = num.to_bytes();

    let index = array_bytes.iter().position(|&value| value != 0).unwrap_or(array_bytes.len());

    let mut sha256: hash256 = hash256::new();

    for byte in array_bytes[index..].iter() {
        sha256.process(*byte);
    }

    let mut hashed_array: Vec<u8> =
        sha256.hash().iter()
            .map(|v| *v as u8)
            .collect();

    hashed_array.reverse();

    FF::from_bytes(&hashed_array[..], hashed_array.len(), 2)
}

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

    #[test]
    fn random_in_range_works() {
        ::env_logger::init().unwrap();

        let start = generate_big_random(100);
        let mut end = generate_big_random(120);

        while end < start {
            end = generate_big_random(30);
        }

        let random = random_in_range(&start, &end);
        assert!((random > start) && (random < end));
    }

    #[test]
    fn test_random_qr() {
//        let n = generate_big_random(10);
//        random_qr(&n);
    }

    #[test]
    fn encode_attribute_works() {
        let test_str_one = "Alexer5435";
        let test_str_two = "Alexer";
        let test_answer_one = "f54a";
        let test_answer_two = "cf76920dae32802476cc5e8d2518fd21c16b5f83e713a684db1aeb7089c67091";
        assert_eq!(FF::from_hex(test_answer_one, BIG_SIZE), encode_attribute(test_str_one, ByteOrder::Big));
        assert_eq!(FF::from_hex(test_answer_two, BIG_SIZE), encode_attribute(test_str_two, ByteOrder::Big));
    }
}<|endoftext|>