<commit_before>extern crate getopts;
use getopts::Options;
use std::env;
use std::fs::File;
use std::io;
use std::io::Read;
use std::mem;

fn pointer_size() -> usize {
    let tmp = 0u8;
    let boxed = Box::new(tmp);
    mem::size_of_val(&boxed)
}

fn read_blend_file(inp: &str) -> io::Result<()> {
    // open file
    let file = try!(File::open(inp));
    // read 12 bytes from the Blender file
    let mut take = file.take(12u64);
    let mut header = String::new();
    try!(take.read_to_string(&mut header));
    println!("header = \"{}\"", header);
    // compare first 7 chars to "BLENDER"
    if header.len() >= 7 {
        // create copy of header without moving value
        let mut blender = String::new();
        blender = blender + &header;
        blender.truncate(7); // first 7 chars
        if blender == "BLENDER" {
            println!("starts with \"BLENDER\" ...");
            // TODO: check version (next 5 chars in header)

            // switch to byte copy of String representation
            let bytes = header.into_bytes();
            // check 7th char of header
            println!("7th char of header = '{}'", bytes[7] as char);
            // check for 32-bit pointers vs. 64-bit pointers
            let ptr_size = pointer_size();
            println!("size of pointer in bytes: {}", ptr_size);
            let mut ptr_size_differs = false;
            if bytes[7] as char == '_' {
                // 32-bit pointers expected
                if ptr_size != 4 {
                    ptr_size_differs = true;
                }
                println!("32-bit pointers in file, pointer size differs? {}",
                         ptr_size_differs);
            } else {
                // 64-bit pointers expected
                if ptr_size != 8 {
                        ptr_size_differs = true;
                }
                println!("64-bit pointers in file, pointer size differs? {}",
                         ptr_size_differs);
            }
        }
    } else {
        println!("WARNING: FILE is not a Blender file");
    }
    Ok(())
}

fn do_work(inp: &str, out: Option<String>) {
    println!("FILE = {}", inp);
    match out {
        Some(x) => println!("output file name: {}", x),
        None => println!("no output file name"),
    }
    read_blend_file(inp);
}

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} FILE [options]", program);
    print!("{}", opts.usage(&brief));
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();

    let mut opts = Options::new();
    opts.optopt("o", "", "set output file name", "NAME");
    opts.optflag("h", "help", "print this help menu");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => { panic!(f.to_string()) }
    };
    if matches.opt_present("h") {
        print_usage(&program, opts);
        return;
    }
    let output = matches.opt_str("o");
    let input = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        print_usage(&program, opts);
        return;
    };
    do_work(&input, output);
}
<commit_msg>Use ERROR instead of WARNING. Catch both cases.<commit_after>extern crate getopts;
use getopts::Options;
use std::env;
use std::fs::File;
use std::io;
use std::io::Read;
use std::mem;

fn pointer_size() -> usize {
    let tmp = 0u8;
    let boxed = Box::new(tmp);
    mem::size_of_val(&boxed)
}

fn read_blend_file(inp: &str) -> io::Result<()> {
    // open file
    let file = try!(File::open(inp));
    // read 12 bytes from the Blender file
    let mut take = file.take(12u64);
    let mut header = String::new();
    try!(take.read_to_string(&mut header));
    println!("header = \"{}\"", header);
    // compare first 7 chars to "BLENDER"
    if header.len() >= 7 {
        // create copy of header without moving value
        let mut blender = String::new();
        blender = blender + &header;
        blender.truncate(7); // first 7 chars
        if blender == "BLENDER" {
            println!("starts with \"BLENDER\" ...");
            // TODO: check version (next 5 chars in header)

            // switch to byte copy of String representation
            let bytes = header.into_bytes();
            // check 7th char of header
            println!("7th char of header = '{}'", bytes[7] as char);
            // check for 32-bit pointers vs. 64-bit pointers
            let ptr_size = pointer_size();
            println!("size of pointer in bytes: {}", ptr_size);
            let mut ptr_size_differs = false;
            if bytes[7] as char == '_' {
                // 32-bit pointers expected
                if ptr_size != 4 {
                    ptr_size_differs = true;
                }
                println!("32-bit pointers in file, pointer size differs? {}",
                         ptr_size_differs);
            } else {
                // 64-bit pointers expected
                if ptr_size != 8 {
                        ptr_size_differs = true;
                }
                println!("64-bit pointers in file, pointer size differs? {}",
                         ptr_size_differs);
            }
        } else {
            println!("ERROR: FILE is not a Blender file");
        }
    } else {
        println!("ERROR: FILE is not a Blender file");
    }
    Ok(())
}

fn do_work(inp: &str, out: Option<String>) {
    println!("FILE = {}", inp);
    match out {
        Some(x) => println!("output file name: {}", x),
        None => println!("no output file name"),
    }
    read_blend_file(inp);
}

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} FILE [options]", program);
    print!("{}", opts.usage(&brief));
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();

    let mut opts = Options::new();
    opts.optopt("o", "", "set output file name", "NAME");
    opts.optflag("h", "help", "print this help menu");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => { panic!(f.to_string()) }
    };
    if matches.opt_present("h") {
        print_usage(&program, opts);
        return;
    }
    let output = matches.opt_str("o");
    let input = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        print_usage(&program, opts);
        return;
    };
    do_work(&input, output);
}
<|endoftext|>


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

// Check that when a `let`-binding occurs in a loop, its associated
// drop-flag is reinitialized (to indicate "needs-drop" at the end of
// the owning variable's scope).

struct A<'a>(&'a mut i32);

impl<'a> Drop for A<'a> {
    fn drop(&mut self) {
        *self.0 += 1;
    }
}

fn main() {
    let mut cnt = 0;
    for i in 0..2 {
        let a = A(&mut cnt);
        if i == 1 { // Note that
            break;  //  both this break
        }           //   and also
        drop(a);    //    this move of `a`
        // are necessary to expose the bug
    }
    assert_eq!(cnt, 2);
}
<commit_msg>placate the pretty tests by ignoring my test.<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-pretty #27582

// Check that when a `let`-binding occurs in a loop, its associated
// drop-flag is reinitialized (to indicate "needs-drop" at the end of
// the owning variable's scope).

struct A<'a>(&'a mut i32);

impl<'a> Drop for A<'a> {
    fn drop(&mut self) {
        *self.0 += 1;
    }
}

fn main() {
    let mut cnt = 0;
    for i in 0..2 {
        let a = A(&mut cnt);
        if i == 1 { // Note that
            break;  //  both this break
        }           //   and also
        drop(a);    //    this move of `a`
        // are necessary to expose the bug
    }
    assert_eq!(cnt, 2);
}
<|endoftext|>


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

#![deny(nonstandard_style)]
#![allow(dead_code)]

fn CamelCase() {} //~ ERROR should have a snake

#[allow(bad_style)]
mod test {
    fn CamelCase() {}

    #[forbid(bad_style)]
    mod bad {
        fn CamelCase() {} //~ ERROR should have a snake

        static bad: isize = 1; //~ ERROR should have an upper
    }

    mod warn {
        #![warn(bad_style)]

        fn CamelCase() {} //~ WARN should have a snake

        struct snake_case; //~ WARN should have a camel
    }
}

fn main() {}
<commit_msg>Fix internal references to bad_style in test code.<commit_after>// Copyright 2014–2017 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.

#![deny(nonstandard_style)]
#![allow(dead_code)]

fn CamelCase() {} //~ ERROR should have a snake

#[allow(nonstandard_style)]
mod test {
    fn CamelCase() {}

    #[forbid(nonstandard_style)]
    mod bad {
        fn CamelCase() {} //~ ERROR should have a snake

        static bad: isize = 1; //~ ERROR should have an upper
    }

    mod warn {
        #![warn(nonstandard_style)]

        fn CamelCase() {} //~ WARN should have a snake

        struct snake_case; //~ WARN should have a camel
    }
}

fn main() {}
<|endoftext|>


<commit_before>// Simple QuadTree
// Alexis Andre (@mactuitui)

use nannou::prelude::*;

pub struct QuadTree<T> {
    indices: [usize; 4],
    num: usize,
    pub x: f32,
    pub y: f32,
    pub width: f32,
    pub height: f32,
    whatever: Option<T>,
    pub children: Option<[Box<QuadTree<T>>; 4]>,
}

pub trait WithPos {
    fn get_pos(&self) -> Vector2;
}

impl<T: WithPos> QuadTree<T> {
    pub fn new() -> Self {
        QuadTree {
            indices: [0; 4],
            num: 0,
            x: 0.0,
            y: 0.0,
            width: 1024.0,
            height: 1024.0,
            whatever: None,
            children: None,
        }
    }

    pub fn contains(&self, point: &T) -> bool {
        let pos = point.get_pos();
        pos.x >= self.x - self.width * 0.5
            && pos.x < self.x + self.width * 0.5
            && pos.y >= self.y - self.height * 0.5
            && pos.y < self.y + self.height * 0.5
    }

    //split in four
    //mutates self
    pub fn split(&mut self, elements: &Vec<T>) {
        //let new_children =
        let mut southwest: Box<QuadTree<T>> = Box::new(QuadTree::<T> {
            indices: [0; 4],
            num: 0,
            x: self.x - self.width * 0.25,
            y: self.y - self.height * 0.25,
            width: self.width * 0.5,
            height: self.height * 0.5,
            whatever: None,
            children: None,
        });
        let mut southeast: Box<QuadTree<T>> = Box::new(QuadTree::<T> {
            indices: [0; 4],
            num: 0,
            x: self.x + self.width * 0.25,
            y: self.y - self.height * 0.25,
            width: self.width * 0.5,
            height: self.height * 0.5,
            whatever: None,
            children: None,
        });
        let mut northwest: Box<QuadTree<T>> = Box::new(QuadTree::<T> {
            indices: [0; 4],
            num: 0,
            x: self.x - self.width * 0.25,
            y: self.y + self.height * 0.25,
            width: self.width * 0.5,
            height: self.height * 0.5,
            whatever: None,
            children: None,
        });
        let mut northeast: Box<QuadTree<T>> = Box::new(QuadTree::<T> {
            indices: [0; 4],
            num: 0,
            x: self.x + self.width * 0.25,
            y: self.y + self.height * 0.25,
            width: self.width * 0.5,
            height: self.height * 0.5,
            whatever: None,
            children: None,
        });
        //push the elements down the children
        for k in 0..self.num {
            let point = &elements[self.indices[k]];
            if northwest.contains(&point) {
                northwest.insert(elements, self.indices[k]);
            } else if northeast.contains(point) {
                northeast.insert(elements, self.indices[k]);
            } else if southeast.contains(point) {
                southeast.insert(elements, self.indices[k]);
            } else if southwest.contains(point) {
                southwest.insert(elements, self.indices[k]);
            }
        }
        self.children = Some([northwest, northeast, southwest, southeast]);
    }

    pub fn insert_children(&mut self, elements: &Vec<T>, index: usize) {
        match self.children.as_mut() {
            Some(children) => {
                //TODO faster sort
                if children[0].contains(&elements[index]) {
                    children[0].insert(elements, index);
                } else if children[1].contains(&elements[index]) {
                    children[1].insert(elements, index);
                } else if children[2].contains(&elements[index]) {
                    children[2].insert(elements, index);
                } else if children[3].contains(&elements[index]) {
                    children[3].insert(elements, index);
                }
            }
            None => {}
        }
    }

    pub fn intersects(&self, x: f32, y: f32, dist: f32) -> bool {
        //think of the inverse, if one rect is completely on the side of another
        if x + dist < self.x - self.width * 0.5 || x - dist > self.x + self.width * 0.5 {
            return false;
        }
        if y + dist < self.y - self.height * 0.5 || y - dist > self.y + self.height * 0.5 {
            return false;
        }

        return true;
    }

    pub fn get_elements(&self, elements: &Vec<T>, x: f32, y: f32, dist: f32) -> Vec<usize> {
        let mut result: Vec<usize> = Vec::new();

        //are we intersecting the rect
        if self.intersects(x, y, dist) {
            //if we have children, recurse
            match &self.children {
                Some(children) => {
                    let mut r0 = children[0].get_elements(elements, x, y, dist);
                    let mut r1 = children[1].get_elements(elements, x, y, dist);
                    let mut r2 = children[2].get_elements(elements, x, y, dist);
                    let mut r3 = children[3].get_elements(elements, x, y, dist);
                    result.append(&mut r0);
                    result.append(&mut r1);
                    result.append(&mut r2);
                    result.append(&mut r3);
                }
                None => {
                    //no children, return all elements?
                    for i in 0..self.num {
                        result.push(self.indices[i]);
                    }
                }
            }
        }
        result
    }

    pub fn insert(&mut self, elements: &Vec<T>, index: usize) {
        //have we split?
        match &self.children {
            Some(_children) => {
                self.insert_children(elements, index);
            }
            None => {
                if self.num < 4 {
                    self.indices[self.num] = index;
                    self.num += 1;
                } else {
                    //we are full
                    // we must split and push down the elements
                    self.split(elements);
                    //add this to children
                    self.insert_children(elements, index);
                }
            }
        }
    }
}
<commit_msg>Fix warning in offline example quadtree module<commit_after>// Simple QuadTree
// Alexis Andre (@mactuitui)

use nannou::prelude::*;

pub struct QuadTree {
    indices: [usize; 4],
    num: usize,
    pub x: f32,
    pub y: f32,
    pub width: f32,
    pub height: f32,
    pub children: Option<[Box<QuadTree>; 4]>,
}

pub trait WithPos {
    fn get_pos(&self) -> Vector2;
}

impl QuadTree {
    pub fn new() -> Self {
        QuadTree {
            indices: [0; 4],
            num: 0,
            x: 0.0,
            y: 0.0,
            width: 1024.0,
            height: 1024.0,
            children: None,
        }
    }

    pub fn contains<T: WithPos>(&self, point: &T) -> bool {
        let pos = point.get_pos();
        pos.x >= self.x - self.width * 0.5
            && pos.x < self.x + self.width * 0.5
            && pos.y >= self.y - self.height * 0.5
            && pos.y < self.y + self.height * 0.5
    }

    //split in four
    //mutates self
    pub fn split<T: WithPos>(&mut self, elements: &[T]) {
        //let new_children =
        let mut southwest: Box<QuadTree> = Box::new(QuadTree {
            indices: [0; 4],
            num: 0,
            x: self.x - self.width * 0.25,
            y: self.y - self.height * 0.25,
            width: self.width * 0.5,
            height: self.height * 0.5,
            children: None,
        });
        let mut southeast: Box<QuadTree> = Box::new(QuadTree {
            indices: [0; 4],
            num: 0,
            x: self.x + self.width * 0.25,
            y: self.y - self.height * 0.25,
            width: self.width * 0.5,
            height: self.height * 0.5,
            children: None,
        });
        let mut northwest: Box<QuadTree> = Box::new(QuadTree {
            indices: [0; 4],
            num: 0,
            x: self.x - self.width * 0.25,
            y: self.y + self.height * 0.25,
            width: self.width * 0.5,
            height: self.height * 0.5,
            children: None,
        });
        let mut northeast: Box<QuadTree> = Box::new(QuadTree {
            indices: [0; 4],
            num: 0,
            x: self.x + self.width * 0.25,
            y: self.y + self.height * 0.25,
            width: self.width * 0.5,
            height: self.height * 0.5,
            children: None,
        });
        //push the elements down the children
        for k in 0..self.num {
            let point = &elements[self.indices[k]];
            if northwest.contains(point) {
                northwest.insert(elements, self.indices[k]);
            } else if northeast.contains(point) {
                northeast.insert(elements, self.indices[k]);
            } else if southeast.contains(point) {
                southeast.insert(elements, self.indices[k]);
            } else if southwest.contains(point) {
                southwest.insert(elements, self.indices[k]);
            }
        }
        self.children = Some([northwest, northeast, southwest, southeast]);
    }

    pub fn insert_children<T: WithPos>(&mut self, elements: &[T], index: usize) {
        match self.children.as_mut() {
            Some(children) => {
                //TODO faster sort
                if children[0].contains(&elements[index]) {
                    children[0].insert(elements, index);
                } else if children[1].contains(&elements[index]) {
                    children[1].insert(elements, index);
                } else if children[2].contains(&elements[index]) {
                    children[2].insert(elements, index);
                } else if children[3].contains(&elements[index]) {
                    children[3].insert(elements, index);
                }
            }
            None => {}
        }
    }

    pub fn intersects(&self, x: f32, y: f32, dist: f32) -> bool {
        //think of the inverse, if one rect is completely on the side of another
        if x + dist < self.x - self.width * 0.5 || x - dist > self.x + self.width * 0.5 {
            return false;
        }
        if y + dist < self.y - self.height * 0.5 || y - dist > self.y + self.height * 0.5 {
            return false;
        }

        return true;
    }

    pub fn get_elements<T: WithPos>(&self, elements: &[T], x: f32, y: f32, dist: f32) -> Vec<usize> {
        let mut result: Vec<usize> = Vec::new();

        //are we intersecting the rect
        if self.intersects(x, y, dist) {
            //if we have children, recurse
            match &self.children {
                Some(children) => {
                    let mut r0 = children[0].get_elements(elements, x, y, dist);
                    let mut r1 = children[1].get_elements(elements, x, y, dist);
                    let mut r2 = children[2].get_elements(elements, x, y, dist);
                    let mut r3 = children[3].get_elements(elements, x, y, dist);
                    result.append(&mut r0);
                    result.append(&mut r1);
                    result.append(&mut r2);
                    result.append(&mut r3);
                }
                None => {
                    //no children, return all elements?
                    for i in 0..self.num {
                        result.push(self.indices[i]);
                    }
                }
            }
        }
        result
    }

    pub fn insert<T: WithPos>(&mut self, elements: &[T], index: usize) {
        //have we split?
        match &self.children {
            Some(_children) => {
                self.insert_children(elements, index);
            }
            None => {
                if self.num < 4 {
                    self.indices[self.num] = index;
                    self.num += 1;
                } else {
                    //we are full
                    // we must split and push down the elements
                    self.split(elements);
                    //add this to children
                    self.insert_children(elements, index);
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Gfx-rs Developers.
//
// 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.

extern crate cgmath;
#[macro_use]
extern crate gfx;
extern crate gfx_window_glfw;
extern crate glfw;
extern crate time;
extern crate gfx_gl as gl;

use time::precise_time_s;
use cgmath::{SquareMatrix, Matrix, Point3, Vector3, Matrix3, Matrix4};
use cgmath::{Transform, AffineMatrix3, Vector4};
pub use gfx::format::{DepthStencil, Rgba8};
use glfw::Context;
use gl::Gl;
use gl::types::*;
use std::mem;
use std::ptr;
use std::str;
use std::env;
use std::str::FromStr;
use std::sync::mpsc::Receiver;
use std::iter::repeat;
use std::ffi::CString;

gfx_defines!{
    vertex Vertex {
        pos: [f32; 3] = "a_Pos",
    }

    pipeline pipe {
        vbuf: gfx::VertexBuffer<Vertex> = (),
        transform: gfx::Global<[[f32; 4]; 4]> = "u_Transform",
        out_color: gfx::RenderTarget<Rgba8> = "o_Color",
        out_depth: gfx::DepthTarget<DepthStencil> =
            gfx::preset::depth::LESS_EQUAL_WRITE,
    }
}

static VERTEX_SRC: &'static [u8] = b"
    #version 150 core
    in vec3 a_Pos;
    uniform mat4 u_Transform;

    void main() {
        gl_Position = u_Transform * vec4(a_Pos, 1.0);
    }
";

static FRAGMENT_SRC: &'static [u8] = b"
    #version 150 core
    out vec4 o_Color;

    void main() {
        o_Color = vec4(1., 0., 0., 1.);
    }
";

//----------------------------------------

fn gfx_main(mut glfw: glfw::Glfw,
            mut window: glfw::Window,
            events: Receiver<(f64, glfw::WindowEvent)>,
            dimension: i16) {
    use gfx::traits::{Device, FactoryExt};

    let (mut device, mut factory, main_color, main_depth) =
        gfx_window_glfw::init(&mut window);
    let mut encoder: gfx::Encoder<_,_> = factory.create_command_buffer().into();

    let pso = factory.create_pipeline_simple(
        VERTEX_SRC, FRAGMENT_SRC,
        gfx::state::CullFace::Back,
        pipe::new()
        ).unwrap();

    let vertex_data = [
        Vertex { pos: [-1.0,  1.0, -1.0] },
        Vertex { pos: [ 1.0,  1.0, -1.0] },
        Vertex { pos: [ 1.0,  1.0,  1.0] },
    ];
    let (vbuf, slice) = factory.create_vertex_buffer(&vertex_data);

    let view: AffineMatrix3<f32> = Transform::look_at(
        Point3::new(0f32, -5.0, 0.0),
        Point3::new(0f32, 0.0, 0.0),
        Vector3::unit_z(),
    );
    let aspect = {
        let (w, h) = window.get_framebuffer_size();
        w as f32 / h as f32
    };
    let proj = cgmath::perspective(cgmath::deg(45.0f32), aspect, 1.0, 10.0);

    let mut data = pipe::Data {
        vbuf: vbuf,
        transform: cgmath::Matrix4::identity().into(),
        out_color: main_color,
        out_depth: main_depth,
    };

    while !window.should_close() {
        glfw.poll_events();
        for (_, event) in glfw::flush_messages(&events) {
            match event {
                glfw::WindowEvent::Key(glfw::Key::Escape, _, glfw::Action::Press, _) =>
                    window.set_should_close(true),
                _ => {},
            }
        }

        let start = precise_time_s() * 1000.;
//        encoder.reset();
        encoder.clear(&data.out_color, [0.3, 0.3, 0.3, 1.0]);
        encoder.clear_depth(&data.out_depth, 1.0);

        for x in (-dimension) ..dimension {
            for y in (-dimension) ..dimension {
                let mut model = Matrix4::from(Matrix3::identity() * 0.01f32);
                model.w = Vector4::new(x as f32 * 0.05,
                                       0f32,
                                       y as f32 * 0.05,
                                       1f32);
                data.transform = (proj * view.mat * model).into();
                encoder.draw(&slice, &pso, &data);
            }
        }

        let pre_submit = precise_time_s() * 1000.;
        encoder.flush(&mut device);
        let post_submit = precise_time_s() * 1000.;
        window.swap_buffers();
        device.cleanup();
        let swap = precise_time_s() * 1000.;

        println!("total time:\t\t{0:4.2}ms", swap - start);
        println!("\tcreate list:\t{0:4.2}ms", pre_submit - start);
        println!("\tsubmit:\t\t{0:4.2}ms", post_submit - pre_submit);
        println!("\tgpu wait:\t{0:4.2}ms", swap - post_submit)
    }
}

fn compile_shader(gl: &Gl, src: &[u8], ty: GLenum) -> GLuint { unsafe {
    let shader = gl.CreateShader(ty);
    // Attempt to compile the shader
    gl.ShaderSource(shader, 1,
        &(src.as_ptr() as *const i8),
        &(src.len() as GLint));
    gl.CompileShader(shader);

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

    // Fail on error
    if status != (gl::TRUE as GLint) {
        let mut len: GLint = 0;
        gl.GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
        let mut buf: Vec<u8> = repeat(0u8).take((len as isize).saturating_sub(1) as usize).collect();     // subtract 1 to skip the trailing null character
        gl.GetShaderInfoLog(shader, len, ptr::null_mut(), buf.as_mut_ptr() as *mut GLchar);
        panic!("{}", str::from_utf8(&buf).ok().expect("ShaderInfoLog not valid utf8"));
    }
    shader
}}

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

    // Fail on error
    if status != (gl::TRUE as GLint) {
        let mut len: GLint = 0;
        gl.GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
        let mut buf: Vec<u8> = repeat(0u8).take((len as isize).saturating_sub(1) as usize).collect();     // subtract 1 to skip the trailing null character
        gl.GetProgramInfoLog(program, len, ptr::null_mut(), buf.as_mut_ptr() as *mut GLchar);
        panic!("{}", str::from_utf8(&buf).ok().expect("ProgramInfoLog not valid utf8"));
    }
    program
}}

fn gl_main(mut glfw: glfw::Glfw,
           mut window: glfw::Window,
           _: Receiver<(f64, glfw::WindowEvent),>,
           dimension: i16) {
    let gl = Gl::load_with(|s| window.get_proc_address(s) as *const _);

    // Create GLSL shaders
    let vs = compile_shader(&gl, VERTEX_SRC, gl::VERTEX_SHADER);
    let fs = compile_shader(&gl, FRAGMENT_SRC, gl::FRAGMENT_SHADER);
    let program = link_program(&gl, vs, fs);

    let mut vao = 0;
    let mut vbo = 0;

    let trans_uniform = unsafe {
        // Create Vertex Array Object
        gl.GenVertexArrays(1, &mut vao);
        gl.BindVertexArray(vao);

        // Create a Vertex Buffer Object and copy the vertex data to it
        gl.GenBuffers(1, &mut vbo);
        gl.BindBuffer(gl::ARRAY_BUFFER, vbo);

        let vertex_data = vec![
            Vertex { pos: [-1.0,  1.0, -1.0] },
            Vertex { pos: [ 1.0,  1.0, -1.0] },
            Vertex { pos: [ 1.0,  1.0,  1.0] },
        ];

        gl.BufferData(gl::ARRAY_BUFFER,
                      (vertex_data.len() * mem::size_of::<Vertex>()) as GLsizeiptr,
                      mem::transmute(&vertex_data[0]),
                      gl::STATIC_DRAW);

        // Use shader program
        gl.UseProgram(program);
        let o_color = CString::new("o_Color").unwrap();
        gl.BindFragDataLocation(program, 0, o_color.as_bytes_with_nul().as_ptr() as *const i8);

        // Specify the layout of the vertex data
        let a_pos = CString::new("a_Pos").unwrap();
        gl.BindFragDataLocation(program, 0, a_pos.as_bytes_with_nul().as_ptr() as *const i8);

        let pos_attr = gl.GetAttribLocation(program, a_pos.as_ptr());
        gl.EnableVertexAttribArray(pos_attr as GLuint);
        gl.VertexAttribPointer(pos_attr as GLuint, 3, gl::BYTE,
                                gl::FALSE as GLboolean, 0, ptr::null());

        let u_transform = CString::new("u_Transform").unwrap();
        gl.GetUniformLocation(program, u_transform.as_bytes_with_nul().as_ptr() as *const i8)
    };

    let (w, h) = window.get_framebuffer_size();
    let view: AffineMatrix3<f32> = Transform::look_at(
        Point3::new(0f32, -5.0, 0.0),
        Point3::new(0f32, 0.0, 0.0),
        Vector3::unit_z(),
    );
    let aspect = w as f32 / h as f32;
    let proj = cgmath::perspective(cgmath::deg(45.0f32), aspect, 1.0, 10.0);

    while !window.should_close() {
        // Poll events
        glfw.poll_events();

        let start = precise_time_s() * 1000.;

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

        for x in (-dimension) ..dimension {
            for y in (-dimension) ..dimension {
                let mut model = Matrix4::from(Matrix3::identity() * 0.01f32);
                model.w = Vector4::new(x as f32 * 0.05,
                                       0f32,
                                       y as f32 * 0.05,
                                       1f32);

                let mat = proj * view.mat * model;

                unsafe {
                    gl.UniformMatrix4fv(trans_uniform,
                                        1,
                                        gl::FALSE,
                                        mat.as_ptr());
                    gl.DrawArrays(gl::TRIANGLES, 0, 3);
                }

            }
        }

        let submit = precise_time_s() * 1000.;

        // Swap buffers
        window.swap_buffers();
        let swap = precise_time_s() * 1000.;

        println!("total time:\t\t{0:4.2}ms", swap - start);
        println!("\tsubmit:\t\t{0:4.2}ms", submit - start);
        println!("\tgpu wait:\t{0:4.2}ms", swap - submit)

    }

    // Cleanup
    unsafe {
        gl.DeleteProgram(program);
        gl.DeleteShader(fs);
        gl.DeleteShader(vs);
        gl.DeleteBuffers(1, &vbo);
        gl.DeleteVertexArrays(1, &vao);
    }
}

pub fn main() {
    let ref mut args = env::args();
    let args_count = env::args().count();
    if args_count == 1 {
        println!("gfx-perf [gl|gfx] <size>");
        return;
    }

    let mode = args.nth(1).unwrap();
    let count: i32 = if args_count == 3 {
        FromStr::from_str(&args.next().unwrap()).ok()
    } else {
        None
    }.unwrap_or(10000);

    let count = ((count as f64).sqrt() / 2.) as i16;

    let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS)
        .ok().expect("Failed to initialize glfw-rs");

    glfw.window_hint(glfw::WindowHint::ContextVersion(3, 2));
    glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));
    glfw.window_hint(glfw::WindowHint::OpenGlProfile(glfw::OpenGlProfileHint::Core));

    let (mut window, events) = glfw
        .create_window(640, 480, "Cube example", glfw::WindowMode::Windowed)
        .expect("Failed to create GLFW window.");

    window.make_current();
    glfw.set_error_callback(glfw::FAIL_ON_ERRORS);
    window.set_key_polling(true);

    println!("count is {}", count*count*4);
    match mode.as_ref() {
        "gfx" => gfx_main(glfw, window, events, count),
        "gl" => gl_main(glfw, window, events, count),
        x => {
            println!("{} is not a known mode", x)
        }
    }
}
<commit_msg>Refactoring of the performance example<commit_after>// Copyright 2014 The Gfx-rs Developers.
//
// 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.

extern crate cgmath;
#[macro_use]
extern crate gfx;
extern crate gfx_core;
extern crate gfx_window_glfw;
extern crate glfw;
extern crate time;
extern crate gfx_gl as gl;
extern crate gfx_device_gl;

use time::precise_time_s;
use cgmath::{SquareMatrix, Matrix, Point3, Vector3, Matrix3, Matrix4};
use cgmath::{Transform, Vector4};
pub use gfx::format::{DepthStencil, Rgba8 as ColorBuffer};
use glfw::Context;
use gl::Gl;
use gl::types::*;
use std::mem;
use std::ptr;
use std::str;
use std::env;
use std::str::FromStr;
//use std::sync::mpsc::Receiver;
use std::iter::repeat;
use std::ffi::CString;
use gfx_device_gl::{Resources as R, CommandBuffer as CB};
use gfx_core::Device;

gfx_defines!{
    vertex Vertex {
        pos: [f32; 3] = "a_Pos",
    }

    pipeline pipe {
        vbuf: gfx::VertexBuffer<Vertex> = (),
        transform: gfx::Global<[[f32; 4]; 4]> = "u_Transform",
        out_color: gfx::RenderTarget<ColorBuffer> = "o_Color",
    }
}

static VERTEX_SRC: &'static [u8] = b"
    #version 150 core
    in vec3 a_Pos;
    uniform mat4 u_Transform;

    void main() {
        gl_Position = u_Transform * vec4(a_Pos, 1.0);
   }
";

static FRAGMENT_SRC: &'static [u8] = b"
    #version 150 core
    out vec4 o_Color;

    void main() {
        o_Color = vec4(1.0, 0.0, 0.0, 1.0);
    }
";

static VERTEX_DATA: &'static [Vertex] = &[
    Vertex { pos: [-1.0, 0.0, -1.0] },
    Vertex { pos: [ 1.0, 0.0, -1.0] },
    Vertex { pos: [-1.0, 0.0,  1.0] },
];

const CLEAR_COLOR: (f32, f32, f32, f32) = (0.3, 0.3, 0.3, 1.0);

//----------------------------------------

fn transform(x: i16, y: i16, proj_view: &Matrix4<f32>) -> Matrix4<f32> {
    let mut model = Matrix4::from(Matrix3::identity() * 0.05);
    model.w = Vector4::new(x as f32 * 0.10,
                           0f32,
                           y as f32 * 0.10,
                           1f32);
    proj_view * model
}

trait Renderer: Drop {
    fn render(&mut self, window: &mut glfw::Window, proj_view: &Matrix4<f32>);
}

struct GFX {
    device:gfx_device_gl::Device,
    encoder: gfx::Encoder<R,CB>,
    data: pipe::Data<R>,
    pso: gfx::PipelineState<R, pipe::Meta>,
    slice: gfx::Slice<R>,
    dimension: i16,
}

impl GFX {
    fn new(window: &mut glfw::Window, dimension: i16) -> Self {
        use gfx::traits::FactoryExt;

        let (device, mut factory, main_color, _) =
            gfx_window_glfw::init(window);
        let encoder: gfx::Encoder<_,_> = factory.create_command_buffer().into();

        let pso = factory.create_pipeline_simple(
            VERTEX_SRC, FRAGMENT_SRC,
            gfx::state::CullFace::Nothing,
            pipe::new()
        ).unwrap();

        let (vbuf, slice) = factory.create_vertex_buffer(VERTEX_DATA);

        let data = pipe::Data {
            vbuf: vbuf,
            transform: cgmath::Matrix4::identity().into(),
            out_color: main_color,
        };

        GFX {
            device: device,
            encoder: encoder,
            data: data,
            pso: pso,
            slice: slice,
            dimension: dimension,
        }
    }
}

impl Renderer for GFX {
    fn render(&mut self, window: &mut glfw::Window, proj_view:&Matrix4<f32>) {
        let start = precise_time_s() * 1000.;
        self.encoder.clear(&self.data.out_color, [CLEAR_COLOR.0,
                                                  CLEAR_COLOR.1,
                                                  CLEAR_COLOR.2,
                                                  CLEAR_COLOR.3]);

        for x in (-self.dimension) ..self.dimension {
            for y in (-self.dimension) ..self.dimension {
                self.data.transform = transform(x, y, proj_view).into();
                self.encoder.draw(&self.slice, &self.pso, &self.data);
            }
        }

        let pre_submit = precise_time_s() * 1000.;
        self.encoder.flush(&mut self.device);
        let post_submit = precise_time_s() * 1000.;
        window.swap_buffers();
        self.device.cleanup();
        let swap = precise_time_s() * 1000.;

        println!("total time:\t\t{0:4.2}ms", swap - start);
        println!("\tcreate list:\t{0:4.2}ms", pre_submit - start);
        println!("\tsubmit:\t\t{0:4.2}ms", post_submit - pre_submit);
        println!("\tgpu wait:\t{0:4.2}ms", swap - post_submit);
    }
}

impl Drop for GFX {
    fn drop(&mut self) {
    }
}

struct GL {
    gl:Gl,
    trans_uniform:GLint,
    vs:GLuint,
    fs:GLuint,
    program:GLuint,
    vbo:GLuint,
    vao:GLuint,
    dimension:i16,
}

impl GL {
    fn new(window: &mut glfw::Window, dimension: i16) -> Self {
        let gl = Gl::load_with(|s| window.get_proc_address(s) as *const _);

        fn compile_shader (gl:&Gl, src: &[u8], ty: GLenum) -> GLuint {
            unsafe {
                let shader = gl.CreateShader(ty);
                // Attempt to compile the shader
                gl.ShaderSource(shader, 1,
                                &(src.as_ptr() as *const i8),
                                &(src.len() as GLint));
                gl.CompileShader(shader);

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

                // Fail on error
                if status != (gl::TRUE as GLint) {
                    let mut len: GLint = 0;
                    gl.GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
                    let mut buf: Vec<u8> = repeat(0u8).take((len as isize).saturating_sub(1) as usize).collect();     // subtract 1 to skip the trailing null character
                    gl.GetShaderInfoLog(shader, len, ptr::null_mut(), buf.as_mut_ptr() as *mut GLchar);
                    panic!("{}", str::from_utf8(&buf).ok().expect("ShaderInfoLog not valid utf8"));
                }
                shader
            }
        };

        // Create GLSL shaders
        let vs = compile_shader(&gl, VERTEX_SRC, gl::VERTEX_SHADER);
        let fs = compile_shader(&gl, FRAGMENT_SRC, gl::FRAGMENT_SHADER);

        // Link program
        let program;
        unsafe {
            program = gl.CreateProgram();
            gl.AttachShader(program, vs);
            gl.AttachShader(program, fs);
            gl.LinkProgram(program);
            // Get the link status
            let mut status = gl::FALSE as GLint;
            gl.GetProgramiv(program, gl::LINK_STATUS, &mut status);

            // Fail on error
            if status != (gl::TRUE as GLint) {
                let mut len: GLint = 0;
                gl.GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
                let mut buf: Vec<u8> = repeat(0u8).take((len as isize).saturating_sub(1) as usize).collect();     // subtract 1 to skip the trailing null character
                gl.GetProgramInfoLog(program, len, ptr::null_mut(), buf.as_mut_ptr() as *mut GLchar);
                panic!("{}", str::from_utf8(&buf).ok().expect("ProgramInfoLog not valid utf8"));
            }
        }

        let mut vao = 0;
        let mut vbo = 0;

        let trans_uniform;
        unsafe {
            // Create Vertex Array Object
            gl.GenVertexArrays(1, &mut vao);
            gl.BindVertexArray(vao);

            // Create a Vertex Buffer Object and copy the vertex data to it
            gl.GenBuffers(1, &mut vbo);
            gl.BindBuffer(gl::ARRAY_BUFFER, vbo);

            gl.BufferData(gl::ARRAY_BUFFER,
                          (VERTEX_DATA.len() * mem::size_of::<Vertex>()) as GLsizeiptr,
                          mem::transmute(&VERTEX_DATA[0]),
                          gl::STATIC_DRAW);

            // Use shader program
            gl.UseProgram(program);
            let o_color = CString::new("o_Color").unwrap();
            gl.BindFragDataLocation(program, 0, o_color.as_bytes_with_nul().as_ptr() as *const i8);

            // Specify the layout of the vertex data
            let a_pos = CString::new("a_Pos").unwrap();
            gl.BindFragDataLocation(program, 0, a_pos.as_bytes_with_nul().as_ptr() as *const i8);

            let pos_attr = gl.GetAttribLocation(program, a_pos.as_ptr());
            gl.EnableVertexAttribArray(pos_attr as GLuint);
            gl.VertexAttribPointer(pos_attr as GLuint, 3, gl::FLOAT,
                                   gl::FALSE as GLboolean, 0, ptr::null());

            let u_transform = CString::new("u_Transform").unwrap();
            trans_uniform = gl.GetUniformLocation(program, u_transform.as_bytes_with_nul().as_ptr() as *const i8)
        };

        GL {
            gl: gl,
            vs: vs,
            fs: fs,
            program: program,
            vbo: vbo,
            vao: vao,
            trans_uniform: trans_uniform,
            dimension: dimension,
        }
    }
}

impl Renderer for GL {
    fn render(&mut self, window: &mut glfw::Window, proj_view: &Matrix4<f32>) {
        let start = precise_time_s() * 1000.;

        // Clear the screen to black
        unsafe {
            self.gl.ClearColor(CLEAR_COLOR.0, CLEAR_COLOR.1, CLEAR_COLOR.2, CLEAR_COLOR.3);
            self.gl.Clear(gl::COLOR_BUFFER_BIT);
        }

        for x in (-self.dimension) ..self.dimension {
            for y in (-self.dimension) ..self.dimension {
                let mat:Matrix4<f32> = transform(x, y, proj_view).into();

                unsafe {
                    self.gl.UniformMatrix4fv(self.trans_uniform,
                                             1,
                                             gl::FALSE,
                                             mat.as_ptr());
                    self.gl.DrawArrays(gl::TRIANGLES, 0, 3);
                }

            }
        }

        let submit = precise_time_s() * 1000.;

        // Swap buffers
        window.swap_buffers();
        let swap = precise_time_s() * 1000.;

        println!("total time:\t\t{0:4.2}ms", swap - start);
        println!("\tsubmit:\t\t{0:4.2}ms", submit - start);
        println!("\tgpu wait:\t{0:4.2}ms", swap - submit)
    }
}

impl Drop for GL {
    fn drop(&mut self) {
        unsafe {
            self.gl.DeleteProgram(self.program);
            self.gl.DeleteShader(self.fs);
            self.gl.DeleteShader(self.vs);
            self.gl.DeleteBuffers(1, &self.vbo);
            self.gl.DeleteVertexArrays(1, &self.vao);
        }
    }
}

fn main() {
    let ref mut args = env::args();
    let args_count = env::args().count();
    if args_count == 1 {
        println!("gfx-perf [gl|gfx] <size>");
        return;
    }

    let mode = args.nth(1).unwrap();
    let count: i32 = if args_count == 3 {
        FromStr::from_str(&args.next().unwrap()).ok()
    } else {
        None
    }.unwrap_or(10000);

    let count = ((count as f64).sqrt() / 2.) as i16;

    let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS)
        .ok().expect("Failed to initialize glfw-rs");

    glfw.window_hint(glfw::WindowHint::ContextVersion(3, 2));
    glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));
    glfw.window_hint(glfw::WindowHint::OpenGlProfile(glfw::OpenGlProfileHint::Core));

    let (mut window, events) = glfw
        .create_window(640, 480, "Performance example", glfw::WindowMode::Windowed)
        .expect("Failed to create GLFW window.");

    window.make_current();
    glfw.set_error_callback(glfw::FAIL_ON_ERRORS);
    window.set_key_polling(true);

    let proj_view = {
        let view = Matrix4::look_at(
            Point3::new(0f32, 5.0, -5.0),
            Point3::new(0f32, 0.0, 0.0),
            Vector3::unit_z(),
        );

        let proj = {
            let aspect = {
                let (w, h) = window.get_framebuffer_size();
                w as f32 / h as f32
            };
            cgmath::perspective(cgmath::deg(45.0f32), aspect, 1.0, 10.0)
        };
        proj * view
    };

    let mut r: Box<Renderer>;
    match mode.as_ref() {
        "gfx" => r = Box::new(GFX::new(&mut window, count)),
        "gl" => r = Box::new(GL::new(&mut window, count)),
        x => {
            panic!("{} is not a known mode", x)
        }
    }

    println!("count is {}", count*count*4);

    while !window.should_close() {
        // Poll events
        glfw.poll_events();
        for (_, event) in glfw::flush_messages(&events) {
            match event {
                glfw::WindowEvent::Key(glfw::Key::Escape, _, glfw::Action::Press, _) =>
                    window.set_should_close(true),
                _ => {},
            }
        }
        r.render(&mut window, &proj_view);
    }
}
<|endoftext|>


<commit_before>use toml_edit;

#[derive(Debug, Hash, PartialEq, Eq, Clone)]
enum DependencySource {
    Version {
        version: Option<String>,
        path: Option<String>,
    },
    Git(String),
}

/// A dependency handled by Cargo
#[derive(Debug, Hash, PartialEq, Eq, Clone)]
pub struct Dependency {
    /// The name of the dependency (as it is set in its `Cargo.toml` and known to crates.io)
    pub name: String,
    optional: bool,
    default_features: bool,
    source: DependencySource,
}

impl Default for Dependency {
    fn default() -> Dependency {
        Dependency {
            name: "".into(),
            optional: false,
            default_features: true,
            source: DependencySource::Version {
                version: None,
                path: None,
            },
        }
    }
}

impl Dependency {
    /// Create a new dependency with a name
    pub fn new(name: &str) -> Dependency {
        Dependency {
            name: name.into(),
            ..Dependency::default()
        }
    }

    /// Set dependency to a given version
    pub fn set_version(mut self, version: &str) -> Dependency {
        let old_source = self.source;
        let old_path = match old_source {
            DependencySource::Version { path, .. } => path,
            _ => None,
        };
        self.source = DependencySource::Version {
            version: Some(version.into()),
            path: old_path,
        };
        self
    }

    /// Set dependency to a given repository
    pub fn set_git(mut self, repo: &str) -> Dependency {
        self.source = DependencySource::Git(repo.into());
        self
    }

    /// Set dependency to a given path
    pub fn set_path(mut self, path: &str) -> Dependency {
        let old_source = self.source;
        let old_version = match old_source {
            DependencySource::Version { version, .. } => version,
            _ => None,
        };
        self.source = DependencySource::Version {
            version: old_version,
            path: Some(path.into()),
        };
        self
    }

    /// Set whether the dependency is optional
    pub fn set_optional(mut self, opt: bool) -> Dependency {
        self.optional = opt;
        self
    }

    /// Set the value of default-features for the dependency
    pub fn set_default_features(mut self, default_features: bool) -> Dependency {
        self.default_features = default_features;
        self
    }

    /// Get version of dependency
    pub fn version(&self) -> Option<&str> {
        if let DependencySource::Version {
            version: Some(ref version),
            ..
        } = self.source
        {
            Some(version)
        } else {
            None
        }
    }

    /// Convert dependency to TOML
    ///
    /// Returns a tuple with the dependency's name and either the version as a `String`
    /// or the path/git repository as an `InlineTable`.
    /// (If the dependency is set as `optional` or `default-features` is set to `false`,
    /// an `InlineTable` is returned in any case.)
    pub fn to_toml(&self) -> (String, toml_edit::Item) {
        let data: toml_edit::Item = match (self.optional, self.default_features, self.source.clone()) {
            // Extra short when version flag only
            (
                false,
                true,
                DependencySource::Version {
                    version: Some(v),
                    path: None,
                },
            ) => toml_edit::value(v),
            // Other cases are represented as an inline table
            (optional, default_features, source) => {
                let mut data = toml_edit::InlineTable::default();

                match source {
                    DependencySource::Version { version, path } => {
                        if let Some(v) = version {
                            data.get_or_insert("version", v);
                        }
                        if let Some(p) = path {
                            data.get_or_insert("path", p);
                        }
                    }
                    DependencySource::Git(v) => {
                        data.get_or_insert("git", v);
                    }
                }
                if self.optional {
                    data.get_or_insert("optional", optional);
                }
                if !self.default_features {
                    data.get_or_insert("default-features", default_features);
                }

                data.fmt();
                toml_edit::value(toml_edit::Value::InlineTable(data))
            }
        };

        (self.name.clone(), data)
    }
}
<commit_msg>work with rustfmt<commit_after>use toml_edit;

#[derive(Debug, Hash, PartialEq, Eq, Clone)]
enum DependencySource {
    Version {
        version: Option<String>,
        path: Option<String>,
    },
    Git(String),
}

/// A dependency handled by Cargo
#[derive(Debug, Hash, PartialEq, Eq, Clone)]
pub struct Dependency {
    /// The name of the dependency (as it is set in its `Cargo.toml` and known to crates.io)
    pub name: String,
    optional: bool,
    default_features: bool,
    source: DependencySource,
}

impl Default for Dependency {
    fn default() -> Dependency {
        Dependency {
            name: "".into(),
            optional: false,
            default_features: true,
            source: DependencySource::Version {
                version: None,
                path: None,
            },
        }
    }
}

impl Dependency {
    /// Create a new dependency with a name
    pub fn new(name: &str) -> Dependency {
        Dependency {
            name: name.into(),
            ..Dependency::default()
        }
    }

    /// Set dependency to a given version
    pub fn set_version(mut self, version: &str) -> Dependency {
        let old_source = self.source;
        let old_path = match old_source {
            DependencySource::Version { path, .. } => path,
            _ => None,
        };
        self.source = DependencySource::Version {
            version: Some(version.into()),
            path: old_path,
        };
        self
    }

    /// Set dependency to a given repository
    pub fn set_git(mut self, repo: &str) -> Dependency {
        self.source = DependencySource::Git(repo.into());
        self
    }

    /// Set dependency to a given path
    pub fn set_path(mut self, path: &str) -> Dependency {
        let old_source = self.source;
        let old_version = match old_source {
            DependencySource::Version { version, .. } => version,
            _ => None,
        };
        self.source = DependencySource::Version {
            version: old_version,
            path: Some(path.into()),
        };
        self
    }

    /// Set whether the dependency is optional
    pub fn set_optional(mut self, opt: bool) -> Dependency {
        self.optional = opt;
        self
    }

    /// Set the value of default-features for the dependency
    pub fn set_default_features(mut self, default_features: bool) -> Dependency {
        self.default_features = default_features;
        self
    }

    /// Get version of dependency
    pub fn version(&self) -> Option<&str> {
        if let DependencySource::Version {
            version: Some(ref version),
            ..
        } = self.source
        {
            Some(version)
        } else {
            None
        }
    }

    /// Convert dependency to TOML
    ///
    /// Returns a tuple with the dependency's name and either the version as a `String`
    /// or the path/git repository as an `InlineTable`.
    /// (If the dependency is set as `optional` or `default-features` is set to `false`,
    /// an `InlineTable` is returned in any case.)
    pub fn to_toml(&self) -> (String, toml_edit::Item) {
        let data: toml_edit::Item =
            match (self.optional, self.default_features, self.source.clone()) {
                // Extra short when version flag only
                (
                    false,
                    true,
                    DependencySource::Version {
                        version: Some(v),
                        path: None,
                    },
                ) => toml_edit::value(v),
                // Other cases are represented as an inline table
                (optional, default_features, source) => {
                    let mut data = toml_edit::InlineTable::default();

                    match source {
                        DependencySource::Version { version, path } => {
                            if let Some(v) = version {
                                data.get_or_insert("version", v);
                            }
                            if let Some(p) = path {
                                data.get_or_insert("path", p);
                            }
                        }
                        DependencySource::Git(v) => {
                            data.get_or_insert("git", v);
                        }
                    }
                    if self.optional {
                        data.get_or_insert("optional", optional);
                    }
                    if !self.default_features {
                        data.get_or_insert("default-features", default_features);
                    }

                    data.fmt();
                    toml_edit::value(toml_edit::Value::InlineTable(data))
                }
            };

        (self.name.clone(), data)
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016-2020 Fabian Schuiki

//! Procedural macros for the moore compiler.

use proc_macro::TokenStream;
use quote::{quote, ToTokens};
use syn::{parse_macro_input, DeriveInput};

fn is_child_field(field: &syn::Field) -> bool {
    let tystr = field.ty.to_token_stream().to_string();
    if tystr.chars().nth(0).unwrap().is_lowercase() {
        return false;
    }
    if tystr == "Span" || tystr == "Spanned" {
        return false;
    }
    if field
        .attrs
        .iter()
        .any(|attr| attr.path.to_token_stream().to_string() == "ignore_child")
    {
        return false;
    }
    true
}

#[proc_macro_derive(CommonNode, attributes(ignore_child))]
pub fn derive_common_node(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);
    // println!("derive(CommonNode) on `{}`", input.ident);

    // Assemble the body of the `children()` method.
    let mut child_fields = vec![];
    match &input.data {
        syn::Data::Struct(data) => match &data.fields {
            syn::Fields::Named(fields) => {
                for field in &fields.named {
                    if is_child_field(field) {
                        let n = field.ident.as_ref().unwrap();
                        child_fields.push(quote! { #n });
                    }
                }
            }
            syn::Fields::Unnamed(fields) => {
                for (i, field) in fields.unnamed.iter().enumerate() {
                    if is_child_field(field) {
                        let i = syn::Index::from(i);
                        child_fields.push(quote! { #i });
                    }
                }
            }
            syn::Fields::Unit => (),
        },
        syn::Data::Enum(_data) => (),
        syn::Data::Union(_) => (),
    }

    // Emit the trait implementation.
    let name = &input.ident;
    let generics = &input.generics;
    let output = quote! {
        impl #generics CommonNode for #name #generics {
            fn for_each_child(&self, f: &mut dyn FnMut(&dyn CommonNode)) {
                #( f(&self.#child_fields); )*
            }
        }
    };
    output.into()
}
<commit_msg>derive: Fix proc_macro for rust v1.38<commit_after>// Copyright (c) 2016-2020 Fabian Schuiki

//! Procedural macros for the moore compiler.

extern crate proc_macro;
use proc_macro::TokenStream;
use quote::{quote, ToTokens};
use syn::{parse_macro_input, DeriveInput};

fn is_child_field(field: &syn::Field) -> bool {
    let tystr = field.ty.to_token_stream().to_string();
    if tystr.chars().nth(0).unwrap().is_lowercase() {
        return false;
    }
    if tystr == "Span" || tystr == "Spanned" {
        return false;
    }
    if field
        .attrs
        .iter()
        .any(|attr| attr.path.to_token_stream().to_string() == "ignore_child")
    {
        return false;
    }
    true
}

#[proc_macro_derive(CommonNode, attributes(ignore_child))]
pub fn derive_common_node(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);
    // println!("derive(CommonNode) on `{}`", input.ident);

    // Assemble the body of the `children()` method.
    let mut child_fields = vec![];
    match &input.data {
        syn::Data::Struct(data) => match &data.fields {
            syn::Fields::Named(fields) => {
                for field in &fields.named {
                    if is_child_field(field) {
                        let n = field.ident.as_ref().unwrap();
                        child_fields.push(quote! { #n });
                    }
                }
            }
            syn::Fields::Unnamed(fields) => {
                for (i, field) in fields.unnamed.iter().enumerate() {
                    if is_child_field(field) {
                        let i = syn::Index::from(i);
                        child_fields.push(quote! { #i });
                    }
                }
            }
            syn::Fields::Unit => (),
        },
        syn::Data::Enum(_data) => (),
        syn::Data::Union(_) => (),
    }

    // Emit the trait implementation.
    let name = &input.ident;
    let generics = &input.generics;
    let output = quote! {
        impl #generics CommonNode for #name #generics {
            fn for_each_child(&self, f: &mut dyn FnMut(&dyn CommonNode)) {
                #( f(&self.#child_fields); )*
            }
        }
    };
    output.into()
}
<|endoftext|>


<commit_before>// TODO: get num cols of terminal dynamically

use super::{Report, ReportKind, RemarkKind};
use code::{FileMap, LineIdx};
use term_painter::{ToStyle, Attr};
use term_painter::Color::*;
use std::default::Default;

/// Options for printing
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct PrintOptions {
    /// Use of unicode allowed?
    pub unicode: bool,
    /// Use of colors allowed?
    pub color: bool,
    /// Is line wrapping allowed?
    pub line_wrap: bool,
}

impl Default for PrintOptions {
    fn default() -> Self {
        PrintOptions {
            unicode: true,
            color: true,
            line_wrap: true,
        }
    }
}

pub fn print(rep: &Report, src: &FileMap, _: PrintOptions) {
    // print header
    let title = match rep.kind {
        ReportKind::Error => White.bold().bg(Red).paint("ERROR"),
        ReportKind::Warning => White.bold().bg(Yellow).paint("WARNING"),
    };

    let line = if rep.span.is_dummy() {
        "<dummy-span>".into()
    } else {
        let start = src.get_loc(rep.span.lo);
        let end = src.get_loc(rep.span.hi);
        if start.line != end.line {
            format!("{}-{}", start.line.0, end.line.0)
        } else {
            start.line.0.to_string()
        }
    };

    println!("+---- {} in {} : {} ----+",
        title,
        src.filename(),
        Blue.paint(line)
    );

    for rem in &rep.remarks {
        // print message
        let (title, title_len) = match rem.kind {
            RemarkKind::Error => (Red.paint("error:"), 6),
            RemarkKind::Warning => (Yellow.paint("warning:"), 8),
            RemarkKind::Note => (Green.paint("note:"), 5),
        };

        print!("      =====>  {} ", title);
        // spaces + big arrow + spaces + title + space
        let indent = 6 + 6 + 2 + title_len + 1;
        let block_width = 80 - indent;

        let mut col = 0;
        for word in rem.desc.split_whitespace() {
            let word_len = word.chars().count();
            if col + word_len >= block_width && col != 0 {
                println!("");
                print!("           >  {0:>1$} ", " ", title_len);
                col = 0;
            }
            print!("{} ", White.bold().paint(word));
            col += word_len + 1;
        }
        println!("");

        // print code snippet
        if let Some(span) = rem.span {
            let start = src.get_loc(span.lo);
            let end = src.get_loc(span.hi);

            if span.is_dummy() {
                println!("!!! no snippet due to <dummy-span> !!!");
            } else if start.line == end.line {
                if let Some(line) = src.get_line(start.line) {
                    println!("{:>#4} {} {}",
                        Magenta.bold().paint(start.line),
                        Magenta.bold().paint("|"),
                        line
                    );

                    Yellow.with(|| {
                        println!("       {: <2$}{:-<3$}",
                            " ", "^",
                            start.col.0 as usize,
                            (end.col.0 - start.col.0) as usize
                        );
                    });
                }
            } else {
                for line_idx in start.line.0..end.line.0 + 1 {
                    let line_idx = LineIdx(line_idx);
                    if let Some(line) = src.get_line(line_idx) {
                        println!("{:>#4} {} {}",
                            Magenta.bold().paint(line_idx),
                            Magenta.bold().paint("|"),
                            line
                        );
                    }
                }
            }
            println!("");
        }

    }
    println!("");
}
<commit_msg>Fix line number printing in header line<commit_after>// TODO: get num cols of terminal dynamically

use super::{Report, ReportKind, RemarkKind};
use code::{FileMap, LineIdx};
use term_painter::ToStyle;
use term_painter::Color::*;
use std::default::Default;

/// Options for printing
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct PrintOptions {
    /// Use of unicode allowed?
    pub unicode: bool,
    /// Use of colors allowed?
    pub color: bool,
    /// Is line wrapping allowed?
    pub line_wrap: bool,
}

impl Default for PrintOptions {
    fn default() -> Self {
        PrintOptions {
            unicode: true,
            color: true,
            line_wrap: true,
        }
    }
}

pub fn print(rep: &Report, src: &FileMap, _: PrintOptions) {
    // print header
    let title = match rep.kind {
        ReportKind::Error => White.bold().bg(Red).paint("ERROR"),
        ReportKind::Warning => White.bold().bg(Yellow).paint("WARNING"),
    };

    let line = if rep.span.is_dummy() {
        "<dummy-span>".into()
    } else {
        let start = src.get_loc(rep.span.lo);
        let end = src.get_loc(rep.span.hi);
        if start.line != end.line {
            format!("{}-{}", start.line, end.line)
        } else {
            start.line.to_string()
        }
    };

    println!("+---- {} in {} : {} ----+",
        title,
        src.filename(),
        Blue.paint(line)
    );

    for rem in &rep.remarks {
        // print message
        let (title, title_len) = match rem.kind {
            RemarkKind::Error => (Red.paint("error:"), 6),
            RemarkKind::Warning => (Yellow.paint("warning:"), 8),
            RemarkKind::Note => (Green.paint("note:"), 5),
        };

        print!("      =====>  {} ", title);
        // spaces + big arrow + spaces + title + space
        let indent = 6 + 6 + 2 + title_len + 1;
        let block_width = 80 - indent;

        let mut col = 0;
        for word in rem.desc.split_whitespace() {
            let word_len = word.chars().count();
            if col + word_len >= block_width && col != 0 {
                println!("");
                print!("           >  {0:>1$} ", " ", title_len);
                col = 0;
            }
            print!("{} ", White.bold().paint(word));
            col += word_len + 1;
        }
        println!("");

        // print code snippet
        if let Some(span) = rem.span {
            let start = src.get_loc(span.lo);
            let end = src.get_loc(span.hi);

            if span.is_dummy() {
                println!("!!! no snippet due to <dummy-span> !!!");
            } else if start.line == end.line {
                if let Some(line) = src.get_line(start.line) {
                    println!("{:>#4} {} {}",
                        Magenta.bold().paint(start.line),
                        Magenta.bold().paint("|"),
                        line
                    );

                    Yellow.with(|| {
                        println!("       {: <2$}{:-<3$}",
                            " ", "^",
                            start.col.0 as usize,
                            (end.col.0 - start.col.0) as usize
                        );
                    });
                }
            } else {
                for line_idx in start.line.0..end.line.0 + 1 {
                    let line_idx = LineIdx(line_idx);
                    if let Some(line) = src.get_line(line_idx) {
                        println!("{:>#4} {} {}",
                            Magenta.bold().paint(line_idx),
                            Magenta.bold().paint("|"),
                            line
                        );
                    }
                }
            }
            println!("");
        }

    }
    println!("");
}
<|endoftext|>


<commit_before>//! CUDA driver
//!
//! Reference: http://docs.nvidia.com/cuda/cuda-driver-api/

use std::ffi::CStr;
use std::marker::PhantomData;
use std::{mem, ptr, result};

#[allow(dead_code)]
#[allow(non_camel_case_types)]
#[allow(non_snake_case)]
#[allow(non_upper_case_globals)]
mod ll;

/// A CUDA "block"
pub struct Block {
    x: u32,
    y: u32,
    z: u32,
}

impl Block {
    /// One dimensional block
    pub fn x(x: u32) -> Self {
        Block { x: x, y: 1, z: 1 }
    }

    /// Two dimensional block
    pub fn xy(x: u32, y: u32) -> Self {
        Block { x: x, y: y, z: 1 }
    }

    /// Three dimensional block
    pub fn xyz(x: u32, y: u32, z: u32) -> Self {
        Block { x: x, y: y, z: z }
    }
}

/// A CUDA "context"
#[derive(Debug)]
pub struct Context {
    defused: bool,
    handle: ll::CUcontext,
}

impl Context {
    // TODO is this actually useful? Note that we are using "RAII" (cf. `drop`)
    // and ownership to manage `Context`es
    #[allow(dead_code)]
    fn current() -> Result<Option<Self>> {
        let mut handle = ptr::null_mut();

        unsafe { lift(ll::cuCtxGetCurrent(&mut handle))? }

        if handle.is_null() {
            Ok(None)
        } else {
            Ok(Some(Context {
                defused: true,
                handle: handle,
            }))
        }
    }

    /// Loads a PTX module
    pub fn load_module<'ctx>(&'ctx self, image: &CStr) -> Result<Module<'ctx>> {
        let mut handle = ptr::null_mut();

        unsafe {
            lift(ll::cuModuleLoadData(&mut handle, image.as_ptr() as *const _))?
        }

        Ok(Module {
            handle: handle,
            _context: PhantomData,
        })
    }
}

impl Drop for Context {
    fn drop(&mut self) {
        if !self.defused {
            unsafe { lift(ll::cuCtxDestroy_v2(self.handle)).unwrap() }
        }
    }
}

/// A CUDA device (a GPU)
#[derive(Debug)]
pub struct Device {
    handle: ll::CUdevice,
}

/// Binds to the `nth` device
#[allow(non_snake_case)]
pub fn Device(nth: u16) -> Result<Device> {
    let mut handle = 0;

    unsafe { lift(ll::cuDeviceGet(&mut handle, i32::from(nth)))? }

    Ok(Device { handle: handle })
}

impl Device {
    /// Returns the number of available devices
    pub fn count() -> Result<u32> {
        let mut count: i32 = 0;

        unsafe { lift(ll::cuDeviceGetCount(&mut count))? }

        Ok(count as u32)
    }

    /// Creates a CUDA context for this device
    pub fn create_context(&self) -> Result<Context> {
        let mut handle = ptr::null_mut();
        // TODO expose
        let flags = 0;

        unsafe { lift(ll::cuCtxCreate_v2(&mut handle, flags, self.handle))? }

        Ok(Context {
            defused: false,
            handle: handle,
        })
    }

    /// Returns the maximum number of threads a block can have
    pub fn max_threads_per_block(&self) -> Result<i32> {
        use self::ll::CUdevice_attribute_enum::*;

        self.get(CU_DEVICE_ATTRIBUTE_MAX_THREADS_PER_BLOCK)
    }

    /// Returns the total amount of (non necessarily free) memory, in bytes,
    /// that the device has
    pub fn total_memory(&self) -> Result<usize> {
        let mut bytes = 0;

        unsafe { lift(ll::cuDeviceTotalMem_v2(&mut bytes, self.handle))? };

        Ok(bytes)
    }

    fn get(&self, attr: ll::CUdevice_attribute) -> Result<i32> {
        let mut value = 0;

        unsafe {
            lift(ll::cuDeviceGetAttribute(&mut value, attr, self.handle))?
        }

        Ok(value)
    }
}

/// A function that the CUDA device can execute. AKA a "kernel"
pub struct Function<'ctx: 'm, 'm> {
    handle: ll::CUfunction,
    _module: PhantomData<&'m Module<'ctx>>,
}

impl<'ctx, 'm> Function<'ctx, 'm> {
    /// Execute a function on the GPU
    ///
    /// NOTE This function blocks until the GPU has finished executing the
    /// kernel
    pub fn launch(&self,
                  args: &[&Any],
                  grid: Grid,
                  block: Block)
                  -> Result<()> {
        let stream = Stream::new()?;
        // TODO expose
        let shared_mem_bytes = 0;
        // TODO expose
        let extra = ptr::null_mut();

        unsafe {
            lift(ll::cuLaunchKernel(self.handle,
                                    grid.x,
                                    grid.y,
                                    grid.z,
                                    block.x,
                                    block.y,
                                    block.z,
                                    shared_mem_bytes,
                                    stream.handle,
                                    args.as_ptr() as *mut _,
                                    extra))?
        }

        stream.sync()?;
        stream.destroy()
    }
}

/// A CUDA "grid"
pub struct Grid {
    x: u32,
    y: u32,
    z: u32,
}

impl Grid {
    /// One dimensional grid
    pub fn x(x: u32) -> Self {
        Grid { x: x, y: 1, z: 1 }
    }

    /// Two dimensional grid
    pub fn xy(x: u32, y: u32) -> Self {
        Grid { x: x, y: y, z: 1 }
    }

    /// Three dimensional grid
    pub fn xyz(x: u32, y: u32, z: u32) -> Self {
        Grid { x: x, y: y, z: z }
    }
}

/// A PTX module
pub struct Module<'ctx> {
    handle: ll::CUmodule,
    _context: PhantomData<&'ctx Context>,
}

impl<'ctx> Module<'ctx> {
    /// Retrieves a function from the PTX module
    pub fn function<'m>(&'m self, name: &CStr) -> Result<Function<'ctx, 'm>> {
        let mut handle = ptr::null_mut();

        unsafe {
            lift(ll::cuModuleGetFunction(&mut handle,
                                         self.handle,
                                         name.as_ptr()))?
        }

        Ok(Function {
            handle: handle,
            _module: PhantomData,
        })
    }
}

impl<'ctx> Drop for Module<'ctx> {
    fn drop(&mut self) {
        unsafe { lift(ll::cuModuleUnload(self.handle)).unwrap() }
    }
}

// TODO expose
struct Stream {
    handle: ll::CUstream,
}

impl Stream {
    fn new() -> Result<Self> {
        let mut handle = ptr::null_mut();
        // TODO expose
        let flags = 0;

        unsafe { lift(ll::cuStreamCreate(&mut handle, flags))? }

        Ok(Stream { handle: handle })
    }

    fn destroy(self) -> Result<()> {
        unsafe { lift(ll::cuStreamDestroy_v2(self.handle)) }
    }

    fn sync(&self) -> Result<()> {
        unsafe { lift(ll::cuStreamSynchronize(self.handle)) }
    }
}

/// Value who's type has been erased
pub enum Any {}

/// Erase the type of a value
#[allow(non_snake_case)]
pub fn Any<T>(ref_: &T) -> &Any {
    unsafe { &*(ref_ as *const T as *const Any) }
}

/// `memcpy` direction
pub enum Direction {
    /// `src` points to device memory. `dst` points to host memory
    DeviceToHost,
    /// `src` points to host memory. `dst` points to device memory
    HostToDevice,
}

#[allow(missing_docs)]
#[derive(Debug)]
pub enum Error {
    AlreadyAcquired,
    AlreadyMapped,
    ArrayIsMapped,
    Assert,
    ContextAlreadyCurrent,
    ContextAlreadyInUse,
    ContextIsDestroyed,
    Deinitialized,
    EccUncorrectable,
    FileNotFound,
    HardwareStackError,
    HostMemoryAlreadyRegistered,
    HostMemoryNotRegistered,
    IllegalAddress,
    IllegalInstruction,
    InvalidAddressSpace,
    InvalidContext,
    InvalidDevice,
    InvalidGraphicsContext,
    InvalidHandle,
    InvalidImage,
    InvalidPc,
    InvalidPtx,
    InvalidSource,
    InvalidValue,
    LaunchFailed,
    LaunchIncompatibleTexturing,
    LaunchOutOfResources,
    LaunchTimeout,
    MapFailed,
    MisalignedAddress,
    NoBinaryForGpu,
    NoDevice,
    NotFound,
    NotInitialized,
    NotMapped,
    NotMappedAsArray,
    NotMappedAsPointer,
    NotPermitted,
    NotReady,
    NotSupported,
    NvlinkUncorrectable,
    OperatingSystem,
    OutOfMemory,
    PeerAccessAlreadyEnabled,
    PeerAccessNotEnabled,
    PeerAccessUnsupported,
    PrimaryContextActive,
    ProfilerAlreadyStarted,
    ProfilerAlreadyStopped,
    ProfilerDisabled,
    ProfilerNotInitialized,
    SharedObjectInitFailed,
    SharedObjectSymbolNotFound,
    TooManyPeers,
    Unknown,
    UnmapFailed,
    UnsupportedLimit,
}

// TODO should this be a method of `Context`?
/// Allocate `n` bytes of memory on the device
pub unsafe fn allocate(n: usize) -> Result<*mut u8> {
    let mut d_ptr = 0;

    lift(ll::cuMemAlloc_v2(&mut d_ptr, n))?;

    Ok(d_ptr as *mut u8)
}

/// Copy `n` bytes of memory from `src` to `dst`
///
/// `direction` indicates where `src` and `dst` are located (device or host)
pub unsafe fn copy<T>(src: *const T,
                      dst: *mut T,
                      count: usize,
                      direction: Direction)
                      -> Result<()> {
    use self::Direction::*;

    let bytes = count * mem::size_of::<T>();

    lift(match direction {
        DeviceToHost => ll::cuMemcpyDtoH_v2(dst as *mut _, src as u64, bytes),
        HostToDevice => ll::cuMemcpyHtoD_v2(dst as u64, src as *const _, bytes),
    })?;

    Ok(())
}

// TODO same question as `allocate`
/// Free the memory pointed to by `ptr`
pub unsafe fn deallocate(ptr: *mut u8) -> Result<()> {
    lift(ll::cuMemFree_v2(ptr as u64))
}

/// Initialize the CUDA runtime
pub fn initialize() -> Result<()> {
    // TODO expose
    let flags = 0;

    unsafe { lift(ll::cuInit(flags)) }
}

/// Returns the version of the CUDA runtime
pub fn version() -> Result<i32> {
    let mut version = 0;

    unsafe { lift(ll::cuDriverGetVersion(&mut version))? }

    Ok(version)
}

#[allow(missing_docs)]
pub type Result<T> = result::Result<T, Error>;

fn lift(e: ll::CUresult) -> Result<()> {
    use self::Error::*;
    use self::ll::cudaError_enum::*;

    Err(match e {
        CUDA_SUCCESS => return Ok(()),
        CUDA_ERROR_ALREADY_ACQUIRED => AlreadyAcquired,
        CUDA_ERROR_ALREADY_MAPPED => AlreadyMapped,
        CUDA_ERROR_ARRAY_IS_MAPPED => ArrayIsMapped,
        CUDA_ERROR_ASSERT => Assert,
        CUDA_ERROR_CONTEXT_ALREADY_CURRENT => ContextAlreadyCurrent,
        CUDA_ERROR_CONTEXT_ALREADY_IN_USE => ContextAlreadyInUse,
        CUDA_ERROR_CONTEXT_IS_DESTROYED => ContextIsDestroyed,
        CUDA_ERROR_DEINITIALIZED => Deinitialized,
        CUDA_ERROR_ECC_UNCORRECTABLE => EccUncorrectable,
        CUDA_ERROR_FILE_NOT_FOUND => FileNotFound,
        CUDA_ERROR_HARDWARE_STACK_ERROR => HardwareStackError,
        CUDA_ERROR_HOST_MEMORY_ALREADY_REGISTERED => {
            HostMemoryAlreadyRegistered
        }
        CUDA_ERROR_HOST_MEMORY_NOT_REGISTERED => HostMemoryNotRegistered,
        CUDA_ERROR_ILLEGAL_ADDRESS => IllegalAddress,
        CUDA_ERROR_ILLEGAL_INSTRUCTION => IllegalInstruction,
        CUDA_ERROR_INVALID_ADDRESS_SPACE => InvalidAddressSpace,
        CUDA_ERROR_INVALID_CONTEXT => InvalidContext,
        CUDA_ERROR_INVALID_DEVICE => InvalidDevice,
        CUDA_ERROR_INVALID_GRAPHICS_CONTEXT => InvalidGraphicsContext,
        CUDA_ERROR_INVALID_HANDLE => InvalidHandle,
        CUDA_ERROR_INVALID_IMAGE => InvalidImage,
        CUDA_ERROR_INVALID_PC => InvalidPc,
        CUDA_ERROR_INVALID_PTX => InvalidPtx,
        CUDA_ERROR_INVALID_SOURCE => InvalidSource,
        CUDA_ERROR_INVALID_VALUE => InvalidValue,
        CUDA_ERROR_LAUNCH_FAILED => LaunchFailed,
        CUDA_ERROR_LAUNCH_INCOMPATIBLE_TEXTURING => LaunchIncompatibleTexturing,
        CUDA_ERROR_LAUNCH_OUT_OF_RESOURCES => LaunchOutOfResources,
        CUDA_ERROR_LAUNCH_TIMEOUT => LaunchTimeout,
        CUDA_ERROR_MAP_FAILED => MapFailed,
        CUDA_ERROR_MISALIGNED_ADDRESS => MisalignedAddress,
        CUDA_ERROR_NOT_FOUND => NotFound,
        CUDA_ERROR_NOT_INITIALIZED => NotInitialized,
        CUDA_ERROR_NOT_MAPPED => NotMapped,
        CUDA_ERROR_NOT_MAPPED_AS_ARRAY => NotMappedAsArray,
        CUDA_ERROR_NOT_MAPPED_AS_POINTER => NotMappedAsPointer,
        CUDA_ERROR_NOT_PERMITTED => NotPermitted,
        CUDA_ERROR_NOT_READY => NotReady,
        CUDA_ERROR_NOT_SUPPORTED => NotSupported,
        CUDA_ERROR_NO_BINARY_FOR_GPU => NoBinaryForGpu,
        CUDA_ERROR_NO_DEVICE => NoDevice,
        CUDA_ERROR_OPERATING_SYSTEM => OperatingSystem,
        CUDA_ERROR_OUT_OF_MEMORY => OutOfMemory,
        CUDA_ERROR_PEER_ACCESS_ALREADY_ENABLED => PeerAccessAlreadyEnabled,
        CUDA_ERROR_PEER_ACCESS_NOT_ENABLED => PeerAccessNotEnabled,
        CUDA_ERROR_PEER_ACCESS_UNSUPPORTED => PeerAccessUnsupported,
        CUDA_ERROR_PRIMARY_CONTEXT_ACTIVE => PrimaryContextActive,
        CUDA_ERROR_PROFILER_ALREADY_STARTED => ProfilerAlreadyStarted,
        CUDA_ERROR_PROFILER_ALREADY_STOPPED => ProfilerAlreadyStopped,
        CUDA_ERROR_PROFILER_DISABLED => ProfilerDisabled,
        CUDA_ERROR_PROFILER_NOT_INITIALIZED => ProfilerNotInitialized,
        CUDA_ERROR_SHARED_OBJECT_INIT_FAILED => SharedObjectInitFailed,
        CUDA_ERROR_SHARED_OBJECT_SYMBOL_NOT_FOUND => SharedObjectSymbolNotFound,
        CUDA_ERROR_TOO_MANY_PEERS => TooManyPeers,
        CUDA_ERROR_UNKNOWN => Unknown,
        CUDA_ERROR_UNMAP_FAILED => UnmapFailed,
        CUDA_ERROR_UNSUPPORTED_LIMIT => UnsupportedLimit,
        CUDA_ERROR_NVLINK_UNCORRECTABLE => NvlinkUncorrectable,
    })
}
<commit_msg>Context: "set_current" method for binding context to the current thread<commit_after>//! CUDA driver
//!
//! Reference: http://docs.nvidia.com/cuda/cuda-driver-api/

use std::ffi::CStr;
use std::marker::PhantomData;
use std::{mem, ptr, result};

#[allow(dead_code)]
#[allow(non_camel_case_types)]
#[allow(non_snake_case)]
#[allow(non_upper_case_globals)]
mod ll;

/// A CUDA "block"
pub struct Block {
    x: u32,
    y: u32,
    z: u32,
}

impl Block {
    /// One dimensional block
    pub fn x(x: u32) -> Self {
        Block { x: x, y: 1, z: 1 }
    }

    /// Two dimensional block
    pub fn xy(x: u32, y: u32) -> Self {
        Block { x: x, y: y, z: 1 }
    }

    /// Three dimensional block
    pub fn xyz(x: u32, y: u32, z: u32) -> Self {
        Block { x: x, y: y, z: z }
    }
}

/// A CUDA "context"
#[derive(Debug)]
pub struct Context {
    defused: bool,
    handle: ll::CUcontext,
}

impl Context {
    // TODO is this actually useful? Note that we are using "RAII" (cf. `drop`)
    // and ownership to manage `Context`es
    #[allow(dead_code)]
    fn current() -> Result<Option<Self>> {
        let mut handle = ptr::null_mut();

        unsafe { lift(ll::cuCtxGetCurrent(&mut handle))? }

        if handle.is_null() {
            Ok(None)
        } else {
            Ok(Some(Context {
                defused: true,
                handle: handle,
            }))
        }
    }

    /// Binds context to the calling thread
    pub fn set_current(&self) -> Result<()> {
        unsafe {
            lift(ll::cuCtxSetCurrent(self.handle))
        }
    }

    /// Loads a PTX module
    pub fn load_module<'ctx>(&'ctx self, image: &CStr) -> Result<Module<'ctx>> {
        let mut handle = ptr::null_mut();

        unsafe {
            lift(ll::cuModuleLoadData(&mut handle, image.as_ptr() as *const _))?
        }

        Ok(Module {
            handle: handle,
            _context: PhantomData,
        })
    }
}

impl Drop for Context {
    fn drop(&mut self) {
        if !self.defused {
            unsafe { lift(ll::cuCtxDestroy_v2(self.handle)).unwrap() }
        }
    }
}

/// A CUDA device (a GPU)
#[derive(Debug)]
pub struct Device {
    handle: ll::CUdevice,
}

/// Binds to the `nth` device
#[allow(non_snake_case)]
pub fn Device(nth: u16) -> Result<Device> {
    let mut handle = 0;

    unsafe { lift(ll::cuDeviceGet(&mut handle, i32::from(nth)))? }

    Ok(Device { handle: handle })
}

impl Device {
    /// Returns the number of available devices
    pub fn count() -> Result<u32> {
        let mut count: i32 = 0;

        unsafe { lift(ll::cuDeviceGetCount(&mut count))? }

        Ok(count as u32)
    }

    /// Creates a CUDA context for this device
    pub fn create_context(&self) -> Result<Context> {
        let mut handle = ptr::null_mut();
        // TODO expose
        let flags = 0;

        unsafe { lift(ll::cuCtxCreate_v2(&mut handle, flags, self.handle))? }

        Ok(Context {
            defused: false,
            handle: handle,
        })
    }

    /// Returns the maximum number of threads a block can have
    pub fn max_threads_per_block(&self) -> Result<i32> {
        use self::ll::CUdevice_attribute_enum::*;

        self.get(CU_DEVICE_ATTRIBUTE_MAX_THREADS_PER_BLOCK)
    }

    /// Returns the total amount of (non necessarily free) memory, in bytes,
    /// that the device has
    pub fn total_memory(&self) -> Result<usize> {
        let mut bytes = 0;

        unsafe { lift(ll::cuDeviceTotalMem_v2(&mut bytes, self.handle))? };

        Ok(bytes)
    }

    fn get(&self, attr: ll::CUdevice_attribute) -> Result<i32> {
        let mut value = 0;

        unsafe {
            lift(ll::cuDeviceGetAttribute(&mut value, attr, self.handle))?
        }

        Ok(value)
    }
}

/// A function that the CUDA device can execute. AKA a "kernel"
pub struct Function<'ctx: 'm, 'm> {
    handle: ll::CUfunction,
    _module: PhantomData<&'m Module<'ctx>>,
}

impl<'ctx, 'm> Function<'ctx, 'm> {
    /// Execute a function on the GPU
    ///
    /// NOTE This function blocks until the GPU has finished executing the
    /// kernel
    pub fn launch(&self,
                  args: &[&Any],
                  grid: Grid,
                  block: Block)
                  -> Result<()> {
        let stream = Stream::new()?;
        // TODO expose
        let shared_mem_bytes = 0;
        // TODO expose
        let extra = ptr::null_mut();

        unsafe {
            lift(ll::cuLaunchKernel(self.handle,
                                    grid.x,
                                    grid.y,
                                    grid.z,
                                    block.x,
                                    block.y,
                                    block.z,
                                    shared_mem_bytes,
                                    stream.handle,
                                    args.as_ptr() as *mut _,
                                    extra))?
        }

        stream.sync()?;
        stream.destroy()
    }
}

/// A CUDA "grid"
pub struct Grid {
    x: u32,
    y: u32,
    z: u32,
}

impl Grid {
    /// One dimensional grid
    pub fn x(x: u32) -> Self {
        Grid { x: x, y: 1, z: 1 }
    }

    /// Two dimensional grid
    pub fn xy(x: u32, y: u32) -> Self {
        Grid { x: x, y: y, z: 1 }
    }

    /// Three dimensional grid
    pub fn xyz(x: u32, y: u32, z: u32) -> Self {
        Grid { x: x, y: y, z: z }
    }
}

/// A PTX module
pub struct Module<'ctx> {
    handle: ll::CUmodule,
    _context: PhantomData<&'ctx Context>,
}

impl<'ctx> Module<'ctx> {
    /// Retrieves a function from the PTX module
    pub fn function<'m>(&'m self, name: &CStr) -> Result<Function<'ctx, 'm>> {
        let mut handle = ptr::null_mut();

        unsafe {
            lift(ll::cuModuleGetFunction(&mut handle,
                                         self.handle,
                                         name.as_ptr()))?
        }

        Ok(Function {
            handle: handle,
            _module: PhantomData,
        })
    }
}

impl<'ctx> Drop for Module<'ctx> {
    fn drop(&mut self) {
        unsafe { lift(ll::cuModuleUnload(self.handle)).unwrap() }
    }
}

// TODO expose
struct Stream {
    handle: ll::CUstream,
}

impl Stream {
    fn new() -> Result<Self> {
        let mut handle = ptr::null_mut();
        // TODO expose
        let flags = 0;

        unsafe { lift(ll::cuStreamCreate(&mut handle, flags))? }

        Ok(Stream { handle: handle })
    }

    fn destroy(self) -> Result<()> {
        unsafe { lift(ll::cuStreamDestroy_v2(self.handle)) }
    }

    fn sync(&self) -> Result<()> {
        unsafe { lift(ll::cuStreamSynchronize(self.handle)) }
    }
}

/// Value who's type has been erased
pub enum Any {}

/// Erase the type of a value
#[allow(non_snake_case)]
pub fn Any<T>(ref_: &T) -> &Any {
    unsafe { &*(ref_ as *const T as *const Any) }
}

/// `memcpy` direction
pub enum Direction {
    /// `src` points to device memory. `dst` points to host memory
    DeviceToHost,
    /// `src` points to host memory. `dst` points to device memory
    HostToDevice,
}

#[allow(missing_docs)]
#[derive(Debug)]
pub enum Error {
    AlreadyAcquired,
    AlreadyMapped,
    ArrayIsMapped,
    Assert,
    ContextAlreadyCurrent,
    ContextAlreadyInUse,
    ContextIsDestroyed,
    Deinitialized,
    EccUncorrectable,
    FileNotFound,
    HardwareStackError,
    HostMemoryAlreadyRegistered,
    HostMemoryNotRegistered,
    IllegalAddress,
    IllegalInstruction,
    InvalidAddressSpace,
    InvalidContext,
    InvalidDevice,
    InvalidGraphicsContext,
    InvalidHandle,
    InvalidImage,
    InvalidPc,
    InvalidPtx,
    InvalidSource,
    InvalidValue,
    LaunchFailed,
    LaunchIncompatibleTexturing,
    LaunchOutOfResources,
    LaunchTimeout,
    MapFailed,
    MisalignedAddress,
    NoBinaryForGpu,
    NoDevice,
    NotFound,
    NotInitialized,
    NotMapped,
    NotMappedAsArray,
    NotMappedAsPointer,
    NotPermitted,
    NotReady,
    NotSupported,
    NvlinkUncorrectable,
    OperatingSystem,
    OutOfMemory,
    PeerAccessAlreadyEnabled,
    PeerAccessNotEnabled,
    PeerAccessUnsupported,
    PrimaryContextActive,
    ProfilerAlreadyStarted,
    ProfilerAlreadyStopped,
    ProfilerDisabled,
    ProfilerNotInitialized,
    SharedObjectInitFailed,
    SharedObjectSymbolNotFound,
    TooManyPeers,
    Unknown,
    UnmapFailed,
    UnsupportedLimit,
}

// TODO should this be a method of `Context`?
/// Allocate `n` bytes of memory on the device
pub unsafe fn allocate(n: usize) -> Result<*mut u8> {
    let mut d_ptr = 0;

    lift(ll::cuMemAlloc_v2(&mut d_ptr, n))?;

    Ok(d_ptr as *mut u8)
}

/// Copy `n` bytes of memory from `src` to `dst`
///
/// `direction` indicates where `src` and `dst` are located (device or host)
pub unsafe fn copy<T>(src: *const T,
                      dst: *mut T,
                      count: usize,
                      direction: Direction)
                      -> Result<()> {
    use self::Direction::*;

    let bytes = count * mem::size_of::<T>();

    lift(match direction {
        DeviceToHost => ll::cuMemcpyDtoH_v2(dst as *mut _, src as u64, bytes),
        HostToDevice => ll::cuMemcpyHtoD_v2(dst as u64, src as *const _, bytes),
    })?;

    Ok(())
}

// TODO same question as `allocate`
/// Free the memory pointed to by `ptr`
pub unsafe fn deallocate(ptr: *mut u8) -> Result<()> {
    lift(ll::cuMemFree_v2(ptr as u64))
}

/// Initialize the CUDA runtime
pub fn initialize() -> Result<()> {
    // TODO expose
    let flags = 0;

    unsafe { lift(ll::cuInit(flags)) }
}

/// Returns the version of the CUDA runtime
pub fn version() -> Result<i32> {
    let mut version = 0;

    unsafe { lift(ll::cuDriverGetVersion(&mut version))? }

    Ok(version)
}

#[allow(missing_docs)]
pub type Result<T> = result::Result<T, Error>;

fn lift(e: ll::CUresult) -> Result<()> {
    use self::Error::*;
    use self::ll::cudaError_enum::*;

    Err(match e {
        CUDA_SUCCESS => return Ok(()),
        CUDA_ERROR_ALREADY_ACQUIRED => AlreadyAcquired,
        CUDA_ERROR_ALREADY_MAPPED => AlreadyMapped,
        CUDA_ERROR_ARRAY_IS_MAPPED => ArrayIsMapped,
        CUDA_ERROR_ASSERT => Assert,
        CUDA_ERROR_CONTEXT_ALREADY_CURRENT => ContextAlreadyCurrent,
        CUDA_ERROR_CONTEXT_ALREADY_IN_USE => ContextAlreadyInUse,
        CUDA_ERROR_CONTEXT_IS_DESTROYED => ContextIsDestroyed,
        CUDA_ERROR_DEINITIALIZED => Deinitialized,
        CUDA_ERROR_ECC_UNCORRECTABLE => EccUncorrectable,
        CUDA_ERROR_FILE_NOT_FOUND => FileNotFound,
        CUDA_ERROR_HARDWARE_STACK_ERROR => HardwareStackError,
        CUDA_ERROR_HOST_MEMORY_ALREADY_REGISTERED => {
            HostMemoryAlreadyRegistered
        }
        CUDA_ERROR_HOST_MEMORY_NOT_REGISTERED => HostMemoryNotRegistered,
        CUDA_ERROR_ILLEGAL_ADDRESS => IllegalAddress,
        CUDA_ERROR_ILLEGAL_INSTRUCTION => IllegalInstruction,
        CUDA_ERROR_INVALID_ADDRESS_SPACE => InvalidAddressSpace,
        CUDA_ERROR_INVALID_CONTEXT => InvalidContext,
        CUDA_ERROR_INVALID_DEVICE => InvalidDevice,
        CUDA_ERROR_INVALID_GRAPHICS_CONTEXT => InvalidGraphicsContext,
        CUDA_ERROR_INVALID_HANDLE => InvalidHandle,
        CUDA_ERROR_INVALID_IMAGE => InvalidImage,
        CUDA_ERROR_INVALID_PC => InvalidPc,
        CUDA_ERROR_INVALID_PTX => InvalidPtx,
        CUDA_ERROR_INVALID_SOURCE => InvalidSource,
        CUDA_ERROR_INVALID_VALUE => InvalidValue,
        CUDA_ERROR_LAUNCH_FAILED => LaunchFailed,
        CUDA_ERROR_LAUNCH_INCOMPATIBLE_TEXTURING => LaunchIncompatibleTexturing,
        CUDA_ERROR_LAUNCH_OUT_OF_RESOURCES => LaunchOutOfResources,
        CUDA_ERROR_LAUNCH_TIMEOUT => LaunchTimeout,
        CUDA_ERROR_MAP_FAILED => MapFailed,
        CUDA_ERROR_MISALIGNED_ADDRESS => MisalignedAddress,
        CUDA_ERROR_NOT_FOUND => NotFound,
        CUDA_ERROR_NOT_INITIALIZED => NotInitialized,
        CUDA_ERROR_NOT_MAPPED => NotMapped,
        CUDA_ERROR_NOT_MAPPED_AS_ARRAY => NotMappedAsArray,
        CUDA_ERROR_NOT_MAPPED_AS_POINTER => NotMappedAsPointer,
        CUDA_ERROR_NOT_PERMITTED => NotPermitted,
        CUDA_ERROR_NOT_READY => NotReady,
        CUDA_ERROR_NOT_SUPPORTED => NotSupported,
        CUDA_ERROR_NO_BINARY_FOR_GPU => NoBinaryForGpu,
        CUDA_ERROR_NO_DEVICE => NoDevice,
        CUDA_ERROR_OPERATING_SYSTEM => OperatingSystem,
        CUDA_ERROR_OUT_OF_MEMORY => OutOfMemory,
        CUDA_ERROR_PEER_ACCESS_ALREADY_ENABLED => PeerAccessAlreadyEnabled,
        CUDA_ERROR_PEER_ACCESS_NOT_ENABLED => PeerAccessNotEnabled,
        CUDA_ERROR_PEER_ACCESS_UNSUPPORTED => PeerAccessUnsupported,
        CUDA_ERROR_PRIMARY_CONTEXT_ACTIVE => PrimaryContextActive,
        CUDA_ERROR_PROFILER_ALREADY_STARTED => ProfilerAlreadyStarted,
        CUDA_ERROR_PROFILER_ALREADY_STOPPED => ProfilerAlreadyStopped,
        CUDA_ERROR_PROFILER_DISABLED => ProfilerDisabled,
        CUDA_ERROR_PROFILER_NOT_INITIALIZED => ProfilerNotInitialized,
        CUDA_ERROR_SHARED_OBJECT_INIT_FAILED => SharedObjectInitFailed,
        CUDA_ERROR_SHARED_OBJECT_SYMBOL_NOT_FOUND => SharedObjectSymbolNotFound,
        CUDA_ERROR_TOO_MANY_PEERS => TooManyPeers,
        CUDA_ERROR_UNKNOWN => Unknown,
        CUDA_ERROR_UNMAP_FAILED => UnmapFailed,
        CUDA_ERROR_UNSUPPORTED_LIMIT => UnsupportedLimit,
        CUDA_ERROR_NVLINK_UNCORRECTABLE => NvlinkUncorrectable,
    })
}
<|endoftext|>