<commit_before>extern crate cargotest;
extern crate hamcrest;

use cargotest::is_nightly;
use cargotest::support::{execs, project};
use hamcrest::assert_that;

#[test]
fn check_success() {
    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#"
            extern crate bar;
            fn main() {
                ::bar::baz();
            }
        "#);
    let bar = project("bar")
        .file("Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.1.0"
            authors = []
        "#)
        .file("src/lib.rs", r#"
            pub fn baz() {}
        "#);
    bar.build();

    let expected = if is_nightly() { 0 } else { 101 };
    assert_that(foo.cargo_process("check"),
                execs().with_status(expected));
}

#[test]
fn check_fail() {
    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#"
            extern crate bar;
            fn main() {
                ::bar::baz(42);
            }
        "#);
    let bar = project("bar")
        .file("Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.1.0"
            authors = []
        "#)
        .file("src/lib.rs", r#"
            pub fn baz() {}
        "#);
    bar.build();

    assert_that(foo.cargo_process("check"),
                execs().with_status(101));
}

#[test]
fn custom_derive() {
    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(proc_macro)]

#[macro_use]
extern crate bar;

trait B {
    fn b(&self);
}

#[derive(B)]
struct A;

fn main() {
    let a = A;
    a.b();
}
"#);
    let bar = project("bar")
        .file("Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.1.0"
            authors = []
            [lib]
            proc-macro = true
        "#)
        .file("src/lib.rs", r#"
#![feature(proc_macro, proc_macro_lib)]
#![crate_type = "proc-macro"]

extern crate proc_macro;

use proc_macro::TokenStream;

#[proc_macro_derive(B)]
pub fn derive(_input: TokenStream) -> TokenStream {
    format!("impl B for A {{ fn b(&self) {{}} }}").parse().unwrap()
}
"#);
    bar.build();

    let expected = if is_nightly() { 0 } else { 101 };
    assert_that(foo.cargo_process("check"),
                execs().with_status(expected));
}

#[test]
fn check_build() {
    if !is_nightly() {
        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#"
            extern crate bar;
            fn main() {
                ::bar::baz();
            }
        "#);
    let bar = project("bar")
        .file("Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.1.0"
            authors = []
        "#)
        .file("src/lib.rs", r#"
            pub fn baz() {}
        "#);
    bar.build();

    assert_that(foo.cargo_process("check"),
                execs().with_status(0));
    assert_that(foo.cargo_process("build"),
                execs().with_status(0));
}

#[test]
fn build_check() {
    if !is_nightly() {
        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#"
            extern crate bar;
            fn main() {
                ::bar::baz();
            }
        "#);
    let bar = project("bar")
        .file("Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.1.0"
            authors = []
        "#)
        .file("src/lib.rs", r#"
            pub fn baz() {}
        "#);
    bar.build();

    assert_that(foo.cargo_process("build"),
                execs().with_status(0));
    assert_that(foo.cargo_process("check"),
                execs().with_status(0));
}
<commit_msg>Auto merge of #3457 - alexcrichton:no-check-on-beta, r=alexcrichton<commit_after>extern crate cargotest;
extern crate hamcrest;

use cargotest::is_nightly;
use cargotest::support::{execs, project};
use hamcrest::assert_that;

#[test]
fn check_success() {
    if !is_nightly() {
        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#"
            extern crate bar;
            fn main() {
                ::bar::baz();
            }
        "#);
    let bar = project("bar")
        .file("Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.1.0"
            authors = []
        "#)
        .file("src/lib.rs", r#"
            pub fn baz() {}
        "#);
    bar.build();

    assert_that(foo.cargo_process("check"),
                execs().with_status(0));
}

#[test]
fn check_fail() {
    if !is_nightly() {
        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#"
            extern crate bar;
            fn main() {
                ::bar::baz(42);
            }
        "#);
    let bar = project("bar")
        .file("Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.1.0"
            authors = []
        "#)
        .file("src/lib.rs", r#"
            pub fn baz() {}
        "#);
    bar.build();

    assert_that(foo.cargo_process("check"),
                execs().with_status(101));
}

#[test]
fn custom_derive() {
    if !is_nightly() {
        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(proc_macro)]

#[macro_use]
extern crate bar;

trait B {
    fn b(&self);
}

#[derive(B)]
struct A;

fn main() {
    let a = A;
    a.b();
}
"#);
    let bar = project("bar")
        .file("Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.1.0"
            authors = []
            [lib]
            proc-macro = true
        "#)
        .file("src/lib.rs", r#"
#![feature(proc_macro, proc_macro_lib)]
#![crate_type = "proc-macro"]

extern crate proc_macro;

use proc_macro::TokenStream;

#[proc_macro_derive(B)]
pub fn derive(_input: TokenStream) -> TokenStream {
    format!("impl B for A {{ fn b(&self) {{}} }}").parse().unwrap()
}
"#);
    bar.build();

    assert_that(foo.cargo_process("check"),
                execs().with_status(0));
}

#[test]
fn check_build() {
    if !is_nightly() {
        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#"
            extern crate bar;
            fn main() {
                ::bar::baz();
            }
        "#);
    let bar = project("bar")
        .file("Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.1.0"
            authors = []
        "#)
        .file("src/lib.rs", r#"
            pub fn baz() {}
        "#);
    bar.build();

    assert_that(foo.cargo_process("check"),
                execs().with_status(0));
    assert_that(foo.cargo_process("build"),
                execs().with_status(0));
}

#[test]
fn build_check() {
    if !is_nightly() {
        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#"
            extern crate bar;
            fn main() {
                ::bar::baz();
            }
        "#);
    let bar = project("bar")
        .file("Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.1.0"
            authors = []
        "#)
        .file("src/lib.rs", r#"
            pub fn baz() {}
        "#);
    bar.build();

    assert_that(foo.cargo_process("build"),
                execs().with_status(0));
    assert_that(foo.cargo_process("check"),
                execs().with_status(0));
}
<|endoftext|>


<commit_before>extern crate ktensor as k;
use k::{Arc, Vec2, Tensor, Context, Graph, State, Variable};
use std::path::{Path};
use std::fs::{File};
use std::io::{BufReader, Read};
use std::error::{Error};
use std::cmp;

fn read_u8(reader: &mut Read) -> u8 {
    use std::mem;

    let mut buf: [u8; 1] = [0];
    match reader.read_exact(&mut buf).map(|_| {
        let data: u8 = unsafe { mem::transmute(buf) };
        data
    }) {
        Err(reason) => panic!("failed to read u8: {}", Error::description(&reason)),
        Ok(byte)    => byte,
    }
}

fn read_u32(reader: &mut Read) -> u32 {
    use std::mem;

    let mut buf: [u8; 4] = [0, 0, 0, 0];
    match reader.read_exact(&mut buf).map(|_| {
        let data: u32 = unsafe { mem::transmute(buf) };
        data
    }) {
        Err(reason) => panic!("failed to read u32: {}", Error::description(&reason)),
        Ok(byte)    => byte,
    }
}

fn read_mnist(labels_path: &Path, labels_checknum: u32, data_path: &Path, data_checknum: u32, batch_size: Option<usize>, sample_size: Option<usize>) -> Vec<(Tensor<f32>, Tensor<f32>)> {
    let labels_file = match File::open(&labels_path) {
        Err(reason) => panic!("failed to open {}: {}", labels_path.display(), Error::description(&reason)),
        Ok(file)    => file,
    };
    let data_file = match File::open(&data_path) {
        Err(reason) => panic!("failed to open {}: {}", data_path.display(), Error::description(&reason)),
        Ok(file)    => file,
    };
    let ref mut labels_reader = BufReader::new(labels_file);
    let ref mut data_reader = BufReader::new(data_file);

    let labels_magic = u32::from_be(read_u32(labels_reader));
    let data_magic = u32::from_be(read_u32(data_reader));

    assert_eq!(labels_magic, labels_checknum);
    assert_eq!(data_magic, data_checknum);

    let labels_count = u32::from_be(read_u32(labels_reader)) as usize;
    let data_count = u32::from_be(read_u32(data_reader)) as usize;
    let sample_count = cmp::min(labels_count, data_count);
    let sample_count = cmp::min(sample_count, sample_size.unwrap_or(sample_count));

    let batch_count = cmp::min(sample_count, batch_size.unwrap_or(sample_count));

    let rows = u32::from_be(read_u32(data_reader)) as usize;
    let columns = u32::from_be(read_u32(data_reader)) as usize;

    let mut sample_vec: Vec<(Tensor<f32>, Tensor<f32>)> = Vec::with_capacity(sample_count/batch_count);
    for _ in 0..sample_count/batch_count {
        let mut sample_data = vec![0u8; batch_count*rows*columns];
        match data_reader.read_exact(sample_data.as_mut()) {
            Err(reason) => panic!("failed to read data byte array: {}", Error::description(&reason)),
            Ok(_)       => (),
        }
        let mut sample_labels_byte = vec![0u8; batch_count];
        match labels_reader.read_exact(sample_labels_byte.as_mut()) {
            Err(reason) => panic!("failed to read labels byte array: {}", Error::description(&reason)),
            Ok(_)       => (),
        }

        let sample_data = sample_data.iter().map(|&x| (x as f32 - 128.0) / 74.0).collect();
        let mut sample_labels: Vec<f32> = Vec::with_capacity(batch_count * 10);
        for i in sample_labels_byte {
            match i {
                0 => sample_labels.extend([1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0].iter().cloned()),
                1 => sample_labels.extend([0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0].iter().cloned()),
                2 => sample_labels.extend([0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0].iter().cloned()),
                3 => sample_labels.extend([0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0].iter().cloned()),
                4 => sample_labels.extend([0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0].iter().cloned()),
                5 => sample_labels.extend([0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0].iter().cloned()),
                6 => sample_labels.extend([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0].iter().cloned()),
                7 => sample_labels.extend([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0].iter().cloned()),
                8 => sample_labels.extend([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0].iter().cloned()),
                9 => sample_labels.extend([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0].iter().cloned()),
                _ => (),
            }
        }

        sample_vec.push((Tensor::from_vec(Vec2(batch_count, rows*columns), sample_data), Tensor::from_vec(Vec2(batch_count, 10), sample_labels)));
    }

    sample_vec
}

#[test]
#[ignore]
fn mnist(){
    ///////////////
    // Variables //
    ///////////////

    let input_x = Arc::new(Variable::new("input_x".to_string(), Vec2(0, 28 * 28)));
    let target_y = Arc::new(Variable::new("target_y".to_string(), Vec2(0, 10)));

    // Initialize
    let mut variable_context = Context::<f32>::with_capacity(2);
    Variable::init_f32(vec![input_x.clone(), target_y.clone()], &mut variable_context);

    ///////////
    // Graph //
    ///////////

    let layers: usize = 4;
    let mut states = Vec::<Arc<State>>::with_capacity(2 * layers);
    let mut graph_head: Arc<Graph<f32>> = input_x.clone();

    {
        let w = Arc::new(State::new(format!("weight_w_{}", 1), Vec2(28 * 28, 128)));
        let b = Arc::new(State::new(format!("weight_b_{}", 1), Vec2(1, 128)));

        let dot = Arc::new(k::op::dot::<f32>(format!("layer_{}_dot", 1), graph_head.clone(), w.clone()));
        let add = Arc::new(k::op::add::<f32>(format!("layer_{}_add", 1), dot, b.clone()));

        let relu = Arc::new(k::op::relu_f32(format!("layer_{}_relu", 1), add));

        graph_head = relu;

        states.push(w);
        states.push(b);
    }

    {
        let w = Arc::new(State::new(format!("weight_w_{}", 2), Vec2(128, 64)));
        let b = Arc::new(State::new(format!("weight_b_{}", 2), Vec2(1, 64)));

        let dot = Arc::new(k::op::dot::<f32>(format!("layer_{}_dot", 2), graph_head.clone(), w.clone()));
        let add = Arc::new(k::op::add::<f32>(format!("layer_{}_add", 2), dot, b.clone()));

        let relu = Arc::new(k::op::relu_f32(format!("layer_{}_relu", 2), add));

        graph_head = relu;

        states.push(w);
        states.push(b);
    }

    {
        let w = Arc::new(State::new(format!("weight_w_{}", 3), Vec2(64, 32)));
        let b = Arc::new(State::new(format!("weight_b_{}", 3), Vec2(1, 32)));

        let dot = Arc::new(k::op::dot::<f32>(format!("layer_{}_dot", 3), graph_head.clone(), w.clone()));
        let add = Arc::new(k::op::add::<f32>(format!("layer_{}_add", 3), dot, b.clone()));

        let relu = Arc::new(k::op::relu_f32(format!("layer_{}_relu", 3), add));

        graph_head = relu;

        states.push(w);
        states.push(b);
    }

    {
        let w = Arc::new(State::new(format!("weight_w_{}", 4), Vec2(32, 10)));
        let b = Arc::new(State::new(format!("weight_b_{}", 4), Vec2(1, 10)));

        let dot = Arc::new(k::op::dot::<f32>(format!("layer_{}_dot", 4), graph_head.clone(), w.clone()));
        let add = Arc::new(k::op::add::<f32>(format!("layer_{}_add", 4), dot, b.clone()));

        let relu = Arc::new(k::op::relu_f32(format!("layer_{}_relu", 4), add));

        graph_head = relu;

        states.push(w);
        states.push(b);
    }

    let softmax = Arc::new(k::op::softmax_f32(format!("layer_{}_softmax", 3), graph_head.clone()));
    let xentropy = Arc::new(k::cost::softmax_cross_entropy_f32(format!("layer_{}_xentropy", 3), softmax.clone(), target_y.clone()));

    // initialize states
    let mut state_context = Context::<f32>::with_capacity(2 * layers);
    State::init_f32(states, &mut state_context);

    //////////////
    // Training //
    //////////////
    {
        // Parameters
        let learning_rate = -0.001;
        let iterations = 2048;
        let batch_size = 16;
        let sample_size = iterations * batch_size;
        let print_rate = 64;

        let train_labels_path = Path::new("data/train-labels-idx1-ubyte");
        let train_data_path = Path::new("data/train-images-idx3-ubyte");
        let training_vec = read_mnist(&train_labels_path, 2049, &train_data_path, 2051, Some(batch_size), Some(sample_size));

        let mut history = Context::<f32>::with_capacity(5 * layers + 4);

        let training_vec_length = training_vec.len();
        for i in 0..iterations {
            let (ref a, ref b) = training_vec[i % training_vec_length];
            variable_context.set(input_x.get_id(), a.clone());
            variable_context.set(target_y.get_id(), b.clone());

            k::train(xentropy.clone(), &mut state_context, &variable_context, &mut history, learning_rate);

            // test print
            if i % print_rate == 0 {
                println!("iteration: {} | cross entropy cost: {}", i,
                k::execute(xentropy.clone(), &state_context, &variable_context).get(Vec2(0, 0)));
            }
        }

        println!("\ntraining complete\nalpha: {}, iterations: {}, batch_size: {}", learning_rate, iterations, batch_size);
    }

    ////////////////
    // Final test //
    ////////////////
    {
        println!("\nFinal Test:\n");
        // Parameters
        let batch_size = None;
        let sample_size = None;

        let test_labels_path = Path::new("data/t10k-labels-idx1-ubyte");
        let test_data_path = Path::new("data/t10k-images-idx3-ubyte");
        let test_vec = read_mnist(&test_labels_path, 2049, &test_data_path, 2051, batch_size, sample_size);

        let (ref a, ref b) = test_vec[0];
        variable_context.set(input_x.get_id(), a.clone());
        variable_context.set(target_y.get_id(), b.clone());

        let result_tensor = k::op::softmax_round_f32(k::execute(softmax.clone(), &state_context, &variable_context)) + (k::op::softmax_round_f32(b.clone()) * -1);
        let total = result_tensor.buffer().len() as f64;
        let mut score = 0.0;
        for &i in result_tensor.buffer().iter() {
            if i == 0 {
                score += 1.0;
            }
        }

        println!("{}", score/total);
    }
}
<commit_msg>simplify mnist<commit_after>extern crate ktensor as k;
use k::{Arc, Vec2, Tensor, Context, Graph, State, Variable};
use std::path::{Path};
use std::fs::{File};
use std::io::{BufReader, Read};
use std::error::{Error};
use std::cmp;

fn read_u8(reader: &mut Read) -> u8 {
    use std::mem;

    let mut buf: [u8; 1] = [0];
    match reader.read_exact(&mut buf).map(|_| {
        let data: u8 = unsafe { mem::transmute(buf) };
        data
    }) {
        Err(reason) => panic!("failed to read u8: {}", Error::description(&reason)),
        Ok(byte)    => byte,
    }
}

fn read_u32(reader: &mut Read) -> u32 {
    use std::mem;

    let mut buf: [u8; 4] = [0, 0, 0, 0];
    match reader.read_exact(&mut buf).map(|_| {
        let data: u32 = unsafe { mem::transmute(buf) };
        data
    }) {
        Err(reason) => panic!("failed to read u32: {}", Error::description(&reason)),
        Ok(byte)    => byte,
    }
}

fn read_mnist(labels_path: &Path, labels_checknum: u32, data_path: &Path, data_checknum: u32, batch_size: Option<usize>, sample_size: Option<usize>) -> Vec<(Tensor<f32>, Tensor<f32>)> {
    let labels_file = match File::open(&labels_path) {
        Err(reason) => panic!("failed to open {}: {}", labels_path.display(), Error::description(&reason)),
        Ok(file)    => file,
    };
    let data_file = match File::open(&data_path) {
        Err(reason) => panic!("failed to open {}: {}", data_path.display(), Error::description(&reason)),
        Ok(file)    => file,
    };
    let ref mut labels_reader = BufReader::new(labels_file);
    let ref mut data_reader = BufReader::new(data_file);

    let labels_magic = u32::from_be(read_u32(labels_reader));
    let data_magic = u32::from_be(read_u32(data_reader));

    assert_eq!(labels_magic, labels_checknum);
    assert_eq!(data_magic, data_checknum);

    let labels_count = u32::from_be(read_u32(labels_reader)) as usize;
    let data_count = u32::from_be(read_u32(data_reader)) as usize;
    let sample_count = cmp::min(labels_count, data_count);
    let sample_count = cmp::min(sample_count, sample_size.unwrap_or(sample_count));

    let batch_count = cmp::min(sample_count, batch_size.unwrap_or(sample_count));

    let rows = u32::from_be(read_u32(data_reader)) as usize;
    let columns = u32::from_be(read_u32(data_reader)) as usize;

    let mut sample_vec: Vec<(Tensor<f32>, Tensor<f32>)> = Vec::with_capacity(sample_count/batch_count);
    for _ in 0..sample_count/batch_count {
        let mut sample_data = vec![0u8; batch_count*rows*columns];
        match data_reader.read_exact(sample_data.as_mut()) {
            Err(reason) => panic!("failed to read data byte array: {}", Error::description(&reason)),
            Ok(_)       => (),
        }
        let mut sample_labels_byte = vec![0u8; batch_count];
        match labels_reader.read_exact(sample_labels_byte.as_mut()) {
            Err(reason) => panic!("failed to read labels byte array: {}", Error::description(&reason)),
            Ok(_)       => (),
        }

        let sample_data = sample_data.iter().map(|&x| (x as f32 - 128.0) / 74.0).collect();
        let mut sample_labels: Vec<f32> = Vec::with_capacity(batch_count * 10);
        for i in sample_labels_byte {
            match i {
                0 => sample_labels.extend([1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0].iter().cloned()),
                1 => sample_labels.extend([0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0].iter().cloned()),
                2 => sample_labels.extend([0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0].iter().cloned()),
                3 => sample_labels.extend([0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0].iter().cloned()),
                4 => sample_labels.extend([0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0].iter().cloned()),
                5 => sample_labels.extend([0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0].iter().cloned()),
                6 => sample_labels.extend([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0].iter().cloned()),
                7 => sample_labels.extend([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0].iter().cloned()),
                8 => sample_labels.extend([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0].iter().cloned()),
                9 => sample_labels.extend([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0].iter().cloned()),
                _ => (),
            }
        }

        sample_vec.push((Tensor::from_vec(Vec2(batch_count, rows*columns), sample_data), Tensor::from_vec(Vec2(batch_count, 10), sample_labels)));
    }

    sample_vec
}

#[test]
#[ignore]
fn mnist(){
    ///////////////
    // Variables //
    ///////////////

    let input_x = Arc::new(Variable::new("input_x".to_string(), Vec2(0, 28 * 28)));
    let target_y = Arc::new(Variable::new("target_y".to_string(), Vec2(0, 10)));

    // Initialize
    let mut variable_context = Context::<f32>::with_capacity(2);
    Variable::init_f32(vec![input_x.clone(), target_y.clone()], &mut variable_context);

    ///////////
    // Graph //
    ///////////

    let layers: usize = 4;
    let mut states = Vec::<Arc<State>>::with_capacity(2 * layers);
    let mut graph_head: Arc<Graph<f32>> = input_x.clone();

    {
        let w = Arc::new(State::new(format!("weight_w_{}", 1), Vec2(28 * 28, 64)));
        let b = Arc::new(State::new(format!("weight_b_{}", 1), Vec2(1, 64)));

        let dot = Arc::new(k::op::dot::<f32>(format!("layer_{}_dot", 1), graph_head.clone(), w.clone()));
        let add = Arc::new(k::op::add::<f32>(format!("layer_{}_add", 1), dot, b.clone()));

        let relu = Arc::new(k::op::relu_f32(format!("layer_{}_relu", 1), add));

        graph_head = relu;

        states.push(w);
        states.push(b);
    }

    {
        let w = Arc::new(State::new(format!("weight_w_{}", 3), Vec2(64, 32)));
        let b = Arc::new(State::new(format!("weight_b_{}", 3), Vec2(1, 32)));

        let dot = Arc::new(k::op::dot::<f32>(format!("layer_{}_dot", 3), graph_head.clone(), w.clone()));
        let add = Arc::new(k::op::add::<f32>(format!("layer_{}_add", 3), dot, b.clone()));

        let relu = Arc::new(k::op::relu_f32(format!("layer_{}_relu", 3), add));

        graph_head = relu;

        states.push(w);
        states.push(b);
    }

    {
        let w = Arc::new(State::new(format!("weight_w_{}", 4), Vec2(32, 10)));
        let b = Arc::new(State::new(format!("weight_b_{}", 4), Vec2(1, 10)));

        let dot = Arc::new(k::op::dot::<f32>(format!("layer_{}_dot", 4), graph_head.clone(), w.clone()));
        let add = Arc::new(k::op::add::<f32>(format!("layer_{}_add", 4), dot, b.clone()));

        let relu = Arc::new(k::op::relu_f32(format!("layer_{}_relu", 4), add));

        graph_head = relu;

        states.push(w);
        states.push(b);
    }

    let softmax = Arc::new(k::op::softmax_f32(format!("layer_{}_softmax", 3), graph_head.clone()));
    let xentropy = Arc::new(k::cost::softmax_cross_entropy_f32(format!("layer_{}_xentropy", 3), softmax.clone(), target_y.clone()));

    // initialize states
    let mut state_context = Context::<f32>::with_capacity(2 * layers);
    State::init_f32(states, &mut state_context);

    //////////////
    // Training //
    //////////////
    {
        // Parameters
        let learning_rate = -0.001;
        let iterations = 2048;
        let batch_size = 16;
        let sample_size = iterations * batch_size;
        let print_rate = 64;

        let train_labels_path = Path::new("data/train-labels-idx1-ubyte");
        let train_data_path = Path::new("data/train-images-idx3-ubyte");
        let training_vec = read_mnist(&train_labels_path, 2049, &train_data_path, 2051, Some(batch_size), Some(sample_size));

        let mut history = Context::<f32>::with_capacity(5 * layers + 4);

        let training_vec_length = training_vec.len();
        for i in 0..iterations {
            let (ref a, ref b) = training_vec[i % training_vec_length];
            variable_context.set(input_x.get_id(), a.clone());
            variable_context.set(target_y.get_id(), b.clone());

            k::train(xentropy.clone(), &mut state_context, &variable_context, &mut history, learning_rate);

            // test print
            if i % print_rate == 0 {
                println!("iteration: {} | cross entropy cost: {}", i,
                k::execute(xentropy.clone(), &state_context, &variable_context).get(Vec2(0, 0)));
            }
        }

        println!("\ntraining complete\nalpha: {}, iterations: {}, batch_size: {}", learning_rate, iterations, batch_size);
    }

    ////////////////
    // Final test //
    ////////////////
    {
        println!("\nFinal Test:\n");
        // Parameters
        let batch_size = None;
        let sample_size = None;

        let test_labels_path = Path::new("data/t10k-labels-idx1-ubyte");
        let test_data_path = Path::new("data/t10k-images-idx3-ubyte");
        let test_vec = read_mnist(&test_labels_path, 2049, &test_data_path, 2051, batch_size, sample_size);

        let (ref a, ref b) = test_vec[0];
        variable_context.set(input_x.get_id(), a.clone());
        variable_context.set(target_y.get_id(), b.clone());

        let result_tensor = k::op::softmax_round_f32(k::execute(softmax.clone(), &state_context, &variable_context)) + (k::op::softmax_round_f32(b.clone()) * -1);
        let total = result_tensor.buffer().len() as f64;
        let mut score = 0.0;
        for &i in result_tensor.buffer().iter() {
            if i == 0 {
                score += 1.0;
            }
        }

        println!("{}", score/total);
    }
}
<|endoftext|>


<commit_before>#![cfg_attr(feature = "qc", feature(plugin, custom_attribute, core))]
#![allow(dead_code)]
#![cfg_attr(feature="qc", plugin(quickcheck_macros))]

#[macro_use]
extern crate itertools;

#[cfg(feature = "qc")]
extern crate quickcheck;

#[cfg(feature = "qc")]
mod quicktests {

use quickcheck as qc;
use std::ops::Range;
use itertools;
use itertools::Itertools;
use itertools::{
    Zip,
    Stride,
    EitherOrBoth,
};

/// Our base iterator that we can impl Arbitrary for
#[derive(Clone, Debug)]
pub struct Iter<T>(Range<T>);

impl<T> Iterator for Iter<T> where Range<T>: Iterator
{
    type Item = <Range<T> as Iterator>::Item;
    fn next(&mut self) -> Option<Self::Item> { self.0.next() }
    fn size_hint(&self) -> (usize, Option<usize>)
    {
        self.0.size_hint()
    }
}

impl<T> DoubleEndedIterator for Iter<T> where Range<T>: DoubleEndedIterator
{
    fn next_back(&mut self) -> Option<Self::Item> { self.0.next_back() }
}

impl<T> ExactSizeIterator for Iter<T> where Range<T>: ExactSizeIterator
{ }

impl<T> qc::Arbitrary for Iter<T> where T: qc::Arbitrary
{
    fn arbitrary<G: qc::Gen>(g: &mut G) -> Self
    {
        Iter(T::arbitrary(g)..T::arbitrary(g))
    }

    fn shrink(&self) -> Box<Iterator<Item=Iter<T>>>
    {
        let r = self.0.clone();
        Box::new(
            r.start.shrink().flat_map(move |x| {
                r.end.shrink().map(move |y| (x.clone(), y))
            })
            .map(|(a, b)| Iter(a..b))
        )
    }
}

fn correct_size_hint<I: Iterator>(it: I) -> bool {
    let (low, hi) = it.size_hint();
    let cnt = it.count();
    cnt >= low &&
        (hi.is_none() || hi.unwrap() >= cnt)
}

fn exact_size<I: ExactSizeIterator>(mut it: I) -> bool {
    // check every iteration
    let (mut low, mut hi) = it.size_hint();
    if Some(low) != hi { return false; }
    while let Some(_) = it.next() {
        let (xlow, xhi) = it.size_hint();
        if low - 1 != xlow { return false; }
        low = xlow;
        hi = xhi;
        if Some(low) != hi { return false; }
    }
    let (low, hi) = it.size_hint();
    low == 0 && hi == Some(0)
}

#[quickcheck]
fn size_stride(data: Vec<u8>, stride: isize) -> bool {
    if stride == 0 {
        return true
    }
    exact_size(Stride::from_slice(&data, stride))
}

#[quickcheck]
fn equal_stride(data: Vec<u8>, stride: i8) -> bool {
    if stride == 0 {
        return true
    }
    if stride > 0 {
        itertools::equal(Stride::from_slice(&data, stride as isize),
                         data.iter().step(stride as usize))
    } else {
        itertools::equal(Stride::from_slice(&data, stride as isize),
                         data.iter().rev().step(-stride as usize))
    }
}

#[quickcheck]
fn size_product(a: Iter<u16>, b: Iter<u16>) -> bool {
    correct_size_hint(a.cartesian_product(b))
}

#[quickcheck]
fn size_product3(a: Iter<u16>, b: Iter<u16>, c: Iter<u16>) -> bool {
    correct_size_hint(iproduct!(a, b, c))
}

#[quickcheck]
fn equal_merge(a: Vec<i16>, b: Vec<i16>) -> bool {
    let mut sa = a.clone();
    let mut sb = b.clone();
    sa.sort();
    sb.sort();
    let mut merged = sa.clone() + &sb;
    merged.sort();
    itertools::equal(&merged, sa.iter().merge(&sb))

}
#[quickcheck]
fn size_merge(a: Iter<u16>, b: Iter<u16>) -> bool {
    correct_size_hint(a.merge(b))
}

#[quickcheck]
fn size_zip(a: Iter<i16>, b: Iter<i16>, c: Iter<i16>) -> bool {
    exact_size(Zip::new((a, b, c)))
}

#[quickcheck]
fn size_zip_longest(a: Iter<i16>, b: Iter<i16>) -> bool {
    exact_size(a.zip_longest(b))
}

#[quickcheck]
fn size_2_zip_longest(a: Iter<i16>, b: Iter<i16>) -> bool {
    let it = a.clone().zip_longest(b.clone());
    let jt = a.clone().zip_longest(b.clone());
    itertools::equal(a.clone(),
                     it.filter_map(|elt| match elt {
                         EitherOrBoth::Both(x, _) => Some(x),
                         EitherOrBoth::Left(x) => Some(x),
                         _ => None,
                     }
                     ))
        &&
    itertools::equal(b.clone(),
                     jt.filter_map(|elt| match elt {
                         EitherOrBoth::Both(_, y) => Some(y),
                         EitherOrBoth::Right(y) => Some(y),
                         _ => None,
                     }
                     ))
}

fn equal_islice(a: Vec<i16>, x: usize, y: usize) -> bool {
    if x > y || y > a.len() { return true; }
    let slc = &a[x..y];
    itertools::equal(a.iter().slice(x..y), slc)
}

#[quickcheck]
fn size_interleave(a: Iter<i16>, b: Iter<i16>) -> bool {
    correct_size_hint(a.interleave(b))
}

#[quickcheck]
fn size_intersperse(a: Iter<i16>, x: i16) -> bool {
    correct_size_hint(a.intersperse(x))
}

#[quickcheck]
fn equal_intersperse(a: Iter<i32>, x: i32) -> bool {
    if a.len() == 0 { return true }
    a.clone().intersperse(x).sum::<i32>() ==
        (a.clone().sum::<i32>() + (a.len() as i32 - 1) * x)
}

#[quickcheck]
fn equal_dedup(a: Vec<i32>) -> bool {
    let mut b = a.clone();
    b.dedup();
    itertools::equal(&b, a.iter().dedup())
}

#[quickcheck]
fn size_dedup(a: Vec<i32>) -> bool {
    correct_size_hint(a.iter().dedup())
}

#[quickcheck]
fn size_group_by(a: Vec<i8>) -> bool {
    correct_size_hint(a.iter().group_by(|x| x.abs()))
}

#[quickcheck]
fn equal_repeatn(n: usize, x: i32) -> bool {
    let it = itertools::RepeatN::new(x, n);
    exact_size(it)
}

}
<commit_msg>Better test for intersperse<commit_after>#![cfg_attr(feature = "qc", feature(plugin, custom_attribute))]
#![cfg_attr(feature="qc", plugin(quickcheck_macros))]
#![allow(dead_code)]

#[macro_use]
extern crate itertools;

#[cfg(feature = "qc")]
extern crate quickcheck;

#[cfg(feature = "qc")]
mod quicktests {

use quickcheck as qc;
use std::ops::Range;
use itertools;
use itertools::Itertools;
use itertools::{
    Zip,
    Stride,
    EitherOrBoth,
};

/// Our base iterator that we can impl Arbitrary for
#[derive(Clone, Debug)]
pub struct Iter<T>(Range<T>);

impl<T> Iterator for Iter<T> where Range<T>: Iterator
{
    type Item = <Range<T> as Iterator>::Item;
    fn next(&mut self) -> Option<Self::Item> { self.0.next() }
    fn size_hint(&self) -> (usize, Option<usize>)
    {
        self.0.size_hint()
    }
}

impl<T> DoubleEndedIterator for Iter<T> where Range<T>: DoubleEndedIterator
{
    fn next_back(&mut self) -> Option<Self::Item> { self.0.next_back() }
}

impl<T> ExactSizeIterator for Iter<T> where Range<T>: ExactSizeIterator
{ }

impl<T> qc::Arbitrary for Iter<T> where T: qc::Arbitrary
{
    fn arbitrary<G: qc::Gen>(g: &mut G) -> Self
    {
        Iter(T::arbitrary(g)..T::arbitrary(g))
    }

    fn shrink(&self) -> Box<Iterator<Item=Iter<T>>>
    {
        let r = self.0.clone();
        Box::new(
            r.start.shrink().flat_map(move |x| {
                r.end.shrink().map(move |y| (x.clone(), y))
            })
            .map(|(a, b)| Iter(a..b))
        )
    }
}

fn correct_size_hint<I: Iterator>(it: I) -> bool {
    let (low, hi) = it.size_hint();
    let cnt = it.count();
    cnt >= low &&
        (hi.is_none() || hi.unwrap() >= cnt)
}

fn exact_size<I: ExactSizeIterator>(mut it: I) -> bool {
    // check every iteration
    let (mut low, mut hi) = it.size_hint();
    if Some(low) != hi { return false; }
    while let Some(_) = it.next() {
        let (xlow, xhi) = it.size_hint();
        if low - 1 != xlow { return false; }
        low = xlow;
        hi = xhi;
        if Some(low) != hi { return false; }
    }
    let (low, hi) = it.size_hint();
    low == 0 && hi == Some(0)
}

#[quickcheck]
fn size_stride(data: Vec<u8>, stride: isize) -> bool {
    if stride == 0 {
        return true
    }
    exact_size(Stride::from_slice(&data, stride))
}

#[quickcheck]
fn equal_stride(data: Vec<u8>, stride: i8) -> bool {
    if stride == 0 {
        return true
    }
    if stride > 0 {
        itertools::equal(Stride::from_slice(&data, stride as isize),
                         data.iter().step(stride as usize))
    } else {
        itertools::equal(Stride::from_slice(&data, stride as isize),
                         data.iter().rev().step(-stride as usize))
    }
}

#[quickcheck]
fn size_product(a: Iter<u16>, b: Iter<u16>) -> bool {
    correct_size_hint(a.cartesian_product(b))
}

#[quickcheck]
fn size_product3(a: Iter<u16>, b: Iter<u16>, c: Iter<u16>) -> bool {
    correct_size_hint(iproduct!(a, b, c))
}

#[quickcheck]
fn equal_merge(a: Vec<i16>, b: Vec<i16>) -> bool {
    let mut sa = a.clone();
    let mut sb = b.clone();
    sa.sort();
    sb.sort();
    let mut merged = sa.clone() + &sb;
    merged.sort();
    itertools::equal(&merged, sa.iter().merge(&sb))

}
#[quickcheck]
fn size_merge(a: Iter<u16>, b: Iter<u16>) -> bool {
    correct_size_hint(a.merge(b))
}

#[quickcheck]
fn size_zip(a: Iter<i16>, b: Iter<i16>, c: Iter<i16>) -> bool {
    exact_size(Zip::new((a, b, c)))
}

#[quickcheck]
fn size_zip_longest(a: Iter<i16>, b: Iter<i16>) -> bool {
    exact_size(a.zip_longest(b))
}

#[quickcheck]
fn size_2_zip_longest(a: Iter<i16>, b: Iter<i16>) -> bool {
    let it = a.clone().zip_longest(b.clone());
    let jt = a.clone().zip_longest(b.clone());
    itertools::equal(a.clone(),
                     it.filter_map(|elt| match elt {
                         EitherOrBoth::Both(x, _) => Some(x),
                         EitherOrBoth::Left(x) => Some(x),
                         _ => None,
                     }
                     ))
        &&
    itertools::equal(b.clone(),
                     jt.filter_map(|elt| match elt {
                         EitherOrBoth::Both(_, y) => Some(y),
                         EitherOrBoth::Right(y) => Some(y),
                         _ => None,
                     }
                     ))
}

fn equal_islice(a: Vec<i16>, x: usize, y: usize) -> bool {
    if x > y || y > a.len() { return true; }
    let slc = &a[x..y];
    itertools::equal(a.iter().slice(x..y), slc)
}

#[quickcheck]
fn size_interleave(a: Iter<i16>, b: Iter<i16>) -> bool {
    correct_size_hint(a.interleave(b))
}

#[quickcheck]
fn size_intersperse(a: Iter<i16>, x: i16) -> bool {
    correct_size_hint(a.intersperse(x))
}

#[quickcheck]
fn equal_intersperse(a: Vec<i32>, x: i32) -> bool {
    let mut inter = false;
    let mut i = 0;
    for elt in a.iter().cloned().intersperse(x) {
        if inter {
            if elt != x { return false }
        } else {
            if elt != a[i] { return false }
            i += 1;
        }
        inter = !inter;
    }
    true
}

#[quickcheck]
fn equal_dedup(a: Vec<i32>) -> bool {
    let mut b = a.clone();
    b.dedup();
    itertools::equal(&b, a.iter().dedup())
}

#[quickcheck]
fn size_dedup(a: Vec<i32>) -> bool {
    correct_size_hint(a.iter().dedup())
}

#[quickcheck]
fn size_group_by(a: Vec<i8>) -> bool {
    correct_size_hint(a.iter().group_by(|x| x.abs()))
}

#[quickcheck]
fn equal_repeatn(n: usize, x: i32) -> bool {
    let it = itertools::RepeatN::new(x, n);
    exact_size(it)
}

}
<|endoftext|>


<commit_before>// Copyright 2013-2014 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.

extern crate tempdir;

use std::env;
use std::fs;
use std::path::Path;
use std::sync::mpsc::channel;
use std::thread;

use tempdir::TempDir;

macro_rules! t {
    ($e:expr) => (match $e { Ok(n) => n, Err(e) => panic!("error: {}", e) })
}

trait PathExt {
    fn exists(&self) -> bool;
    fn is_dir(&self) -> bool;
}

impl PathExt for Path {
    fn exists(&self) -> bool { fs::metadata(self).is_ok() }
    fn is_dir(&self) -> bool {
        fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false)
    }
}

fn test_tempdir() {
    let path = {
        let p = t!(TempDir::new_in(&Path::new("."), "foobar"));
        let p = p.path();
        assert!(p.to_str().unwrap().contains("foobar"));
        p.to_path_buf()
    };
    assert!(!path.exists());
}

fn test_rm_tempdir() {
    let (tx, rx) = channel();
    let f = move|| -> () {
        let tmp = t!(TempDir::new("test_rm_tempdir"));
        tx.send(tmp.path().to_path_buf()).unwrap();
        panic!("panic to unwind past `tmp`");
    };
    let _ = thread::spawn(f).join();
    let path = rx.recv().unwrap();
    assert!(!path.exists());

    let tmp = t!(TempDir::new("test_rm_tempdir"));
    let path = tmp.path().to_path_buf();
    let f = move|| -> () {
        let _tmp = tmp;
        panic!("panic to unwind past `tmp`");
    };
    let _ = thread::spawn(f).join();
    assert!(!path.exists());

    let path;
    {
        let f = move || {
            t!(TempDir::new("test_rm_tempdir"))
        };
        // FIXME(#16640) `: TempDir` annotation shouldn't be necessary
        let tmp: TempDir = thread::spawn(f).join().unwrap();
        path = tmp.path().to_path_buf();
        assert!(path.exists());
    }
    assert!(!path.exists());

    let path;
    {
        let tmp = t!(TempDir::new("test_rm_tempdir"));
        path = tmp.into_path();
    }
    assert!(path.exists());
    t!(fs::remove_dir_all(&path));
    assert!(!path.exists());
}

fn test_rm_tempdir_close() {
    let (tx, rx) = channel();
    let f = move|| -> () {
        let tmp = t!(TempDir::new("test_rm_tempdir"));
        tx.send(tmp.path().to_path_buf()).unwrap();
        t!(tmp.close());
        panic!("panic when unwinding past `tmp`");
    };
    let _ = thread::spawn(f).join();
    let path = rx.recv().unwrap();
    assert!(!path.exists());

    let tmp = t!(TempDir::new("test_rm_tempdir"));
    let path = tmp.path().to_path_buf();
    let f = move|| -> () {
        let tmp = tmp;
        t!(tmp.close());
        panic!("panic when unwinding past `tmp`");
    };
    let _ = thread::spawn(f).join();
    assert!(!path.exists());

    let path;
    {
        let f = move || {
            t!(TempDir::new("test_rm_tempdir"))
        };
        // FIXME(#16640) `: TempDir` annotation shouldn't be necessary
        let tmp: TempDir = thread::spawn(f).join().unwrap();
        path = tmp.path().to_path_buf();
        assert!(path.exists());
        t!(tmp.close());
    }
    assert!(!path.exists());

    let path;
    {
        let tmp = t!(TempDir::new("test_rm_tempdir"));
        path = tmp.into_path();
    }
    assert!(path.exists());
    t!(fs::remove_dir_all(&path));
    assert!(!path.exists());
}

// Ideally these would be in std::os but then core would need
// to depend on std
fn recursive_mkdir_rel() {
    let path = Path::new("frob");
    let cwd = env::current_dir().unwrap();
    println!("recursive_mkdir_rel: Making: {} in cwd {} [{}]", path.display(),
           cwd.display(), path.exists());
    t!(fs::create_dir(&path));
    assert!(path.is_dir());
    t!(fs::create_dir_all(&path));
    assert!(path.is_dir());
}

fn recursive_mkdir_dot() {
    let dot = Path::new(".");
    t!(fs::create_dir_all(&dot));
    let dotdot = Path::new("..");
    t!(fs::create_dir_all(&dotdot));
}

fn recursive_mkdir_rel_2() {
    let path = Path::new("./frob/baz");
    let cwd = env::current_dir().unwrap();
    println!("recursive_mkdir_rel_2: Making: {} in cwd {} [{}]", path.display(),
             cwd.display(), path.exists());
    t!(fs::create_dir_all(&path));
    assert!(path.is_dir());
    assert!(path.parent().unwrap().is_dir());
    let path2 = Path::new("quux/blat");
    println!("recursive_mkdir_rel_2: Making: {} in cwd {}", path2.display(),
             cwd.display());
    t!(fs::create_dir("quux"));
    t!(fs::create_dir_all(&path2));
    assert!(path2.is_dir());
    assert!(path2.parent().unwrap().is_dir());
}

// Ideally this would be in core, but needs TempFile
pub fn test_remove_dir_all_ok() {
    let tmpdir = t!(TempDir::new("test"));
    let tmpdir = tmpdir.path();
    let root = tmpdir.join("foo");

    println!("making {}", root.display());
    t!(fs::create_dir(&root));
    t!(fs::create_dir(&root.join("foo")));
    t!(fs::create_dir(&root.join("foo").join("bar")));
    t!(fs::create_dir(&root.join("foo").join("bar").join("blat")));
    t!(fs::remove_dir_all(&root));
    assert!(!root.exists());
    assert!(!root.join("bar").exists());
    assert!(!root.join("bar").join("blat").exists());
}

pub fn dont_double_panic() {
    let r: Result<(), _> = thread::spawn(move|| {
        let tmpdir = TempDir::new("test").unwrap();
        // Remove the temporary directory so that TempDir sees
        // an error on drop
        t!(fs::remove_dir(tmpdir.path()));
        // Panic. If TempDir panics *again* due to the rmdir
        // error then the process will abort.
        panic!();
    }).join();
    assert!(r.is_err());
}

fn in_tmpdir<F>(f: F) where F: FnOnce() {
    let tmpdir = t!(TempDir::new("test"));
    assert!(env::set_current_dir(tmpdir.path()).is_ok());

    f();
}

pub fn pass_as_asref_path() {
    let tempdir = t!(TempDir::new("test"));
    takes_asref_path(&tempdir);

    fn takes_asref_path<T: AsRef<Path>>(path: T) {
        let path = path.as_ref();
        assert!(path.exists());
    }
}

#[test]
fn main() {
    in_tmpdir(test_tempdir);
    in_tmpdir(test_rm_tempdir);
    in_tmpdir(test_rm_tempdir_close);
    in_tmpdir(recursive_mkdir_rel);
    in_tmpdir(recursive_mkdir_dot);
    in_tmpdir(recursive_mkdir_rel_2);
    in_tmpdir(test_remove_dir_all_ok);
    in_tmpdir(dont_double_panic);
    in_tmpdir(pass_as_asref_path);
}
<commit_msg>test: remove old fixme from the tests<commit_after>// Copyright 2013-2014 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.

extern crate tempdir;

use std::env;
use std::fs;
use std::path::Path;
use std::sync::mpsc::channel;
use std::thread;

use tempdir::TempDir;

macro_rules! t {
    ($e:expr) => (match $e { Ok(n) => n, Err(e) => panic!("error: {}", e) })
}

trait PathExt {
    fn exists(&self) -> bool;
    fn is_dir(&self) -> bool;
}

impl PathExt for Path {
    fn exists(&self) -> bool { fs::metadata(self).is_ok() }
    fn is_dir(&self) -> bool {
        fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false)
    }
}

fn test_tempdir() {
    let path = {
        let p = t!(TempDir::new_in(&Path::new("."), "foobar"));
        let p = p.path();
        assert!(p.to_str().unwrap().contains("foobar"));
        p.to_path_buf()
    };
    assert!(!path.exists());
}

fn test_rm_tempdir() {
    let (tx, rx) = channel();
    let f = move|| -> () {
        let tmp = t!(TempDir::new("test_rm_tempdir"));
        tx.send(tmp.path().to_path_buf()).unwrap();
        panic!("panic to unwind past `tmp`");
    };
    let _ = thread::spawn(f).join();
    let path = rx.recv().unwrap();
    assert!(!path.exists());

    let tmp = t!(TempDir::new("test_rm_tempdir"));
    let path = tmp.path().to_path_buf();
    let f = move|| -> () {
        let _tmp = tmp;
        panic!("panic to unwind past `tmp`");
    };
    let _ = thread::spawn(f).join();
    assert!(!path.exists());

    let path;
    {
        let f = move || {
            t!(TempDir::new("test_rm_tempdir"))
        };

        let tmp = thread::spawn(f).join().unwrap();
        path = tmp.path().to_path_buf();
        assert!(path.exists());
    }
    assert!(!path.exists());

    let path;
    {
        let tmp = t!(TempDir::new("test_rm_tempdir"));
        path = tmp.into_path();
    }
    assert!(path.exists());
    t!(fs::remove_dir_all(&path));
    assert!(!path.exists());
}

fn test_rm_tempdir_close() {
    let (tx, rx) = channel();
    let f = move|| -> () {
        let tmp = t!(TempDir::new("test_rm_tempdir"));
        tx.send(tmp.path().to_path_buf()).unwrap();
        t!(tmp.close());
        panic!("panic when unwinding past `tmp`");
    };
    let _ = thread::spawn(f).join();
    let path = rx.recv().unwrap();
    assert!(!path.exists());

    let tmp = t!(TempDir::new("test_rm_tempdir"));
    let path = tmp.path().to_path_buf();
    let f = move|| -> () {
        let tmp = tmp;
        t!(tmp.close());
        panic!("panic when unwinding past `tmp`");
    };
    let _ = thread::spawn(f).join();
    assert!(!path.exists());

    let path;
    {
        let f = move || {
            t!(TempDir::new("test_rm_tempdir"))
        };

        let tmp = thread::spawn(f).join().unwrap();
        path = tmp.path().to_path_buf();
        assert!(path.exists());
        t!(tmp.close());
    }
    assert!(!path.exists());

    let path;
    {
        let tmp = t!(TempDir::new("test_rm_tempdir"));
        path = tmp.into_path();
    }
    assert!(path.exists());
    t!(fs::remove_dir_all(&path));
    assert!(!path.exists());
}

// Ideally these would be in std::os but then core would need
// to depend on std
fn recursive_mkdir_rel() {
    let path = Path::new("frob");
    let cwd = env::current_dir().unwrap();
    println!("recursive_mkdir_rel: Making: {} in cwd {} [{}]", path.display(),
           cwd.display(), path.exists());
    t!(fs::create_dir(&path));
    assert!(path.is_dir());
    t!(fs::create_dir_all(&path));
    assert!(path.is_dir());
}

fn recursive_mkdir_dot() {
    let dot = Path::new(".");
    t!(fs::create_dir_all(&dot));
    let dotdot = Path::new("..");
    t!(fs::create_dir_all(&dotdot));
}

fn recursive_mkdir_rel_2() {
    let path = Path::new("./frob/baz");
    let cwd = env::current_dir().unwrap();
    println!("recursive_mkdir_rel_2: Making: {} in cwd {} [{}]", path.display(),
             cwd.display(), path.exists());
    t!(fs::create_dir_all(&path));
    assert!(path.is_dir());
    assert!(path.parent().unwrap().is_dir());
    let path2 = Path::new("quux/blat");
    println!("recursive_mkdir_rel_2: Making: {} in cwd {}", path2.display(),
             cwd.display());
    t!(fs::create_dir("quux"));
    t!(fs::create_dir_all(&path2));
    assert!(path2.is_dir());
    assert!(path2.parent().unwrap().is_dir());
}

// Ideally this would be in core, but needs TempFile
pub fn test_remove_dir_all_ok() {
    let tmpdir = t!(TempDir::new("test"));
    let tmpdir = tmpdir.path();
    let root = tmpdir.join("foo");

    println!("making {}", root.display());
    t!(fs::create_dir(&root));
    t!(fs::create_dir(&root.join("foo")));
    t!(fs::create_dir(&root.join("foo").join("bar")));
    t!(fs::create_dir(&root.join("foo").join("bar").join("blat")));
    t!(fs::remove_dir_all(&root));
    assert!(!root.exists());
    assert!(!root.join("bar").exists());
    assert!(!root.join("bar").join("blat").exists());
}

pub fn dont_double_panic() {
    let r: Result<(), _> = thread::spawn(move|| {
        let tmpdir = TempDir::new("test").unwrap();
        // Remove the temporary directory so that TempDir sees
        // an error on drop
        t!(fs::remove_dir(tmpdir.path()));
        // Panic. If TempDir panics *again* due to the rmdir
        // error then the process will abort.
        panic!();
    }).join();
    assert!(r.is_err());
}

fn in_tmpdir<F>(f: F) where F: FnOnce() {
    let tmpdir = t!(TempDir::new("test"));
    assert!(env::set_current_dir(tmpdir.path()).is_ok());

    f();
}

pub fn pass_as_asref_path() {
    let tempdir = t!(TempDir::new("test"));
    takes_asref_path(&tempdir);

    fn takes_asref_path<T: AsRef<Path>>(path: T) {
        let path = path.as_ref();
        assert!(path.exists());
    }
}

#[test]
fn main() {
    in_tmpdir(test_tempdir);
    in_tmpdir(test_rm_tempdir);
    in_tmpdir(test_rm_tempdir_close);
    in_tmpdir(recursive_mkdir_rel);
    in_tmpdir(recursive_mkdir_dot);
    in_tmpdir(recursive_mkdir_rel_2);
    in_tmpdir(test_remove_dir_all_ok);
    in_tmpdir(dont_double_panic);
    in_tmpdir(pass_as_asref_path);
}
<|endoftext|>


<commit_before>// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

mod cmd_finder;

use std::env;
use std::env::consts;
use std::fs;
use std::path::{Path, PathBuf};

static COMBINED_LIB: &str = "shaderc_combined";
static COMBINED_LIB_FILE: &str = "libshaderc_combined.a";
static SPIRV_LIB_FILE: &str = "libSPIRV.a";

fn build_shaderc(shaderc_dir: &PathBuf, use_ninja: bool) -> PathBuf {
    let mut config = cmake::Config::new(shaderc_dir);
    config
        .profile("Release")
        .define("CMAKE_POSITION_INDEPENDENT_CODE", "ON")
        .define("SPIRV_SKIP_EXECUTABLES", "ON")
        .define("SPIRV_WERROR", "OFF")
        .define("SHADERC_SKIP_TESTS", "ON")
        .define("CMAKE_INSTALL_LIBDIR", "lib");
    if use_ninja {
        config.generator("Ninja");
    }
    config.build()
}

fn build_shaderc_msvc(shaderc_dir: &PathBuf) -> PathBuf {
    let mut config = cmake::Config::new(shaderc_dir);
    config
        .profile("Release")
        .define("CMAKE_POSITION_INDEPENDENT_CODE", "ON")
        .define("SPIRV_SKIP_EXECUTABLES", "ON")
        .define("SPIRV_WERROR", "OFF")
        .define("SHADERC_SKIP_TESTS", "ON")
        // cmake-rs tries to be clever on Windows by injecting several
        // C/C++ flags, which causes problems. So I have to manually
        // define CMAKE_*_FLAGS_* here to suppress that.
        .define("CMAKE_C_FLAGS", " /nologo /EHsc")
        .define("CMAKE_CXX_FLAGS", " /nologo /EHsc")
        .define("CMAKE_C_FLAGS_RELEASE", " /nologo /EHsc")
        .define("CMAKE_CXX_FLAGS_RELEASE", " /nologo /EHsc")
        .define("CMAKE_INSTALL_LIBDIR", "lib")
        .generator("Ninja");
    config.build()
}

fn main() {
    let config_build_from_source = env::var("CARGO_FEATURE_BUILD_FROM_SOURCE").is_ok();
    let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
    let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap();
    let explicit_lib_dir_set = env::var("SHADERC_LIB_DIR").is_ok();

    // Deprecated --no-defaults behavior from before shaderc-rs & shaderc-sys split
    // This block is only relevant to shaderc-rs but will skip all subsequent
    // build options
    if env::var("CARGO_FEATURE_CHECK_INVERTED_NO_DEFAULTS").is_ok()
        && env::var("CARGO_FEATURE_INVERTED_NO_DEFAULTS").is_err()
    {
        let out_dir = env::var("OUT_DIR").unwrap();
        println!("cargo:warning=USE OF --no-default-features IS DEPRECATED BEHAVIOR.");
        println!(
            "cargo:warning=Requested to use cargo out directory to find libshaderc_combined.a"
        );
        println!(
            "cargo:warning=Searching {} for shaderc_combined static lib...",
            out_dir
        );
        println!("cargo:rustc-link-search=native={}", out_dir);
        println!("cargo:rustc-link-lib=static=shaderc_combined");
        emit_std_cpp_link();
        return;
    }

    // Initialize explicit libshaderc search directory first
    let mut search_dir = if let Ok(lib_dir) = env::var("SHADERC_LIB_DIR") {
        println!(
            "cargo:warning=Specified {} to search for libshaderc.",
            lib_dir
        );
        Some(lib_dir)
    } else {
        None
    };

    // If no explicit path is set and no explicit request is made to build from
    // source, check known locations before falling back to from-source-build
    if search_dir.is_none() && target_os == "linux" && !config_build_from_source {
        println!(
            "cargo:warning=Checking for system installed libraries.  \
             Use --features = build-from-source to disable this behavior"
        );
        search_dir = Some("/usr/lib/".to_owned());
    }

    // Try to build with the static lib if a path was received or chosen
    let search_dir = if let Some(search_dir) = search_dir {
        let path = Path::new(&search_dir);
        let cannonical = fs::canonicalize(&path);
        if path.is_relative() {
            println!(
                "cargo:warning=Provided path {:?} is relative.  Path must be \
                 relative to shaderc-sys crate, possibly not your current \
                 working directory",
                &path
            );
        } else if path.is_dir() == false {
            println!(
                "cargo:warning=Provided path {:?} is not a directory.",
                &path
            );
        }
        if (cannonical.is_err()) && explicit_lib_dir_set {
            println!("cargo:warning={:?}", cannonical.err().unwrap());
            println!(
                "cargo:warning=Provided path {:?} could not be canonicallized",
                &path
            );
            None
        } else {
            cannonical.ok()
        }
    } else {
        None
    };

    if let Some(search_dir) = search_dir {
        let search_dir_str = search_dir.to_string_lossy();
        let combined_lib_path = search_dir.join(COMBINED_LIB_FILE);
        let dylib_name = format!("{}shaderc{}", consts::DLL_PREFIX, consts::DLL_SUFFIX);
        let dylib_path = search_dir.join(dylib_name.clone());

        if let Some((lib_dir, lib_name)) = {
            if combined_lib_path.exists() {
                Some((&search_dir_str, COMBINED_LIB))
            } else if dylib_path.exists() {
                Some((&search_dir_str, dylib_name.as_str()))
            } else {
                None
            }
        } {
            match (target_os.as_str(), target_env.as_str()) {
                ("linux", _) => {
                    println!("cargo:rustc-link-search=native={}", lib_dir);
                    let spirv_path = search_dir.join(SPIRV_LIB_FILE);
                    if spirv_path.exists() {
                        println!(
                            "cargo:warning=Found SPIRV.  Linking libSPIRV & \
                             libglslang"
                        );
                        println!("cargo:rustc-link-lib=static=SPIRV");
                        println!("cargo:rustc-link-lib=static=SPIRV-Tools-opt");
                        println!("cargo:rustc-link-lib=static=SPIRV-Tools");
                        println!("cargo:rustc-link-lib=glslang");
                    } else {
                        println!(
                            "cargo:warning=Only libshaderc library found.  \
                             Assuming libSPIRV & libglslang built into provided \
                             libshaderc."
                        );
                    }
                    println!("cargo:rustc-link-lib=static={}", lib_name);
                    println!("cargo:rustc-link-lib=dylib=stdc++");
                    return;
                }
                ("windows", "gnu") => {
                    println!(
                        "cargo:warning=Windows MinGW static builds \
                         experimental"
                    );
                    println!("cargo:rustc-link-search=native={}", lib_dir);
                    println!("cargo:rustc-link-lib=static={}", lib_name);
                    println!("cargo:rustc-link-lib=dylib=stdc++");
                    return;
                }
                ("macos", _) => {
                    println!("cargo:warning=MacOS static builds experimental");
                    println!("cargo:rustc-link-search=native={}", lib_dir);
                    println!("cargo:rustc-link-lib=static={}", lib_name);
                    println!("cargo:rustc-link-lib=dylib=c++");
                    return;
                }
                (_, _) => {
                    println!(
                        "cargo:warning=Platform unsupported for pre-built \
                         libshaderc"
                    );
                }
            }
        }
    }

    if config_build_from_source {
        println!("cargo:warning=Requested to build from source");
    } else {
        println!(
            "cargo:warning=Pre-built library not found.  Falling back \
             to from-source build"
        );
    }

    let mut finder = cmd_finder::CommandFinder::new();

    finder.must_have("cmake");
    finder.must_have("git");
    finder.must_have("python");

    let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let shaderc_dir = Path::new(&manifest_dir).join("build");

    let mut lib_path = if target_env == "msvc" {
        finder.must_have("ninja");
        build_shaderc_msvc(&shaderc_dir)
    } else {
        let has_ninja = finder.maybe_have("ninja").is_some();
        build_shaderc(&shaderc_dir, has_ninja)
    };

    lib_path.push("lib");
    println!("cargo:rustc-link-search=native={}", lib_path.display());
    println!("cargo:rustc-link-lib=static=shaderc_combined");

    emit_std_cpp_link();
}

fn emit_std_cpp_link() {
    let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
    let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap();

    match (target_os.as_str(), target_env.as_str()) {
        ("linux", _) | ("windows", "gnu") => println!("cargo:rustc-link-lib=dylib=stdc++"),
        ("macos", _) => println!("cargo:rustc-link-lib=dylib=c++"),
        _ => {}
    }
}
<commit_msg>Fix dynamic library name (#54)<commit_after>// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

mod cmd_finder;

use std::env;
use std::env::consts;
use std::fs;
use std::path::{Path, PathBuf};

static COMBINED_LIB: &str = "shaderc_combined";
static DYNAMIC_LIB: &str = "shaderc_shared";
static COMBINED_LIB_FILE: &str = "libshaderc_combined.a";
static SPIRV_LIB_FILE: &str = "libSPIRV.a";

fn build_shaderc(shaderc_dir: &PathBuf, use_ninja: bool) -> PathBuf {
    let mut config = cmake::Config::new(shaderc_dir);
    config
        .profile("Release")
        .define("CMAKE_POSITION_INDEPENDENT_CODE", "ON")
        .define("SPIRV_SKIP_EXECUTABLES", "ON")
        .define("SPIRV_WERROR", "OFF")
        .define("SHADERC_SKIP_TESTS", "ON")
        .define("CMAKE_INSTALL_LIBDIR", "lib");
    if use_ninja {
        config.generator("Ninja");
    }
    config.build()
}

fn build_shaderc_msvc(shaderc_dir: &PathBuf) -> PathBuf {
    let mut config = cmake::Config::new(shaderc_dir);
    config
        .profile("Release")
        .define("CMAKE_POSITION_INDEPENDENT_CODE", "ON")
        .define("SPIRV_SKIP_EXECUTABLES", "ON")
        .define("SPIRV_WERROR", "OFF")
        .define("SHADERC_SKIP_TESTS", "ON")
        // cmake-rs tries to be clever on Windows by injecting several
        // C/C++ flags, which causes problems. So I have to manually
        // define CMAKE_*_FLAGS_* here to suppress that.
        .define("CMAKE_C_FLAGS", " /nologo /EHsc")
        .define("CMAKE_CXX_FLAGS", " /nologo /EHsc")
        .define("CMAKE_C_FLAGS_RELEASE", " /nologo /EHsc")
        .define("CMAKE_CXX_FLAGS_RELEASE", " /nologo /EHsc")
        .define("CMAKE_INSTALL_LIBDIR", "lib")
        .generator("Ninja");
    config.build()
}

fn main() {
    let config_build_from_source = env::var("CARGO_FEATURE_BUILD_FROM_SOURCE").is_ok();
    let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
    let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap();
    let explicit_lib_dir_set = env::var("SHADERC_LIB_DIR").is_ok();

    // Deprecated --no-defaults behavior from before shaderc-rs & shaderc-sys split
    // This block is only relevant to shaderc-rs but will skip all subsequent
    // build options
    if env::var("CARGO_FEATURE_CHECK_INVERTED_NO_DEFAULTS").is_ok()
        && env::var("CARGO_FEATURE_INVERTED_NO_DEFAULTS").is_err()
    {
        let out_dir = env::var("OUT_DIR").unwrap();
        println!("cargo:warning=USE OF --no-default-features IS DEPRECATED BEHAVIOR.");
        println!(
            "cargo:warning=Requested to use cargo out directory to find libshaderc_combined.a"
        );
        println!(
            "cargo:warning=Searching {} for shaderc_combined static lib...",
            out_dir
        );
        println!("cargo:rustc-link-search=native={}", out_dir);
        println!("cargo:rustc-link-lib=static=shaderc_combined");
        emit_std_cpp_link();
        return;
    }

    // Initialize explicit libshaderc search directory first
    let mut search_dir = if let Ok(lib_dir) = env::var("SHADERC_LIB_DIR") {
        println!(
            "cargo:warning=Specified {} to search for libshaderc.",
            lib_dir
        );
        Some(lib_dir)
    } else {
        None
    };

    // If no explicit path is set and no explicit request is made to build from
    // source, check known locations before falling back to from-source-build
    if search_dir.is_none() && target_os == "linux" && !config_build_from_source {
        println!(
            "cargo:warning=Checking for system installed libraries.  \
             Use --features = build-from-source to disable this behavior"
        );
        search_dir = Some("/usr/lib/".to_owned());
    }

    // Try to build with the static lib if a path was received or chosen
    let search_dir = if let Some(search_dir) = search_dir {
        let path = Path::new(&search_dir);
        let cannonical = fs::canonicalize(&path);
        if path.is_relative() {
            println!(
                "cargo:warning=Provided path {:?} is relative.  Path must be \
                 relative to shaderc-sys crate, possibly not your current \
                 working directory",
                &path
            );
        } else if path.is_dir() == false {
            println!(
                "cargo:warning=Provided path {:?} is not a directory.",
                &path
            );
        }
        if (cannonical.is_err()) && explicit_lib_dir_set {
            println!("cargo:warning={:?}", cannonical.err().unwrap());
            println!(
                "cargo:warning=Provided path {:?} could not be canonicallized",
                &path
            );
            None
        } else {
            cannonical.ok()
        }
    } else {
        None
    };

    if let Some(search_dir) = search_dir {
        let search_dir_str = search_dir.to_string_lossy();
        let combined_lib_path = search_dir.join(COMBINED_LIB_FILE);
        let dylib_name = format!("{}{}{}", consts::DLL_PREFIX, DYNAMIC_LIB, consts::DLL_SUFFIX);
        let dylib_path = search_dir.join(dylib_name.clone());

        if let Some((lib_dir, lib_name, kind)) = {
            if combined_lib_path.exists() {
                Some((&search_dir_str, COMBINED_LIB, "static"))
            } else if dylib_path.exists() {
                Some((&search_dir_str, DYNAMIC_LIB, "dylib"))
            } else {
                None
            }
        } {
            match (target_os.as_str(), target_env.as_str()) {
                ("linux", _) => {
                    println!("cargo:rustc-link-search=native={}", lib_dir);
                    let spirv_path = search_dir.join(SPIRV_LIB_FILE);
                    if spirv_path.exists() {
                        println!(
                            "cargo:warning=Found SPIRV.  Linking libSPIRV & \
                             libglslang"
                        );
                        println!("cargo:rustc-link-lib=static=SPIRV");
                        println!("cargo:rustc-link-lib=static=SPIRV-Tools-opt");
                        println!("cargo:rustc-link-lib=static=SPIRV-Tools");
                        println!("cargo:rustc-link-lib=glslang");
                    } else {
                        println!(
                            "cargo:warning=Only libshaderc library found.  \
                             Assuming libSPIRV & libglslang built into provided \
                             libshaderc."
                        );
                    }
                    println!("cargo:rustc-link-lib={}={}", kind, lib_name);
                    println!("cargo:rustc-link-lib=dylib=stdc++");
                    return;
                }
                ("windows", "gnu") => {
                    println!(
                        "cargo:warning=Windows MinGW static builds \
                         experimental"
                    );
                    println!("cargo:rustc-link-search=native={}", lib_dir);
                    println!("cargo:rustc-link-lib={}={}", kind, lib_name);
                    println!("cargo:rustc-link-lib=dylib=stdc++");
                    return;
                }
                ("macos", _) => {
                    println!("cargo:warning=MacOS static builds experimental");
                    println!("cargo:rustc-link-search=native={}", lib_dir);
                    println!("cargo:rustc-link-lib={}={}", kind, lib_name);
                    println!("cargo:rustc-link-lib=dylib=c++");
                    return;
                }
                (_, _) => {
                    println!(
                        "cargo:warning=Platform unsupported for pre-built \
                         libshaderc"
                    );
                }
            }
        }
    }

    if config_build_from_source {
        println!("cargo:warning=Requested to build from source");
    } else {
        println!(
            "cargo:warning=Pre-built library not found.  Falling back \
             to from-source build"
        );
    }

    let mut finder = cmd_finder::CommandFinder::new();

    finder.must_have("cmake");
    finder.must_have("git");
    finder.must_have("python");

    let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let shaderc_dir = Path::new(&manifest_dir).join("build");

    let mut lib_path = if target_env == "msvc" {
        finder.must_have("ninja");
        build_shaderc_msvc(&shaderc_dir)
    } else {
        let has_ninja = finder.maybe_have("ninja").is_some();
        build_shaderc(&shaderc_dir, has_ninja)
    };

    lib_path.push("lib");
    println!("cargo:rustc-link-search=native={}", lib_path.display());
    println!("cargo:rustc-link-lib=static=shaderc_combined");

    emit_std_cpp_link();
}

fn emit_std_cpp_link() {
    let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
    let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap();

    match (target_os.as_str(), target_env.as_str()) {
        ("linux", _) | ("windows", "gnu") => println!("cargo:rustc-link-lib=dylib=stdc++"),
        ("macos", _) => println!("cargo:rustc-link-lib=dylib=c++"),
        _ => {}
    }
}
<|endoftext|>


<commit_before>#![cfg_attr(feature="nightly", feature(const_fn, core_intrinsics))]

#[macro_use]
extern crate lazy_static;
use std::collections::HashMap;

lazy_static! {
    /// Documentation!
    pub static ref NUMBER: u32 = times_two(3);

    static ref ARRAY_BOXES: [Box<u32>; 3] = [Box::new(1), Box::new(2), Box::new(3)];

    /// More documentation!
    #[allow(unused_variables)]
    #[derive(Copy, Clone, Debug)]
    pub static ref STRING: String = "hello".to_string();

    static ref HASHMAP: HashMap<u32, &'static str> = {
        let mut m = HashMap::new();
        m.insert(0, "abc");
        m.insert(1, "def");
        m.insert(2, "ghi");
        m
    };

    // This should not compile if the unsafe is removed.
    static ref UNSAFE: u32 = unsafe {
        std::mem::transmute::<i32, u32>(-1)
    };

    // This *should* triggger warn(dead_code) by design.
    static ref UNUSED: () = ();

}

fn times_two(n: u32) -> u32 {
    n * 2
}

#[test]
fn test_basic() {
    assert_eq!(&**STRING, "hello");
    assert_eq!(*NUMBER, 6);
    assert!(HASHMAP.get(&1).is_some());
    assert!(HASHMAP.get(&3).is_none());
    assert_eq!(&*ARRAY_BOXES, &[Box::new(1), Box::new(2), Box::new(3)]);
    assert_eq!(*UNSAFE, std::u32::MAX);
}

#[test]
fn test_repeat() {
    assert_eq!(*NUMBER, 6);
    assert_eq!(*NUMBER, 6);
    assert_eq!(*NUMBER, 6);
}

#[test]
fn test_meta() {
    // this would not compile if STRING were not marked #[derive(Copy, Clone)]
    let copy_of_string = STRING;
    // just to make sure it was copied
    assert!(&STRING as *const _ != &copy_of_string as *const _);

    // this would not compile if STRING were not marked #[derive(Debug)]
    assert_eq!(format!("{:?}", STRING), "STRING { __private_field: () }".to_string());
}

mod visibility {
    lazy_static! {
        pub static ref FOO: Box<u32> = Box::new(0);
    }
}

#[test]
fn test_visibility() {
    assert_eq!(*visibility::FOO, Box::new(0));
}

// This should not cause a warning about a missing Copy implementation
lazy_static! {
    pub static ref VAR: i32 = { 0 };
}

#[derive(Copy, Clone, Debug, PartialEq)]
struct X;
struct Once(X);
const ONCE_INIT: Once = Once(X);
static DATA: X = X;
static ONCE: X = X;
fn require_sync() -> X { X }
fn transmute() -> X { X }
fn __static_ref_initialize() -> X { X }
fn test(_: Vec<X>) -> X { X }

// All these names should not be shadowed
lazy_static! {
    static ref ITEM_NAME_TEST: X = {
        test(vec![X, Once(X).0, ONCE_INIT.0, DATA, ONCE,
                  require_sync(), transmute(),
                  // Except this, which will sadly be shadowed by internals:
                  // __static_ref_initialize()
                  ])
    };
}

#[test]
fn item_name_shadowing() {
    assert_eq!(*ITEM_NAME_TEST, X);
}
<commit_msg>Add a visibility test<commit_after>#![cfg_attr(feature="nightly", feature(const_fn, core_intrinsics))]

#[macro_use]
extern crate lazy_static;
use std::collections::HashMap;

lazy_static! {
    /// Documentation!
    pub static ref NUMBER: u32 = times_two(3);

    static ref ARRAY_BOXES: [Box<u32>; 3] = [Box::new(1), Box::new(2), Box::new(3)];

    /// More documentation!
    #[allow(unused_variables)]
    #[derive(Copy, Clone, Debug)]
    pub static ref STRING: String = "hello".to_string();

    static ref HASHMAP: HashMap<u32, &'static str> = {
        let mut m = HashMap::new();
        m.insert(0, "abc");
        m.insert(1, "def");
        m.insert(2, "ghi");
        m
    };

    // This should not compile if the unsafe is removed.
    static ref UNSAFE: u32 = unsafe {
        std::mem::transmute::<i32, u32>(-1)
    };

    // This *should* triggger warn(dead_code) by design.
    static ref UNUSED: () = ();

}

fn times_two(n: u32) -> u32 {
    n * 2
}

#[test]
fn test_basic() {
    assert_eq!(&**STRING, "hello");
    assert_eq!(*NUMBER, 6);
    assert!(HASHMAP.get(&1).is_some());
    assert!(HASHMAP.get(&3).is_none());
    assert_eq!(&*ARRAY_BOXES, &[Box::new(1), Box::new(2), Box::new(3)]);
    assert_eq!(*UNSAFE, std::u32::MAX);
}

#[test]
fn test_repeat() {
    assert_eq!(*NUMBER, 6);
    assert_eq!(*NUMBER, 6);
    assert_eq!(*NUMBER, 6);
}

#[test]
fn test_meta() {
    // this would not compile if STRING were not marked #[derive(Copy, Clone)]
    let copy_of_string = STRING;
    // just to make sure it was copied
    assert!(&STRING as *const _ != &copy_of_string as *const _);

    // this would not compile if STRING were not marked #[derive(Debug)]
    assert_eq!(format!("{:?}", STRING), "STRING { __private_field: () }".to_string());
}

mod visibility {
    lazy_static! {
        pub static ref FOO: Box<u32> = Box::new(0);
        static ref BAR: Box<u32> = Box::new(98);
    }

    #[test]
    fn sub_test() {
        assert_eq!(**FOO, 0);
        assert_eq!(**BAR, 98);
    }
}

#[test]
fn test_visibility() {
    assert_eq!(*visibility::FOO, Box::new(0));
}

// This should not cause a warning about a missing Copy implementation
lazy_static! {
    pub static ref VAR: i32 = { 0 };
}

#[derive(Copy, Clone, Debug, PartialEq)]
struct X;
struct Once(X);
const ONCE_INIT: Once = Once(X);
static DATA: X = X;
static ONCE: X = X;
fn require_sync() -> X { X }
fn transmute() -> X { X }
fn __static_ref_initialize() -> X { X }
fn test(_: Vec<X>) -> X { X }

// All these names should not be shadowed
lazy_static! {
    static ref ITEM_NAME_TEST: X = {
        test(vec![X, Once(X).0, ONCE_INIT.0, DATA, ONCE,
                  require_sync(), transmute(),
                  // Except this, which will sadly be shadowed by internals:
                  // __static_ref_initialize()
                  ])
    };
}

#[test]
fn item_name_shadowing() {
    assert_eq!(*ITEM_NAME_TEST, X);
}
<|endoftext|>


<commit_before>use std::cmp::Ordering;
use std::ops::Index;

#[derive(Clone, PartialOrd, PartialEq)]
pub enum Value {
    Null, // only used internally - not visible to users
    Bool(bool),
    String(String),
    Float(f64),
}

impl ::std::fmt::Debug for Value {
    fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
        match *self {
            Value::Null => formatter.write_str("null"),
            Value::Bool(bool) => bool.fmt(formatter),
            Value::String(ref string) => string.fmt(formatter),
            Value::Float(float) => float.fmt(formatter),
        };
        Ok(())
    }
}

pub type Id = String; // TODO use uuid?

impl Ord for Value {
    fn cmp(&self, other: &Value) -> Ordering {
        self.partial_cmp(other).unwrap() // TODO this will panic on NaN
    }
}

impl Eq for Value {} // TODO this is unsafe for NaN

impl Value {
    pub fn as_str(&self) -> &str {
        match *self {
            Value::String(ref string) => &*string,
            _ => panic!("Cannot convert this to string: {:?}", self),
        }
    }

    pub fn as_f64(&self) -> f64 {
        match *self {
            Value::Float(float) => float,
            _ => panic!("Cannot convert this to f64: {:?}", self),
        }
    }

    pub fn as_i64(&self) -> i64 {
        match *self {
            Value::Float(float) => {
                let result = float as i64;
                if float == (result as f64) {
                    result
                } else {
                    panic!("Cannot convert this to i64: {:?}", self)
                }
            }
            _ => panic!("Cannot convert this to i64: {:?}", self),
        }
    }

    pub fn as_usize(&self) -> usize {
        match *self {
            Value::Float(float) => {
                let result = float as usize;
                if float == (result as f64) {
                    result
                } else {
                    panic!("Cannot convert this to usize: {:?}", self)
                }
            },
            _ => panic!("Cannot convert this to usize: {:?}", self),
        }
    }
}

pub type Field = Id;

#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Tuple<'a> {
    pub view: &'a str,
    pub names: &'a [String],
    pub values: &'a [Value],
}

impl<'a, 'b> Index<&'b str> for Tuple<'a> {
    type Output = Value;
    fn index<'c>(&'c self, index: &'b str) -> &'c Value {
        let ix = self.names.iter().position(|name| &name[..] == index).unwrap();
        &self.values[ix]
    }
}

impl<'a> ::std::fmt::Debug for Tuple<'a> {
    fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
        let mut debug_struct = formatter.debug_struct(self.view);
        for (name, value) in self.names.iter().zip(self.values.iter()) {
            debug_struct.field(name, value);
        }
        debug_struct.finish();
        Ok(())
    }
}
<commit_msg>Fix warnings<commit_after>use std::cmp::Ordering;
use std::ops::Index;

#[derive(Clone, PartialOrd, PartialEq)]
pub enum Value {
    Null, // only used internally - not visible to users
    Bool(bool),
    String(String),
    Float(f64),
}

impl ::std::fmt::Debug for Value {
    fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
        match *self {
            Value::Null => formatter.write_str("null").unwrap(),
            Value::Bool(bool) => bool.fmt(formatter).unwrap(),
            Value::String(ref string) => string.fmt(formatter).unwrap(),
            Value::Float(float) => float.fmt(formatter).unwrap(),
        };
        Ok(())
    }
}

pub type Id = String; // TODO use uuid?

impl Ord for Value {
    fn cmp(&self, other: &Value) -> Ordering {
        self.partial_cmp(other).unwrap() // TODO this will panic on NaN
    }
}

impl Eq for Value {} // TODO this is unsafe for NaN

impl Value {
    pub fn as_str(&self) -> &str {
        match *self {
            Value::String(ref string) => &*string,
            _ => panic!("Cannot convert this to string: {:?}", self),
        }
    }

    pub fn as_f64(&self) -> f64 {
        match *self {
            Value::Float(float) => float,
            _ => panic!("Cannot convert this to f64: {:?}", self),
        }
    }

    pub fn as_i64(&self) -> i64 {
        match *self {
            Value::Float(float) => {
                let result = float as i64;
                if float == (result as f64) {
                    result
                } else {
                    panic!("Cannot convert this to i64: {:?}", self)
                }
            }
            _ => panic!("Cannot convert this to i64: {:?}", self),
        }
    }

    pub fn as_usize(&self) -> usize {
        match *self {
            Value::Float(float) => {
                let result = float as usize;
                if float == (result as f64) {
                    result
                } else {
                    panic!("Cannot convert this to usize: {:?}", self)
                }
            },
            _ => panic!("Cannot convert this to usize: {:?}", self),
        }
    }
}

pub type Field = Id;

#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Tuple<'a> {
    pub view: &'a str,
    pub names: &'a [String],
    pub values: &'a [Value],
}

impl<'a, 'b> Index<&'b str> for Tuple<'a> {
    type Output = Value;
    fn index<'c>(&'c self, index: &'b str) -> &'c Value {
        let ix = self.names.iter().position(|name| &name[..] == index).unwrap();
        &self.values[ix]
    }
}

impl<'a> ::std::fmt::Debug for Tuple<'a> {
    fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
        let mut debug_struct = formatter.debug_struct(self.view);
        for (name, value) in self.names.iter().zip(self.values.iter()) {
            debug_struct.field(name, value);
        }
        debug_struct.finish().unwrap();
        Ok(())
    }
}
<|endoftext|>


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

use std;
use gl;
use gl::types::{
  GLfloat,
  GLint,
  GLuint,
};
use cgmath::vector::{
  Vec3,
  Vec2,
};
use glh = gl_helpers;
use map::TileIterator;
use color::Color3;
use camera::Camera;
use geom::Geom;

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

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

pub struct TilePicker {
  program: GLuint,
  color_buffer_obj: GLuint,
  mat_id: GLint,
  vertex_buffer_obj: GLuint,
  vertex_data: ~[Vec3<GLfloat>],
  color_data: ~[Color3],
}

impl TilePicker {
  pub fn new() -> TilePicker {
    let picker = TilePicker {
      color_buffer_obj: 0,
      program: 0,
      vertex_buffer_obj: 0,
      mat_id: 0,
      vertex_data: ~[],
      color_data: ~[],
    };
    picker
  }

  pub fn cleanup_opengl(&self) {
    gl::DeleteProgram(self.program);
    glh::delete_buffer(self.vertex_buffer_obj);
    glh::delete_buffer(self.color_buffer_obj);
  }

  fn build_hex_mesh_for_picking(&mut self, geom: &Geom) {
    for tile_pos in TileIterator::new() {
      let pos3d = geom.v2i_to_v2f(tile_pos).extend(0.0);
      for num in range(0, 6) {
        let vertex = geom.index_to_hex_vertex(num);
        let next_vertex = geom.index_to_hex_vertex(num + 1);
        let col_x = tile_pos.x as f32 / 255.0;
        let col_y = tile_pos.y as f32 / 255.0;
        let c_data = &mut self.color_data;
        let v_data = &mut self.vertex_data;
        let color = Color3{r: col_x, g: col_y, b: 1.0};
        v_data.push(pos3d + vertex.extend(0.0));
        c_data.push(color);
        v_data.push(pos3d + next_vertex.extend(0.0));
        c_data.push(color);
        v_data.push(pos3d + Vec3::zero());
        c_data.push(color);
      }
    }
  }

  pub fn init(&mut self, geom: &Geom) {
    self.build_hex_mesh_for_picking(geom);
    self.program = glh::compile_program(
      PICK_VERTEX_SHADER_SRC,
      PICK_FRAGMENT_SHADER_SRC);
    unsafe {
      gl::UseProgram(self.program);
      self.vertex_buffer_obj = glh::gen_buffer();
      gl::BindBuffer(gl::ARRAY_BUFFER, self.vertex_buffer_obj);
      glh::fill_current_coord_vbo(self.vertex_data);
      let pos_attr = glh::get_attr(self.program, "position");
      gl::EnableVertexAttribArray(pos_attr);
      glh::vertex_attrib_pointer(pos_attr);
      gl::GenBuffers(1, &mut self.color_buffer_obj);
      gl::BindBuffer(gl::ARRAY_BUFFER, self.color_buffer_obj);
      glh::fill_current_color_vbo(self.color_data);
      let color_attr = glh::get_attr(self.program, "color");
      gl::EnableVertexAttribArray(color_attr);
      glh::vertex_attrib_pointer(color_attr);
      self.mat_id = glh::get_uniform(self.program, "mvp_mat");
    }
  }

  fn _pick_tile(
    &self,
    win_size: (i32, i32),
    mouse_pos: Vec2<i32>
  ) -> Option<Vec2<i32>> {
    let (_, height) = win_size;
    let reverted_y = height - mouse_pos.y;
    let data: [u8, ..4] = [0, 0, 0, 0]; // mut
    unsafe {
      let data_ptr = std::cast::transmute(&data[0]);
      gl::ReadPixels(
        mouse_pos.x, reverted_y, 1, 1,
        gl::RGBA,
        gl::UNSIGNED_BYTE,
        data_ptr
      );
    }
    if data[2] != 0 {
      Some(Vec2{x: data[0] as i32, y: data[1] as i32})
    } else {
      None
    }
  }

  pub fn pick_tile(
    &mut self,
    win_size: (i32, i32),
    camera: &Camera,
    mouse_pos: Vec2<i32>
  ) -> Option<Vec2<i32>> {
    gl::UseProgram(self.program);
    gl::BindBuffer(gl::ARRAY_BUFFER, self.vertex_buffer_obj);
    gl::BindBuffer(gl::ARRAY_BUFFER, self.color_buffer_obj);
    glh::uniform_mat4f(self.mat_id, &camera.mat());
    gl::ClearColor(0.0, 0.0, 0.0, 1.0);
    gl::Clear(gl::COLOR_BUFFER_BIT);
    glh::draw_mesh(self.vertex_data.len() as int);
    self._pick_tile(win_size, mouse_pos)
  }
}

impl Drop for TilePicker {
  fn drop(&mut self) {
    self.cleanup_opengl();
  }
}

// vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab:
<commit_msg>tile_picker.rs: Removed unsafe<commit_after>// See LICENSE file for copyright and license details.

use std;
use gl;
use gl::types::{
  GLfloat,
  GLint,
  GLuint,
};
use cgmath::vector::{
  Vec3,
  Vec2,
};
use glh = gl_helpers;
use map::TileIterator;
use color::Color3;
use camera::Camera;
use geom::Geom;

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

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

pub struct TilePicker {
  program: GLuint,
  color_buffer_obj: GLuint,
  mat_id: GLint,
  vertex_buffer_obj: GLuint,
  vertex_data: ~[Vec3<GLfloat>],
  color_data: ~[Color3],
}

impl TilePicker {
  pub fn new() -> TilePicker {
    let picker = TilePicker {
      color_buffer_obj: 0,
      program: 0,
      vertex_buffer_obj: 0,
      mat_id: 0,
      vertex_data: ~[],
      color_data: ~[],
    };
    picker
  }

  pub fn cleanup_opengl(&self) {
    gl::DeleteProgram(self.program);
    glh::delete_buffer(self.vertex_buffer_obj);
    glh::delete_buffer(self.color_buffer_obj);
  }

  fn build_hex_mesh_for_picking(&mut self, geom: &Geom) {
    for tile_pos in TileIterator::new() {
      let pos3d = geom.v2i_to_v2f(tile_pos).extend(0.0);
      for num in range(0, 6) {
        let vertex = geom.index_to_hex_vertex(num);
        let next_vertex = geom.index_to_hex_vertex(num + 1);
        let col_x = tile_pos.x as f32 / 255.0;
        let col_y = tile_pos.y as f32 / 255.0;
        let c_data = &mut self.color_data;
        let v_data = &mut self.vertex_data;
        let color = Color3{r: col_x, g: col_y, b: 1.0};
        v_data.push(pos3d + vertex.extend(0.0));
        c_data.push(color);
        v_data.push(pos3d + next_vertex.extend(0.0));
        c_data.push(color);
        v_data.push(pos3d + Vec3::zero());
        c_data.push(color);
      }
    }
  }

  pub fn init(&mut self, geom: &Geom) {
    self.build_hex_mesh_for_picking(geom);
    self.program = glh::compile_program(
      PICK_VERTEX_SHADER_SRC,
      PICK_FRAGMENT_SHADER_SRC);
    gl::UseProgram(self.program);
    self.vertex_buffer_obj = glh::gen_buffer();
    gl::BindBuffer(gl::ARRAY_BUFFER, self.vertex_buffer_obj);
    glh::fill_current_coord_vbo(self.vertex_data);
    let pos_attr = glh::get_attr(self.program, "position");
    gl::EnableVertexAttribArray(pos_attr);
    glh::vertex_attrib_pointer(pos_attr);
    self.color_buffer_obj = glh::gen_buffer();
    gl::BindBuffer(gl::ARRAY_BUFFER, self.color_buffer_obj);
    glh::fill_current_color_vbo(self.color_data);
    let color_attr = glh::get_attr(self.program, "color");
    gl::EnableVertexAttribArray(color_attr);
    glh::vertex_attrib_pointer(color_attr);
    self.mat_id = glh::get_uniform(self.program, "mvp_mat");
  }

  fn _pick_tile(
    &self,
    win_size: (i32, i32),
    mouse_pos: Vec2<i32>
  ) -> Option<Vec2<i32>> {
    let (_, height) = win_size;
    let reverted_y = height - mouse_pos.y;
    let data: [u8, ..4] = [0, 0, 0, 0]; // mut
    unsafe {
      let data_ptr = std::cast::transmute(&data[0]);
      gl::ReadPixels(
        mouse_pos.x, reverted_y, 1, 1,
        gl::RGBA,
        gl::UNSIGNED_BYTE,
        data_ptr
      );
    }
    if data[2] != 0 {
      Some(Vec2{x: data[0] as i32, y: data[1] as i32})
    } else {
      None
    }
  }

  pub fn pick_tile(
    &mut self,
    win_size: (i32, i32),
    camera: &Camera,
    mouse_pos: Vec2<i32>
  ) -> Option<Vec2<i32>> {
    gl::UseProgram(self.program);
    gl::BindBuffer(gl::ARRAY_BUFFER, self.vertex_buffer_obj);
    gl::BindBuffer(gl::ARRAY_BUFFER, self.color_buffer_obj);
    glh::uniform_mat4f(self.mat_id, &camera.mat());
    gl::ClearColor(0.0, 0.0, 0.0, 1.0);
    gl::Clear(gl::COLOR_BUFFER_BIT);
    glh::draw_mesh(self.vertex_data.len() as int);
    self._pick_tile(win_size, mouse_pos)
  }
}

impl Drop for TilePicker {
  fn drop(&mut self) {
    self.cleanup_opengl();
  }
}

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