<commit_before>extern crate gfx_gl as gl;
extern crate camera_controllers;
extern crate collada;
extern crate env_logger;
extern crate gfx;
extern crate gfx_debug_draw;
extern crate gfx_device_gl;
extern crate piston;
extern crate sdl2;
extern crate sdl2_window;
extern crate shader_version;
extern crate skeletal_animation;
extern crate vecmath;

use gfx::traits::*;
use gfx_debug_draw::DebugRenderer;

use gl::Gl;

use std::path::Path;
use std::rc::Rc;
use std::cell::RefCell;
use std::collections::HashMap;

use piston::window::{
    WindowSettings,
    OpenGLWindow,
};

use piston::event::*;

use vecmath::{Matrix4, mat4_id};

use sdl2_window::Sdl2Window;

use camera_controllers::{
    OrbitZoomCamera,
    OrbitZoomCameraSettings,
    CameraPerspective,
    model_view_projection
};

use skeletal_animation::*;
use collada::document::ColladaDocument;

mod menu;

pub struct Settings {
    pub draw_skeleton: bool,
    pub draw_labels: bool,
    pub draw_mesh: bool,
    pub playback_speed: f32,

    pub params: HashMap<String, f32>,
}

fn main() {

    env_logger::init().unwrap();

    let (win_width, win_height) = (640, 480);

    let mut window = Sdl2Window::new(
        shader_version::OpenGL::_3_2,
        WindowSettings::new(
            "Animation Viewer".to_string(),
            piston::window::Size { width: 640, height: 480 }
        ).exit_on_esc(true)
    );

    let mut graphics = gfx_device_gl::create(|s| window.get_proc_address(s)).into_graphics();

    let mut frame = gfx::Frame::new(win_width as u16, win_height as u16);

    let window = Rc::new(RefCell::new(window));

    let clear = gfx::ClearData {
        color: [0.3, 0.3, 0.3, 1.0],
        depth: 1.0,
        stencil: 0
    };

    let mut debug_renderer = DebugRenderer::new(&mut graphics, [frame.width as u32, frame.height as u32], 64, None, None).ok().unwrap();

    // TODO - these are (usually) available in the COLLADA file, associated with a <mesh> element in a somewhat convoluted way
    let texture_paths = vec![
        "assets/young_lightskinned_male_diffuse.png",
        "assets/suit01lres_diffuse.png",
        "assets/male02_diffuse_black.png",
        "assets/brown_eye.png",
        "assets/eyebrow009.png",
        "assets/eyelashes01.png",
    ];

    let collada_document = ColladaDocument::from_path(&Path::new("assets/suit_guy.dae")).unwrap();

    let skeleton = {
        let skeleton_set = collada_document.get_skeletons().unwrap();
        skeleton_set[0].clone()
    };

    let skeleton = Rc::new(RefCell::new(skeleton));

    let mut asset_manager = AssetManager::new();
    asset_manager.load_animations("assets/clips.json");

    let blend_tree_def = BlendTreeNodeDef::from_path("assets/walking_blend_tree.json").unwrap();
    let mut controller = AnimationController::new(skeleton.clone(), blend_tree_def, &asset_manager.animation_clips);

    //let mut skinned_renderer = SkinnedRenderer::from_collada(&mut graphics, collada_document, texture_paths).unwrap();

    let model = mat4_id();
    let mut projection = CameraPerspective {
        fov: 90.0f32,
        near_clip: 0.1,
        far_clip: 1000.0,
        aspect_ratio: (win_width as f32) / (win_height as f32)
    }.projection();

    let mut orbit_zoom_camera: OrbitZoomCamera<f32> = OrbitZoomCamera::new(
        [0.0, 0.0, 0.0],
        OrbitZoomCameraSettings::default()
    );

    // Start event loop

    Gl::load_with(|s| unsafe {
        std::mem::transmute(sdl2::video::gl_get_proc_address(s))
    });

    let mut elapsed_time = 0f64;

    let mut settings = Settings {

        draw_skeleton: true,
        draw_labels: true,
        draw_mesh: true,
        playback_speed: 1.0,

        params: HashMap::new(),
    };

    let mut menu = menu::Menu::<Settings>::new();

    menu.add_item(menu::MenuItem::action_item(
        "Toggle Skeleton",
        Box::new( |ref mut settings| { settings.draw_skeleton = !settings.draw_skeleton; })
    ));

    menu.add_item(menu::MenuItem::action_item(
        "Toggle Joint Labels",
        Box::new( |ref mut settings| { settings.draw_labels = !settings.draw_labels; })
    ));

    menu.add_item(menu::MenuItem::action_item(
        "Toggle Mesh",
        Box::new( |ref mut settings| { settings.draw_mesh = !settings.draw_mesh; })
    ));

    menu.add_item(menu::MenuItem::slider_item(
        "Playback Speed = ",
        [0.0, 5.0],
        0.1,
        Box::new( |ref settings| { settings.playback_speed }),
        Box::new( |ref mut settings, value| { settings.playback_speed = value }),
    ));

    for (param, &value) in controller.get_parameters().iter() {
        settings.params.insert(param.clone(), value);

        // Apparently need to make our own string copies to move into each closure..
        let param_copy_1 = param.clone();
        let param_copy_2 = param.clone();

        menu.add_item(menu::MenuItem::slider_item(
            &format!("Param[{}] = ", param)[..],
            [0.0, 1.0],
            0.01,
            Box::new( move |ref settings| {
                settings.params[&param_copy_1[..]]
            }),
            Box::new( move |ref mut settings, value| {
                settings.params.insert(param_copy_2.clone(), value);
            }),
        ));
    }

    for e in window.events() {

        e.resize(|width, height| {
            debug_renderer.resize(width, height);

            // Update frame
            frame.width = width as u16;
            frame.height = height as u16;

            // Update projection matrix
            projection = CameraPerspective {
                fov: 90.0f32,
                near_clip: 0.1,
                far_clip: 1000.0,
                aspect_ratio: (width as f32) / (height as f32)
            }.projection();
        });

        orbit_zoom_camera.event(&e);

        menu.event(&e, &mut settings);

        if let Some(args) = e.render_args() {
            graphics.clear(clear, gfx::COLOR | gfx::DEPTH, &frame);

            let camera_view = orbit_zoom_camera.camera(args.ext_dt).orthogonal();

            let camera_projection = model_view_projection(
                model,
                camera_view,
                projection
            );

            // Draw axes
            debug_renderer.draw_line([0.0, 0.0, 0.0], [5.0, 0.0, 0.0], [1.0, 0.0, 0.0, 1.0]);
            debug_renderer.draw_line([0.0, 0.0, 0.0], [0.0, 5.0, 0.0], [0.0, 1.0, 0.0, 1.0]);
            debug_renderer.draw_line([0.0, 0.0, 0.0], [0.0, 0.0, 5.0], [0.0, 0.0, 1.0, 1.0]);

            debug_renderer.draw_text_at_position(
                "X",
                [6.0, 0.0, 0.0],
                [1.0, 0.0, 0.0, 1.0],
            );

            debug_renderer.draw_text_at_position(
                "Y",
                [0.0, 6.0, 0.0],
                [0.0, 1.0, 0.0, 1.0],
            );

            debug_renderer.draw_text_at_position(
                "Z",
                [0.0, 0.0, 6.0],
                [0.0, 0.0, 1.0, 1.0],
            );

            elapsed_time = elapsed_time + 0.01 * settings.playback_speed as f64;

            let mut global_poses: [Matrix4<f32>; 64] = [ mat4_id(); 64 ];

            for (param, &value) in settings.params.iter() {
                controller.set_param_value(param, value);
            }

            controller.get_output_pose(elapsed_time as f32, &mut global_poses[0 .. skeleton.borrow().joints.len()]);

            if settings.draw_mesh {
                //skinned_renderer.render(&mut graphics, &frame, camera_view, camera_projection, &global_poses);
            }

            if settings.draw_skeleton {
                draw_skeleton(skeleton.clone(), &global_poses, &mut debug_renderer, settings.draw_labels);
            }

            menu.draw(&settings, &mut debug_renderer);

            debug_renderer.render(&mut graphics, &frame, camera_projection);

            graphics.end_frame();
        }
    }
}
<commit_msg>Using dt and ext_dt from UpdateArgs / RenderArgs<commit_after>extern crate gfx_gl as gl;
extern crate camera_controllers;
extern crate collada;
extern crate env_logger;
extern crate gfx;
extern crate gfx_debug_draw;
extern crate gfx_device_gl;
extern crate piston;
extern crate sdl2;
extern crate sdl2_window;
extern crate shader_version;
extern crate skeletal_animation;
extern crate vecmath;

use gfx::traits::*;
use gfx_debug_draw::DebugRenderer;

use gl::Gl;

use std::path::Path;
use std::rc::Rc;
use std::cell::RefCell;
use std::collections::HashMap;

use piston::window::{
    WindowSettings,
    OpenGLWindow,
};

use piston::event::*;

use vecmath::{Matrix4, mat4_id};

use sdl2_window::Sdl2Window;

use camera_controllers::{
    OrbitZoomCamera,
    OrbitZoomCameraSettings,
    CameraPerspective,
    model_view_projection
};

use skeletal_animation::*;
use collada::document::ColladaDocument;

mod menu;

pub struct Settings {
    pub draw_skeleton: bool,
    pub draw_labels: bool,
    pub draw_mesh: bool,
    pub playback_speed: f32,

    pub params: HashMap<String, f32>,
}

fn main() {

    env_logger::init().unwrap();

    let (win_width, win_height) = (640, 480);

    let mut window = Sdl2Window::new(
        shader_version::OpenGL::_3_2,
        WindowSettings::new(
            "Animation Viewer".to_string(),
            piston::window::Size { width: 640, height: 480 }
        ).exit_on_esc(true)
    );

    let mut graphics = gfx_device_gl::create(|s| window.get_proc_address(s)).into_graphics();

    let mut frame = gfx::Frame::new(win_width as u16, win_height as u16);

    let window = Rc::new(RefCell::new(window));

    let clear = gfx::ClearData {
        color: [0.3, 0.3, 0.3, 1.0],
        depth: 1.0,
        stencil: 0
    };

    let mut debug_renderer = DebugRenderer::new(&mut graphics, [frame.width as u32, frame.height as u32], 64, None, None).ok().unwrap();

    // TODO - these are (usually) available in the COLLADA file, associated with a <mesh> element in a somewhat convoluted way
    let texture_paths = vec![
        "assets/young_lightskinned_male_diffuse.png",
        "assets/suit01lres_diffuse.png",
        "assets/male02_diffuse_black.png",
        "assets/brown_eye.png",
        "assets/eyebrow009.png",
        "assets/eyelashes01.png",
    ];

    let collada_document = ColladaDocument::from_path(&Path::new("assets/suit_guy.dae")).unwrap();

    let skeleton = {
        let skeleton_set = collada_document.get_skeletons().unwrap();
        skeleton_set[0].clone()
    };

    let skeleton = Rc::new(RefCell::new(skeleton));

    let mut asset_manager = AssetManager::new();
    asset_manager.load_animations("assets/clips.json");

    let blend_tree_def = BlendTreeNodeDef::from_path("assets/walking_blend_tree.json").unwrap();
    let mut controller = AnimationController::new(skeleton.clone(), blend_tree_def, &asset_manager.animation_clips);

    //let mut skinned_renderer = SkinnedRenderer::from_collada(&mut graphics, collada_document, texture_paths).unwrap();

    let model = mat4_id();
    let mut projection = CameraPerspective {
        fov: 90.0f32,
        near_clip: 0.1,
        far_clip: 1000.0,
        aspect_ratio: (win_width as f32) / (win_height as f32)
    }.projection();

    let mut orbit_zoom_camera: OrbitZoomCamera<f32> = OrbitZoomCamera::new(
        [0.0, 0.0, 0.0],
        OrbitZoomCameraSettings::default()
    );

    // Start event loop

    Gl::load_with(|s| unsafe {
        std::mem::transmute(sdl2::video::gl_get_proc_address(s))
    });

    let mut settings = Settings {

        draw_skeleton: true,
        draw_labels: true,
        draw_mesh: true,
        playback_speed: 1.0,

        params: HashMap::new(),
    };

    let mut menu = menu::Menu::<Settings>::new();

    menu.add_item(menu::MenuItem::action_item(
        "Toggle Skeleton",
        Box::new( |ref mut settings| { settings.draw_skeleton = !settings.draw_skeleton; })
    ));

    menu.add_item(menu::MenuItem::action_item(
        "Toggle Joint Labels",
        Box::new( |ref mut settings| { settings.draw_labels = !settings.draw_labels; })
    ));

    menu.add_item(menu::MenuItem::action_item(
        "Toggle Mesh",
        Box::new( |ref mut settings| { settings.draw_mesh = !settings.draw_mesh; })
    ));

    menu.add_item(menu::MenuItem::slider_item(
        "Playback Speed = ",
        [-5.0, 5.0],
        0.01,
        Box::new( |ref settings| { settings.playback_speed }),
        Box::new( |ref mut settings, value| { settings.playback_speed = value }),
    ));

    for (param, &value) in controller.get_parameters().iter() {
        settings.params.insert(param.clone(), value);

        // Apparently need to make our own string copies to move into each closure..
        let param_copy_1 = param.clone();
        let param_copy_2 = param.clone();

        menu.add_item(menu::MenuItem::slider_item(
            &format!("Param[{}] = ", param)[..],
            [0.0, 1.0],
            0.01,
            Box::new( move |ref settings| {
                settings.params[&param_copy_1[..]]
            }),
            Box::new( move |ref mut settings, value| {
                settings.params.insert(param_copy_2.clone(), value);
            }),
        ));
    }

    for e in window.events() {

        orbit_zoom_camera.event(&e);
        menu.event(&e, &mut settings);

        e.resize(|width, height| {
            debug_renderer.resize(width, height);

            // Update frame
            frame.width = width as u16;
            frame.height = height as u16;

            // Update projection matrix
            projection = CameraPerspective {
                fov: 90.0f32,
                near_clip: 0.1,
                far_clip: 1000.0,
                aspect_ratio: (width as f32) / (height as f32)
            }.projection();
        });

        e.update(|args| {

            controller.set_playback_speed(settings.playback_speed as f64);

            for (param, &value) in settings.params.iter() {
                controller.set_param_value(param, value);
            }

            controller.update(args.dt);
        });

        e.render(|args| {

            graphics.clear(clear, gfx::COLOR | gfx::DEPTH, &frame);

            let camera_view = orbit_zoom_camera.camera(args.ext_dt).orthogonal();

            let camera_projection = model_view_projection(
                model,
                camera_view,
                projection
            );

            // Draw axes
            debug_renderer.draw_line([0.0, 0.0, 0.0], [5.0, 0.0, 0.0], [1.0, 0.0, 0.0, 1.0]);
            debug_renderer.draw_line([0.0, 0.0, 0.0], [0.0, 5.0, 0.0], [0.0, 1.0, 0.0, 1.0]);
            debug_renderer.draw_line([0.0, 0.0, 0.0], [0.0, 0.0, 5.0], [0.0, 0.0, 1.0, 1.0]);

            debug_renderer.draw_text_at_position(
                "X",
                [6.0, 0.0, 0.0],
                [1.0, 0.0, 0.0, 1.0],
            );

            debug_renderer.draw_text_at_position(
                "Y",
                [0.0, 6.0, 0.0],
                [0.0, 1.0, 0.0, 1.0],
            );

            debug_renderer.draw_text_at_position(
                "Z",
                [0.0, 0.0, 6.0],
                [0.0, 0.0, 1.0, 1.0],
            );

            let mut global_poses: [Matrix4<f32>; 64] = [ mat4_id(); 64 ];

            controller.get_output_pose(args.ext_dt, &mut global_poses[0 .. skeleton.borrow().joints.len()]);

            if settings.draw_mesh {
                //skinned_renderer.render(&mut graphics, &frame, camera_view, camera_projection, &global_poses);
            }

            if settings.draw_skeleton {
                draw_skeleton(skeleton.clone(), &global_poses, &mut debug_renderer, settings.draw_labels);
            }

            menu.draw(&settings, &mut debug_renderer);

            debug_renderer.render(&mut graphics, &frame, camera_projection);

            graphics.end_frame();

        });
    }
}
<|endoftext|>


<commit_before>#![feature(specialization)]
#![feature(zero_one)]
extern crate core;
extern crate rand;

use std::ops::{Add, Mul, Sub, Div, AddAssign, MulAssign, SubAssign, DivAssign};
use std::num::{Zero};
use core::fmt::{Display};
use core::marker::PhantomData;

trait Scalar where
    Self: Add<Self, Output=Self>,
    Self: Mul<Self, Output=Self>,
    Self: Sub<Self, Output=Self>,
    Self: Div<Self, Output=Self>,
    Self: AddAssign<Self>,
    Self: MulAssign<Self>,
    Self: SubAssign<Self>,
    Self: DivAssign<Self>,
    Self: Zero,
    Self: Sized,
    Self: Copy,
    Self: Display,
    Self: rand::Rand,
{}
impl Scalar for f64{}
impl Scalar for f32{}

struct Matrix<T: Scalar> {
    h: usize,
    w: usize,
    row_stride: usize,
    column_stride: usize,
    buffer: Vec<T>,
}
impl<T: Scalar> Matrix<T> {
    fn new( h: usize, w: usize ) -> Matrix<T> {
        let mut buf = Vec::with_capacity( h * w );
        unsafe{ buf.set_len( h * w );}
        let mat = Matrix{ h: h, w: w, row_stride: 1, column_stride: h, buffer: buf };
        return mat;
    }
    fn get( &self, y: usize, x: usize) -> T {
        return self.buffer[y*self.row_stride + x*self.column_stride];
    }
    fn set( &mut self, y: usize, x: usize, alpha: T) -> () {
        self.buffer[y*self.row_stride + x*self.column_stride] = alpha;
    }
    fn fill_rand( &mut self ) -> () {
        for x in 0..self.w {
            for y in 0..self.h {
                self.set(y,x,rand::random::<T>());
            }
        }
    }
    fn fill_zero( &mut self ) -> () {
        for x in 0..self.w {
            for y in 0..self.h {
                self.set(y,x,T::zero());
            }
        }
    }
    fn frosqr( &self ) -> T {
        let mut norm:T = T::zero();
        for x in 0..self.w {
            for y in 0..self.h {
                norm += self.get(0,0) * self.get(0,0);
            }
        }
        return norm;
    }
}
/*
struct ColumnPanelMatrix<T: Scalar> {
    h: usize,
    w: usize,
    panel_h: usize,
    panel_w: usize,
    panel_stride: usize,
    buffer: Vec<T>,
}
impl<T: Scalar> Matrix<T> for ColumnPanelMatrix<T> {
    fn get( &self, x: usize, y:usize ) -> T {
        let panel_id = y / self.panel_w;
        let panel_index  = y % self.panel_w;
        let elem_index = panel_id * self.panel_stride + x * self.panel_w + panel_index;

        return self.buffer[ elem_index ];
    }
    fn set( &mut self, x: usize, y:usize, alpha: T) -> () {
        let panel_id = y / self.panel_w;
        let panel_index  = y % self.panel_w;
        let elem_index = panel_id * self.panel_stride + x * self.panel_w + panel_index;

        self.buffer[ elem_index ] = alpha;
    }
    fn height( &self ) -> usize{
        return self.h;
    }
    fn width( &self ) -> usize{
        return self.w;
    }
}*/

struct View<T> {
    m: usize,
    n: usize,
    k: usize,
    m_off: usize,
    n_off: usize,
    k_off: usize,

    a_pack: Vec<T>,
    ap_orig_x: usize,
    ap_orig_y: usize,
    b_pack: Vec<T>,
    bp_orig_x: usize,
    bp_orig_y: usize,
    c_pack: Vec<T>,
    cp_orig_x: usize,
    cp_orig_y: usize,
}
impl<T:Scalar> View<T>{
    fn new( a: &Matrix<T>, b: &Matrix<T>, c: &Matrix<T> ) -> View<T>{
        let v : View<T> = View{ m: c.h, n: c.w, k: a.w,
                      m_off: 0, n_off: 0, k_off: 0,
                      a_pack: Vec::new(), ap_orig_x: 0, ap_orig_y: 0,
                      b_pack: Vec::new(), bp_orig_x: 0, bp_orig_y: 0,
                      c_pack: Vec::new(), cp_orig_x: 0, cp_orig_y: 0 };
        return v;
    }
}

trait GemmNode<T: Scalar> {
     fn run( &self, a: &Matrix<T>, b: &Matrix<T>, c: &mut Matrix<T>, v: &mut View<T> ) -> ();
}
/*
fn pack<T: Scalar>( a: &Matrix<T> ) {
}

struct PackA<T: Scalar, S: GemmNode<T>> {
    child: S,
    panel_height: usize,
    panel_width: usize,
    dt: PhantomData<T>,
}
impl<T:Scalar, S:GemmNode<T>> GemmNode<T> for PackA<T,S> {
     fn run( &self, a: &Matrix<T>, b: &Matrix<T>, c: &mut Matrix<T>, v: &mut View<T> ) {
        pack( a );
        self.child.run(a, b, c, v);
    }
}

struct PackB<T: Scalar, S: GemmNode<T>> {
    child: S,
    panel_height: usize,
    panel_width: usize,
    _dt: PhantomData<T>,
}
impl<T:Scalar, S:GemmNode<T>> GemmNode<T> for PackB<T,S> {
     fn run( &self, a: &Matrix<T>, b: &Matrix<T>, c: &mut Matrix<T>, v: &mut View<T> ) {
        pack( b );
        self.child.run(a, b, c, v);
    }
}
*/

struct PartM<T: Scalar, S: GemmNode<T>> {
    nb: usize,
    iota: usize,
    child: S,
    _dt: PhantomData<T>
}
impl<T: Scalar, S: GemmNode<T>> GemmNode<T> for PartM<T,S> {
    fn run( &self, a: &Matrix<T>, b: &Matrix<T>, c:&mut Matrix<T>, v: &mut View<T> ) -> () {
        let m_save = v.m;
        let m_off_save = v.m_off;

        let mut i = 0;
        while i < m_save  {
            let nb_step = std::cmp::min( self.nb, m_save - i );
            v.m = nb_step;
            v.m_off = m_off_save + i;
            self.child.run(a, b, c, v);
            i += nb_step;
        }
        v.m = m_save;
        v.m_off = m_off_save;
    }
}

//leaf node that does nothing for testing
struct End { }
impl<T: Scalar> GemmNode<T> for End {
    fn run( &self, a: &Matrix<T>, b: &Matrix<T>, c: &mut Matrix<T>, v: &mut View<T> ) -> () {
    }
}

struct TripleLoopKernel{}
impl<T: Scalar> GemmNode<T> for TripleLoopKernel {
    fn run( &self, a: &Matrix<T>, b: &Matrix<T>, c: &mut Matrix<T>, v: &mut View<T> ) -> () {
        //For now, let's do an axpy based gemm
        for jn in 0..v.n {
            for pk in 0..v.k {
                for im in 0..v.m {
                    let y = im+v.m_off;
                    let x = jn+v.n_off;
                    let z = pk+v.k_off;
                    let t = a.get(y,z) * b.get(z,x) + c.get(y,x);
                    c.set( y, x, t );
                }
            }
        }
    }
}

fn axpy<T:Scalar>( alpha: T, x: &Matrix<T>, beta: T, y: &mut Matrix<T> ) {
    //x.h should equal y.h and x.w should equal y.w!
    //but we dont check this yet
    for i in 0..x.w {
        for j in 0..x.h {
            let t = alpha * x.get(j,i) + beta * y.get(j,i);
            y.set(j,i,t);
        }
    }
}

fn main() {
    let mut a : Matrix<f64> = Matrix::new(10, 10);
    let mut b : Matrix<f64> = Matrix::new(10, 10);
    let mut c : Matrix<f64> = Matrix::new(10, 10);
    let mut gemm_view : View<f64> = View::new(&a,&b,&c);
    a.fill_rand();
    b.fill_rand();
    c.fill_zero();

    let mut w : Matrix<f64> = Matrix::new(10, 1);
    let mut abw : Matrix<f64> = Matrix::new(10, 1);
    let mut bw : Matrix<f64> = Matrix::new(10, 1);
    let mut cw : Matrix<f64> = Matrix::new(10, 1);
    w.fill_rand();
    cw.fill_zero();
    bw.fill_zero();
    abw.fill_zero();

    let kernel : TripleLoopKernel = TripleLoopKernel{};
    //C = AB
    kernel.run( &a, &b, &mut c, &mut gemm_view );

    //Do bw = Bw, then abw = A*(Bw)
    let mut bw_view : View<f64> = View::new(&b, &w, &bw);
    kernel.run( &b, &w, &mut bw, &mut bw_view );
    let mut abw_view : View<f64> = View::new(&a, &bw, &abw);
    kernel.run( &a, &bw, &mut abw, &mut abw_view );

    //Do cw = Cw
    let mut cw_view : View<f64> = View::new(&c, &w, &cw);
    kernel.run( &c, &w, &mut cw, &mut cw_view );

    //Cw -= abw
    axpy( 1.0, &abw, -1.0, &mut cw );
    let norm = cw.frosqr();
    println!("diff is {}", norm);
    /*

    let leaf : End = End{};
    let root : PartM<End> = PartM{child: leaf};
    root.run(&a, &b, &mut c);

    println!("c is {}", c.buffer);*/
}
<commit_msg>Make Mat a trait,<commit_after>#![feature(specialization)]
#![feature(zero_one)]
extern crate core;
extern crate rand;

use std::ops::{Add, Mul, Sub, Div, AddAssign, MulAssign, SubAssign, DivAssign};
use std::num::{Zero};
use core::fmt::{Display};
use core::marker::PhantomData;

trait Scalar where
    Self: Add<Self, Output=Self>,
    Self: Mul<Self, Output=Self>,
    Self: Sub<Self, Output=Self>,
    Self: Div<Self, Output=Self>,
    Self: AddAssign<Self>,
    Self: MulAssign<Self>,
    Self: SubAssign<Self>,
    Self: DivAssign<Self>,
    Self: Zero,
    Self: Sized,
    Self: Copy,
    Self: Display,
    Self: rand::Rand,
{}
impl Scalar for f64{}
impl Scalar for f32{}

trait Mat<T: Scalar> {
    fn get( &self, y: usize, x: usize) -> T;
    fn set( &mut self, y: usize, x: usize, alpha: T) -> ();
    fn width( &self ) -> usize;
    fn height( &self ) -> usize;

    fn fill_rand( &mut self ) -> () {
        for x in 0..self.width() {
            for y in 0..self.height() {
                self.set(y,x,rand::random::<T>());
            }
        }
    }

    fn fill_zero( &mut self ) -> () {
        for x in 0..self.width() {
            for y in 0..self.height() {
                self.set(y,x,T::zero());
            }
        }
    }

    fn frosqr( &self ) -> T {
        let mut norm:T = T::zero();
        for x in 0..self.width() {
            for y in 0..self.height() {
                norm += self.get(y,x) * self.get(y,x);
            }
        }
        return norm;
    }
}

struct Matrix<T: Scalar> {
    h: usize,
    w: usize,
    row_stride: usize,
    column_stride: usize,
    buffer: Vec<T>,
}
impl<T: Scalar> Matrix<T> {
    fn new( h: usize, w: usize ) -> Matrix<T> {
        let mut buf = Vec::with_capacity( h * w );
        unsafe{ buf.set_len( h * w );}
        let mat = Matrix{ h: h, w: w, row_stride: 1, column_stride: h, buffer: buf };
        return mat;
    }
}
impl<T: Scalar> Mat<T> for Matrix<T> {
    fn get( &self, y: usize, x: usize) -> T {
        return self.buffer[y*self.row_stride + x*self.column_stride];
    }
    fn set( &mut self, y: usize, x: usize, alpha: T) -> () {
        self.buffer[y*self.row_stride + x*self.column_stride] = alpha;
    }
    fn width( &self ) -> usize {
        return self.w;
    }
    fn height( &self ) -> usize {
        return self.h;
    }
}

/*
struct ColumnPanelMatrix<T: Scalar> {
    h: usize,
    w: usize,
    panel_h: usize,
    panel_w: usize,
    panel_stride: usize,
    buffer: Vec<T>,
}
impl<T: Scalar> Mat<T> for ColumnPanelMatrix<T> {
    fn get( &self, x: usize, y:usize ) -> T {
        let panel_id = y / self.panel_w;
        let panel_index  = y % self.panel_w;
        let elem_index = panel_id * self.panel_stride + x * self.panel_w + panel_index;

        return self.buffer[ elem_index ];
    }
    fn set( &mut self, x: usize, y:usize, alpha: T) -> () {
        let panel_id = y / self.panel_w;
        let panel_index  = y % self.panel_w;
        let elem_index = panel_id * self.panel_stride + x * self.panel_w + panel_index;

        self.buffer[ elem_index ] = alpha;
    }
    fn height( &self ) -> usize{
        return self.h;
    }
    fn width( &self ) -> usize{
        return self.w;
    }
}*/

struct View {
    m: usize,
    n: usize,
    k: usize,
    m_off: usize,
    n_off: usize,
    k_off: usize,
}
impl View{
    fn new<T: Scalar>( a: &Mat<T>, b: &Mat<T>, c: &Mat<T> ) -> View{
        if a.height() != c.height() || a.width() != b.height() || c.width() != b.width() {
            panic!("Cannot create View with nonconformal operands!");
        }

        let v : View = View{ m: c.height(), n: b.width(), k: a.width(),
                      m_off: 0, n_off: 0, k_off: 0 };
        return v;
    }
}

trait GemmNode<T: Scalar, At: Mat<T>, Bt: Mat<T>, Ct: Mat<T>> {
     fn run( &self, a: &At, b: &Bt, c: &mut Ct, v: &mut View ) -> ();
}

/*
fn pack<T: Scalar>( a: &Matrix<T> ) {
}

struct PackA<T: Scalar, S: GemmNode<T>> {
    child: S,
    panel_height: usize,
    panel_width: usize,
    dt: PhantomData<T>,
}
impl<T:Scalar, S:GemmNode<T>> GemmNode<T> for PackA<T,S> {
     fn run( &self, a: &Matrix<T>, b: &Matrix<T>, c: &mut Matrix<T>, v: &mut View<T> ) {
        pack( a );
        self.child.run(a, b, c, v);
    }
}

struct PackB<T: Scalar, S: GemmNode<T>> {
    child: S,
    panel_height: usize,
    panel_width: usize,
    _dt: PhantomData<T>,
}
impl<T:Scalar, S:GemmNode<T>> GemmNode<T> for PackB<T,S> {
     fn run( &self, a: &Matrix<T>, b: &Matrix<T>, c: &mut Matrix<T>, v: &mut View<T> ) {
        pack( b );
        self.child.run(a, b, c, v);
    }
}
*/

struct PartM<T: Scalar, At: Mat<T>, Bt: Mat<T>, Ct: Mat<T>, S: GemmNode<T, At, Bt, Ct>> {
    nb: usize,
    iota: usize,
    child: S,
    _t: PhantomData<T>,
    _at: PhantomData<At>,
    _bt: PhantomData<Bt>,
    _ct: PhantomData<Ct>,
}
impl<T: Scalar, At: Mat<T>, Bt: Mat<T>, Ct: Mat<T>, S: GemmNode<T, At, Bt, Ct>>
    GemmNode<T, At, Bt, Ct> for PartM<T,At,Bt,Ct,S> {
    fn run( &self, a: &At, b: &Bt, c:&mut Ct, v: &mut View ) -> () {
        let m_save = v.m;
        let m_off_save = v.m_off;

        let mut i = 0;
        while i < m_save  {
            let nb_step = std::cmp::min( self.nb, m_save - i );
            v.m = nb_step;
            v.m_off = m_off_save + i;
            self.child.run(a, b, c, v);
            i += nb_step;
        }
        v.m = m_save;
        v.m_off = m_off_save;
    }
}

//Leaf node that does nothing. For testing.
struct End { }
impl<T: Scalar, At: Mat<T>, Bt: Mat<T>, Ct: Mat<T>> GemmNode<T, At, Bt, Ct> for End {
    fn run( &self, a: &At, b: &Bt, c: &mut Ct, v: &mut View ) -> () {
    }
}

struct TripleLoopKernel{}
impl<T: Scalar, At: Mat<T>, Bt: Mat<T>, Ct: Mat<T>>
    GemmNode<T, At, Bt, Ct> for TripleLoopKernel {
    fn run( &self, a: &At, b: &Bt, c: &mut Ct, v: &mut View ) -> () {
        //For now, let's do an axpy based gemm
        for jn in 0..v.n {
            for pk in 0..v.k {
                for im in 0..v.m {
                    let y = im+v.m_off;
                    let x = jn+v.n_off;
                    let z = pk+v.k_off;
                    let t = a.get(y,z) * b.get(z,x) + c.get(y,x);
                    c.set( y, x, t );
                }
            }
        }
    }
}

fn axpy<T:Scalar, Xt: Mat<T>, Yt: Mat<T>>( alpha: T, x: &Xt, beta: T, y: &mut Yt ) {
    //x.h should equal y.h and x.w should equal y.w!
    //but we dont check this yet
    for i in 0..x.width() {
        for j in 0..x.height() {
            let t = alpha * x.get(j,i) + beta * y.get(j,i);
            y.set(j,i,t);
        }
    }
}

fn main() {
    let mut a : Matrix<f64> = Matrix::new(10, 10);
    let mut b : Matrix<f64> = Matrix::new(10, 10);
    let mut c : Matrix<f64> = Matrix::new(10, 10);
    let mut gemm_view : View = View::new(&a,&b,&c);
    a.fill_rand();
    b.fill_rand();
    c.fill_zero();

    let mut w : Matrix<f64> = Matrix::new(10, 1);
    let mut abw : Matrix<f64> = Matrix::new(10, 1);
    let mut bw : Matrix<f64> = Matrix::new(10, 1);
    let mut cw : Matrix<f64> = Matrix::new(10, 1);
    w.fill_rand();
    cw.fill_zero();
    bw.fill_zero();
    abw.fill_zero();

    let kernel : TripleLoopKernel = TripleLoopKernel{};
    //C = AB
    kernel.run( &a, &b, &mut c, &mut gemm_view );

    //Do bw = Bw, then abw = A*(Bw)
    let mut bw_view : View = View::new(&b, &w, &bw);
    kernel.run( &b, &w, &mut bw, &mut bw_view );
    let mut abw_view : View = View::new(&a, &bw, &abw);
    kernel.run( &a, &bw, &mut abw, &mut abw_view );

    //Do cw = Cw
    let mut cw_view : View = View::new(&c, &w, &cw);
    kernel.run( &c, &w, &mut cw, &mut cw_view );

    //Cw -= abw
    axpy( 1.0, &abw, -1.0, &mut cw );
    let norm = cw.frosqr();
    println!("diff is {}", norm);
    /*

    let leaf : End = End{};
    let root : PartM<End> = PartM{child: leaf};
    root.run(&a, &b, &mut c);

    println!("c is {}", c.buffer);*/
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(rocket_codegen)]

extern crate reqwest;
extern crate rocket;
extern crate toml;

use std::fmt::{Display, Formatter, Error};
use std::fs::File;
use std::io::Read;

enum Status {
    Unknown,
    OutOfDate,
    UpToDate
}

impl Display for Status {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        match *self {
            Status::Unknown => write!(f, "unknown"),
            Status::OutOfDate => write!(f, "outofdate"),
            Status::UpToDate => write!(f, "uptodate")
        }
    }
}

#[get("/<owner>/<name>")]
fn index(owner: &str, name: &str) -> File {
    // TODO: HEADER 'Cache-Control': 'no-cache, no-store, must-revalidate',
    // TODO: HEADER 'Expires': new Date().toUTCString()
    let status = get_deps_status(owner, name, "dev-dependencies");
    File::open(format!("public/img/status/{}.png", status)).unwrap()
}

fn get_deps_status(owner: &str, name: &str, deps_type: &str) -> Status {
    let cargo_url = format!("https://raw.githubusercontent.com/{}/{}/master/Cargo.toml", owner, name);

    if let Ok(mut resp) = reqwest::get(&*cargo_url) {
        match resp.status() {
            &reqwest::StatusCode::Ok => {
                let mut body = String::new();
                resp.read_to_string(&mut body).ok();
                deps_status_from_cargo(body, deps_type)
            },
            _ => Status::Unknown
        }
    } else {
        Status::Unknown
    }
}

fn deps_status_from_cargo(cargo: String, deps_type: &str) -> Status {
    if let Some(root) = toml::Parser::new(&*cargo).parse() {
        match root.get(deps_type) {
            Some(val) => {
                if let Some(dependencies) = val.as_table() {
                    // TODO:
                    // 1- Download the Cargo.toml of the project into /tmp/owner/name/Cargo.toml
                    // 2- Create a dummy /tmp/owner/name/src/lib.rs (avoid `cargo update` complaint)
                    // 3- Parse the /tmp/owner/name/Cargo.lock generated
                    // 4- Compare each deps with semver
                    dependencies.iter().fold(Status::UpToDate, |oldest, (dep, version)| {
                        println!("{:?}", dep);
                        println!("{:?}", version);
                        Status::OutOfDate
                    })
                } else {
                    Status::UpToDate
                }
            },
            None => Status::UpToDate
        }
    } else {
        Status::Unknown
    }
}

fn main() {
    rocket::ignite().mount("/", routes![index]).launch();
}
<commit_msg>Implement steps 1 & 2<commit_after>#![feature(plugin)]
#![plugin(rocket_codegen)]

extern crate reqwest;
extern crate rocket;
extern crate toml;

use std::fmt::{Display, Formatter, self};
use std::fs::{File, self};
use std::io::Read;
use std::io::Write;

enum Status {
    Unknown,
    OutOfDate,
    UpToDate
}

impl Display for Status {
    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
        match *self {
            Status::Unknown => write!(f, "unknown"),
            Status::OutOfDate => write!(f, "outofdate"),
            Status::UpToDate => write!(f, "uptodate")
        }
    }
}

#[get("/<owner>/<name>")]
fn index(owner: &str, name: &str) -> File {
    // TODO: HEADER 'Cache-Control': 'no-cache, no-store, must-revalidate',
    // TODO: HEADER 'Expires': new Date().toUTCString()
    let status = get_deps_status(owner, name, "dev-dependencies");
    File::open(format!("public/img/status/{}.png", status)).unwrap()
}

fn get_deps_status(owner: &str, name: &str, deps_type: &str) -> Status {
    let cargo_url = format!("https://raw.githubusercontent.com/{}/{}/master/Cargo.toml", owner, name);

    if let Ok(mut resp) = reqwest::get(&*cargo_url) {
        match resp.status() {
            &reqwest::StatusCode::Ok => {
                let mut body = String::new();
                resp.read_to_string(&mut body).ok();
                deps_status_from_cargo(owner, name, body, deps_type)
            },
            _ => Status::Unknown
        }
    } else {
        Status::Unknown
    }
}

fn deps_status_from_cargo(owner: &str, name: &str, cargo: String, deps_type: &str) -> Status {

    if let Some(root) = toml::Parser::new(&*cargo).parse() {
        match root.get(deps_type) {
            Some(val) => {
                if let Some(dependencies) = val.as_table() {
                    // TODO:
                    // 1- Download the Cargo.toml of the project into /tmp/owner/name/Cargo.toml
                    // 2- Create a dummy /tmp/owner/name/src/lib.rs (avoid `cargo update` complaint)
                    let tmp_dir = format!("/tmp/{}/{}/src", owner, name);
                    let tmp_cargo = format!("{}/Cargo.toml", tmp_dir);
                    let tmp_src_dir = format!("{}/src", tmp_dir);
                    let tmp_src_lib = format!("{}/lib.rs", tmp_src_dir);

                    if let Err(e) = fs::create_dir_all(tmp_src_dir.as_str())
                        .and_then(|_| File::create(tmp_cargo.as_str()))
                        .and_then(|mut file| file.write_all(cargo.as_bytes()))
                        .and_then(|_| File::create(tmp_src_lib.as_str())) {
                            Status::Unknown
                        }
                    // 3- `cargo update --manifest-path /tmp/owner/name/Cargo.toml`
                    // 4- Parse the /tmp/owner/name/Cargo.lock generated
                    // 5- Compare each deps with semver
                    dependencies.iter().fold(Status::UpToDate, |oldest, (dep, version)| {
                        println!("{:?}", dep);
                        println!("{:?}", version);
                        Status::OutOfDate
                    })
                } else {
                    Status::UpToDate
                }
            },
            None => Status::UpToDate
        }
    } else {
        Status::Unknown
    }
}

fn main() {
    rocket::ignite().mount("/", routes![index]).launch();
}
<|endoftext|>


<commit_before>extern crate opencl;
extern crate sdl2;

use opencl::mem::CLBuffer;
use sdl2::pixels::Color;
use sdl2::keyboard::Keycode;

const KERNEL: &'static str = r"
__kernel void multiply_by_scalar(__global float const* const src_buf,
                                 __private float const coeff,
                                 __global float* dst_buf) {
    uint i = get_global_id(0);
    dst_buf[i] = src_buf[i] * coeff;
}
";

fn main() {
    let (device, ctx, queue) = opencl::util::create_compute_context().expect("Could not initialise OpenCL");

    let sdl = sdl2::init().expect("Could not intialise SDL library");
    let mut renderer = sdl.video()
                          .expect("Could not initialise video")
                          .window("mandlebrot", 800, 600)
                          .position_centered()
                          .build()
                          .expect("Could not create a window from the video subsystem")
                          .renderer()
                          .build()
                          .expect("Could not get renderer from window");

    let mut events = sdl.event_pump().expect("Could not initialise events");
    'mainloop: loop {
        for e in events.poll_iter() {
            use sdl2::event::Event;
            match e {
                Event::Quit {..} | Event::KeyDown {keycode: Some(Keycode::Escape), ..} => break 'mainloop,
                _ => { }
            }
        }

        renderer.set_draw_color(Color::RGB(255, 0, 0));
        renderer.clear();
        renderer.present();
    }
}
<commit_msg>Add simple OpenCL example<commit_after>//! Doc placeholder

extern crate opencl;
extern crate sdl2;

use sdl2::pixels::Color;
use sdl2::keyboard::Keycode;

const KERNEL: &'static str = r"
__kernel void multiply_by_scalar(__global float const* const src_buf,
                                 __private float const coeff,
                                 __global float* dst_buf) {
    uint i = get_global_id(0);
    dst_buf[i] = src_buf[i] * coeff;
}
";

fn main() {
    // Initial kernel stuff
    {
        let (device, ctx, queue) = opencl::util::create_compute_context().expect("Could not initialise OpenCL");
        const COEFF: f32 = 5.4321;

        let vec_src = vec![1.0f32, 2.0, 3.0, 4.0, 5.0];

        let cl_src_buf = ctx.create_buffer::<f32>(vec_src.len(), opencl::cl::CL_MEM_READ_ONLY);
        let cl_dst_buf = ctx.create_buffer::<f32>(vec_src.len(), opencl::cl::CL_MEM_WRITE_ONLY);

        queue.write(&cl_src_buf, &&vec_src[..], ());

        let program = {
            let p = ctx.create_program_from_source(KERNEL);
            p.build(&device).expect("Could not build program");
            p
        };

        let kernel = program.create_kernel("multiply_by_scalar");
        kernel.set_arg(0, &cl_src_buf);
        kernel.set_arg(1, &COEFF);
        kernel.set_arg(2, &cl_dst_buf);

        let event = queue.enqueue_async_kernel(&kernel, vec_src.len(), None, ());

        let vec_dst: Vec<f32> = queue.get(&cl_dst_buf, &event);

        println!("  {:?}", &vec_src[..]);
        println!("+ {:?}", COEFF);
        println!("= {:?}", &vec_dst[..]);
    }

    let sdl = sdl2::init().expect("Could not intialise SDL library");
    let mut renderer = sdl.video()
                          .expect("Could not initialise video")
                          .window("mandlebrot", 800, 600)
                          .position_centered()
                          .build()
                          .expect("Could not create a window from the video subsystem")
                          .renderer()
                          .build()
                          .expect("Could not get renderer from window");

    let mut events = sdl.event_pump().expect("Could not initialise events");
    'mainloop: loop {
        for e in events.poll_iter() {
            use sdl2::event::Event;
            match e {
                Event::Quit {..} | Event::KeyDown {keycode: Some(Keycode::Escape), ..} => break 'mainloop,
                _ => { }
            }
        }

        renderer.set_draw_color(Color::RGB(255, 0, 0));
        renderer.clear();
        renderer.present();
    }
}
<|endoftext|>


<commit_before>extern crate sdl2;
extern crate sdl2_image;

use std::io::fs::PathExtensions;
use std::collections::HashMap;

use std::io::BufferedReader;
use std::io::File;

mod game;

fn main() {
    sdl2::init(sdl2::INIT_VIDEO);
    sdl2_image::init(sdl2_image::INIT_PNG | sdl2_image::INIT_JPG);

    let columns : int = 20;
    let rows : int = 20;
    let boxsize : int = 34;

    let window = match sdl2::video::Window::new("Sokoban", sdl2::video::PosCentered, sdl2::video::PosCentered, columns * boxsize, rows * boxsize, sdl2::video::OPENGL) {
        Ok(window) => window,
        Err(err) => fail!(format!("error on window init : {}", err))
    };

    let renderer = match sdl2::render::Renderer::from_window(window, sdl2::render::DriverAuto, sdl2::render::ACCELERATED) {
        Ok(renderer) => renderer,
        Err(err) => fail!(format!("failed to create renderer: {}", err))
    };

    let _ = renderer.set_draw_color(sdl2::pixels::RGB(255, 255, 255));
    let _ = renderer.clear();

    let mygame = game::Game::new();
    mygame.start();

    let mut grid_textures: HashMap<SquareType, sdl2::render::Texture> = HashMap::new();

    let wall_texture = load_texture_from_file("mur.jpg", &renderer);
    let box_texture = load_texture_from_file("caisse.jpg", &renderer);
    let target_texture = load_texture_from_file("objectif.png", &renderer);
    let target_valid_texture = load_texture_from_file("caisse_ok.jpg", &renderer);

    grid_textures.insert(WALL, wall_texture);
    grid_textures.insert(BOX, box_texture);
    grid_textures.insert(TARGET, target_texture);
    grid_textures.insert(TARGETVALID, target_valid_texture);

    let mut grid_content: Vec<Vec<SquareType>> = get_level_content();

/*
    for i in range(0, rows) {
        let mut row = Vec::new();
        for j in range(0, columns) {
            let square_type = match FromPrimitive::from_uint(std::rand::random::<uint>() % 5) {
                Some(t) => t,
                None => EMPTY
            };
            row.push(square_type);
        }
        grid_content.push(row);
    }*/
    let grid = create_grid(grid_content, &grid_textures);
    println!("grid created");
    render_grid(&renderer, &grid, boxsize as i32);

    renderer.present();

    'main : loop {
        'event : loop {
            match sdl2::event::poll_event() {
                sdl2::event::QuitEvent(_) => break 'main,
                sdl2::event::KeyDownEvent(_, _, key, _, _) => {
                    if key == sdl2::keycode::EscapeKey {
                        break 'main
                    }
                },
                sdl2::event::NoEvent => break 'event,
                _ => {}
            }
        }
    }
    sdl2::quit();
}
#[deriving(FromPrimitive)]
#[deriving(Hash)]
pub enum SquareType {
    EMPTY = 0i,
    WALL = 1i,
    BOX = 2i,
    TARGET = 3i,
    TARGETVALID = 4i
}
impl PartialEq for SquareType {
    fn eq(&self, other: &SquareType) -> bool {
        *self as int == *other as int
    }
}
impl Eq for SquareType {}
pub struct Square<'a> {
    x: int,
    y: int,
    square_type: SquareType,
    texture: Option<&'a sdl2::render::Texture>
}

impl<'a> Square<'a> {
    pub fn set_texture(&mut self, texture: &'a sdl2::render::Texture) -> () {
        self.texture = Some(texture)
    }
}

pub fn load_texture_from_file(filename: &str, renderer: &sdl2::render::Renderer<sdl2::video::Window>) -> sdl2::render::Texture {
    let mut path = Path::new("./target/data/sprites");
    path.push(filename);

    let surface = match sdl2_image::LoadSurface::from_file(&path) {
        Ok(surface) => surface,
        Err(err) => fail!(format!("error on image load {}", err))
    };
    let texture = match renderer.create_texture_from_surface(&surface) {
        Ok(texture) => texture,
        Err(err) => fail!(format!("error on texture creation {}", err))
    };
    return texture;
}
pub fn get_level_content() -> Vec<Vec<SquareType>> {
    let level_path = Path::new("./target/data/level.txt");
    let mut file = BufferedReader::new(File::open(&level_path));
    let lines: Vec<String> = file.lines().map(|x| x.unwrap()).collect();

    let mut grid: Vec<Vec<SquareType>> = Vec::new();
    for line in lines.iter() {
        let mut row: Vec<SquareType> = Vec::new();
        let mut myline = line.clone();
        myline.pop();
        let slice: &str = myline.as_slice();
        for c in slice.chars() {
            let code: int = match c.to_digit(4) {
                Some(d) => d as int,
                None => 0i
            };
            let square_type = match FromPrimitive::from_int(code) {
                Some(t) => t,
                None => EMPTY
            };
            row.push(square_type);
        }
        grid.push(row);
    }
    return grid;
}

pub fn create_grid(content: Vec<Vec<SquareType>>, textures: &HashMap<SquareType, sdl2::render::Texture>) -> Vec<Vec<Square>> {
    let mut grid: Vec<Vec<Square>> = Vec::new();
    let mut i = 0i;

    for content_row in content.iter() {
        let mut row: Vec<Square> = Vec::new();
        let mut j = 0i;
        for square_type in content_row.iter() {
            let mut tex: Option<&sdl2::render::Texture> = None;
            if *square_type != EMPTY {
                tex = match textures.find(square_type) {
                    Some(texture) => Some(texture),
                    None => fail!(format!("error on texture retrieval for type {}", *square_type as int))
                };
            }
            row.push(create_square(j, i, *square_type, tex));
            j += 1;
        }
        i += 1;
        grid.push(row);
    }
    return grid;
}

pub fn create_square(x: int, y: int, square_type: SquareType, texture: Option<&sdl2::render::Texture>) -> Square {
    Square{x:x, y:y, square_type: square_type, texture:texture}
}

pub fn render_grid(renderer: &sdl2::render::Renderer<sdl2::video::Window>, grid: &Vec<Vec<Square>>, boxsize: i32) {
    for row in grid.iter() {
        for square in row.iter() {
            match square.texture {
                Some(texture) => {
                    let x: i32 = square.x as i32 * boxsize;
                    let y: i32 = square.y as i32 * boxsize;
                    let _ = renderer.copy(texture, None, Some(sdl2::rect::Rect::new(x, y, boxsize, boxsize)));
                },
                None => {}
            }
        }
    }
}
<commit_msg>remove commented out code<commit_after>extern crate sdl2;
extern crate sdl2_image;

use std::io::fs::PathExtensions;
use std::collections::HashMap;

use std::io::BufferedReader;
use std::io::File;

mod game;

fn main() {
    sdl2::init(sdl2::INIT_VIDEO);
    sdl2_image::init(sdl2_image::INIT_PNG | sdl2_image::INIT_JPG);

    let columns : int = 20;
    let rows : int = 20;
    let boxsize : int = 34;

    let window = match sdl2::video::Window::new("Sokoban", sdl2::video::PosCentered, sdl2::video::PosCentered, columns * boxsize, rows * boxsize, sdl2::video::OPENGL) {
        Ok(window) => window,
        Err(err) => fail!(format!("error on window init : {}", err))
    };

    let renderer = match sdl2::render::Renderer::from_window(window, sdl2::render::DriverAuto, sdl2::render::ACCELERATED) {
        Ok(renderer) => renderer,
        Err(err) => fail!(format!("failed to create renderer: {}", err))
    };

    let _ = renderer.set_draw_color(sdl2::pixels::RGB(255, 255, 255));
    let _ = renderer.clear();

    let mygame = game::Game::new();
    mygame.start();

    let mut grid_textures: HashMap<SquareType, sdl2::render::Texture> = HashMap::new();

    let wall_texture = load_texture_from_file("mur.jpg", &renderer);
    let box_texture = load_texture_from_file("caisse.jpg", &renderer);
    let target_texture = load_texture_from_file("objectif.png", &renderer);
    let target_valid_texture = load_texture_from_file("caisse_ok.jpg", &renderer);

    grid_textures.insert(WALL, wall_texture);
    grid_textures.insert(BOX, box_texture);
    grid_textures.insert(TARGET, target_texture);
    grid_textures.insert(TARGETVALID, target_valid_texture);

    let mut grid_content: Vec<Vec<SquareType>> = get_level_content();
    let grid = create_grid(grid_content, &grid_textures);
    render_grid(&renderer, &grid, boxsize as i32);
    renderer.present();

    'main : loop {
        'event : loop {
            match sdl2::event::poll_event() {
                sdl2::event::QuitEvent(_) => break 'main,
                sdl2::event::KeyDownEvent(_, _, key, _, _) => {
                    if key == sdl2::keycode::EscapeKey {
                        break 'main
                    }
                },
                sdl2::event::NoEvent => break 'event,
                _ => {}
            }
        }
    }
    sdl2::quit();
}
#[deriving(FromPrimitive)]
#[deriving(Hash)]
pub enum SquareType {
    EMPTY = 0i,
    WALL = 1i,
    BOX = 2i,
    TARGET = 3i,
    TARGETVALID = 4i
}
impl PartialEq for SquareType {
    fn eq(&self, other: &SquareType) -> bool {
        *self as int == *other as int
    }
}
impl Eq for SquareType {}
pub struct Square<'a> {
    x: int,
    y: int,
    square_type: SquareType,
    texture: Option<&'a sdl2::render::Texture>
}

impl<'a> Square<'a> {
    pub fn set_texture(&mut self, texture: &'a sdl2::render::Texture) -> () {
        self.texture = Some(texture)
    }
}

pub fn load_texture_from_file(filename: &str, renderer: &sdl2::render::Renderer<sdl2::video::Window>) -> sdl2::render::Texture {
    let mut path = Path::new("./target/data/sprites");
    path.push(filename);

    let surface = match sdl2_image::LoadSurface::from_file(&path) {
        Ok(surface) => surface,
        Err(err) => fail!(format!("error on image load {}", err))
    };
    let texture = match renderer.create_texture_from_surface(&surface) {
        Ok(texture) => texture,
        Err(err) => fail!(format!("error on texture creation {}", err))
    };
    return texture;
}
pub fn get_level_content() -> Vec<Vec<SquareType>> {
    let level_path = Path::new("./target/data/level.txt");
    let mut file = BufferedReader::new(File::open(&level_path));
    let lines: Vec<String> = file.lines().map(|x| x.unwrap()).collect();

    let mut grid: Vec<Vec<SquareType>> = Vec::new();
    for line in lines.iter() {
        let mut row: Vec<SquareType> = Vec::new();
        let mut myline = line.clone();
        myline.pop();
        let slice: &str = myline.as_slice();
        for c in slice.chars() {
            let code: int = match c.to_digit(4) {
                Some(d) => d as int,
                None => 0i
            };
            let square_type = match FromPrimitive::from_int(code) {
                Some(t) => t,
                None => EMPTY
            };
            row.push(square_type);
        }
        grid.push(row);
    }
    return grid;
}

pub fn create_grid(content: Vec<Vec<SquareType>>, textures: &HashMap<SquareType, sdl2::render::Texture>) -> Vec<Vec<Square>> {
    let mut grid: Vec<Vec<Square>> = Vec::new();
    let mut i = 0i;

    for content_row in content.iter() {
        let mut row: Vec<Square> = Vec::new();
        let mut j = 0i;
        for square_type in content_row.iter() {
            let mut tex: Option<&sdl2::render::Texture> = None;
            if *square_type != EMPTY {
                tex = match textures.find(square_type) {
                    Some(texture) => Some(texture),
                    None => fail!(format!("error on texture retrieval for type {}", *square_type as int))
                };
            }
            row.push(create_square(j, i, *square_type, tex));
            j += 1;
        }
        i += 1;
        grid.push(row);
    }
    return grid;
}

pub fn create_square(x: int, y: int, square_type: SquareType, texture: Option<&sdl2::render::Texture>) -> Square {
    Square{x:x, y:y, square_type: square_type, texture:texture}
}

pub fn render_grid(renderer: &sdl2::render::Renderer<sdl2::video::Window>, grid: &Vec<Vec<Square>>, boxsize: i32) {
    for row in grid.iter() {
        for square in row.iter() {
            match square.texture {
                Some(texture) => {
                    let x: i32 = square.x as i32 * boxsize;
                    let y: i32 = square.y as i32 * boxsize;
                    let _ = renderer.copy(texture, None, Some(sdl2::rect::Rect::new(x, y, boxsize, boxsize)));
                },
                None => {}
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 rust-fuzz developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

extern crate toml;
extern crate clap;
extern crate term;
#[macro_use]
extern crate error_chain;

use clap::{App, Arg, SubCommand, ArgMatches, AppSettings};
use std::{env, fs, path, ffi, process};
use std::io::Write;
use std::io::Read;

#[macro_use]
mod templates;
mod utils;

error_chain! {
    foreign_links {
        Toml(toml::de::Error);
        Io(::std::io::Error);
    }
}

fn main() {
    let app = App::new("cargo-fuzz")
        .version(option_env!("CARGO_PKG_VERSION").unwrap_or("0.0.0"))
        .about(option_env!("CARGO_PKG_DESCRIPTION").unwrap_or(""))
        .setting(AppSettings::SubcommandRequiredElseHelp)
        .setting(AppSettings::GlobalVersion)
        // cargo passes in the subcommand name to the invoked executable. Use a hidden, optional
        // positional argument to deal with it?
        .arg(Arg::with_name("dummy").possible_value("fuzz").required(false).hidden(true))
        .subcommand(SubCommand::with_name("init").about("Initialize the fuzz folder"))
        .subcommand(SubCommand::with_name("run").about("Run the fuzz target in fuzz/fuzzers")
            .arg(Arg::with_name("release").long("release").short("O")
                 .help("Build artifacts in release mode, with optimizations"))
            .arg(Arg::with_name("debug_assertions").long("debug-assertions").short("a")
                 .help("Build artifacts with debug assertions enabled (default if not -O)"))
            .arg(Arg::with_name("TARGET").required(true)
                 .help("name of the fuzz target"))
            .arg(Arg::with_name("CORPUS").multiple(true)
                 .help("custom corpus directory or artefact files"))
            .arg(Arg::with_name("ARGS").multiple(true).last(true)
                 .help("additional libFuzzer arguments passed to the binary"))
        )
        .subcommand(SubCommand::with_name("add").about("Add a new fuzz target")
                    .arg(Arg::with_name("TARGET").required(true)
                         .help("name of the fuzz target"))
        )
        .subcommand(SubCommand::with_name("list").about("List all fuzz targets"));
    let args = app.get_matches();

    ::std::process::exit(match args.subcommand() {
        ("init", _) => FuzzProject::init().map(|_| ()),
        ("add", matches) =>
            FuzzProject::new().and_then(|p| p.add_target(matches.expect("arguments present"))),
        ("list", _) => FuzzProject::new().and_then(|p| p.list_targets()),
        ("run", matches) =>
            FuzzProject::new().and_then(|p| p.exec_target(matches.expect("arguments present"))),
        (s, _) => panic!("unimplemented subcommand {}!", s),
    }.map(|_| 0).unwrap_or_else(|err| {
        utils::report_error(&err);
        1
    }));
}

struct FuzzProject {
    /// Path to the root cargo project
    ///
    /// Not the project with fuzz targets, but the project being fuzzed
    root_project: path::PathBuf,
    targets: Vec<String>,
}

impl FuzzProject {
    fn new() -> Result<Self> {
        let mut project = FuzzProject {
            root_project: find_package()?,
            targets: Vec::new()
        };
        let manifest = project.manifest()?;
        if !is_fuzz_manifest(&manifest) {
            return Err(format!("manifest `{:?}` does not look a cargo-fuzz manifest. \
                                Add following lines to override:\n\
                                [package.metadata]\ncargo-fuzz = true",
                                project.manifest_path()).into());
        }
        project.targets = collect_targets(&manifest);
        Ok(project)
    }

    /// Create the fuzz project structure
    ///
    /// This will not clone libfuzzer-sys
    fn init() -> Result<Self> {
        let project = FuzzProject {
            root_project: find_package()?,
            targets: Vec::new(),
        };
        let fuzz_project = project.path();
        let root_project_name = try!(project.root_project_name());

        // TODO: check if the project is already initialized
        fs::create_dir(&fuzz_project)?;
        fs::create_dir(fuzz_project.join("fuzzers"))?;

        let mut cargo = fs::File::create(fuzz_project.join("Cargo.toml"))?;
        cargo.write_fmt(toml_template!(root_project_name))?;

        let mut ignore = fs::File::create(fuzz_project.join(".gitignore"))?;
        ignore.write_fmt(gitignore_template!())?;

        const TARGET: &'static str = "fuzzer_script_1";
        project.create_target_template(TARGET)
               .chain_err(|| format!("could not create template file for target {:?}", TARGET))?;
        Ok(project)
    }

    fn list_targets(&self) -> Result<()> {
        for bin in &self.targets {
            utils::print_message(bin, term::color::GREEN);
        }
        Ok(())
    }

    fn add_target(&self, args: &ArgMatches) -> Result<()> {
        let target: String = args.value_of_os("TARGET").expect("TARGET is required").to_os_string()
            .into_string().map_err(|_| "TARGET must be valid unicode")?;
        // Create corpus and artifact directories for the newly added target
        self.corpus_for(&target)?;
        self.artifacts_for(&target)?;
        self.create_target_template(&target)
            .chain_err(|| format!("could not add target {:?}", target))
    }

    /// Add a new fuzz target script with a given name
    fn create_target_template(&self, target: &str) -> Result<()> {
        let target_path = self.target_path(target);
        let mut script = fs::OpenOptions::new().write(true).create_new(true).open(&target_path)
            .chain_err(|| format!("could not create target script file at {:?}", target_path))?;
        script.write_fmt(target_template!(self.root_project_name()?.replace("-", "_")))?;

        let mut cargo = fs::OpenOptions::new().append(true)
            .open(self.manifest_path())?;
        Ok(cargo.write_fmt(toml_bin_template!(target))?)
    }

    /// Fuzz a given fuzz target
    fn exec_target<'a>(&self, args: &ArgMatches<'a>) -> Result<()> {
        let target: String = args.value_of_os("TARGET").expect("TARGET is required").to_os_string()
            .into_string().map_err(|_| "TARGET must be valid unicode")?;
        let release: bool = args.is_present("release");
        let assertions: bool = args.is_present("debug_assertions");
        let corpus = args.values_of_os("CORPUS");
        let exec_args = args.values_of_os("ARGS")
                            .map(|v| v.collect::<Vec<_>>());
        let target_triple = "x86_64-unknown-linux-gnu";

        let other_flags = env::var("RUSTFLAGS").unwrap_or_default();
        let mut flags: Vec<&str> = vec![
            "-Cpasses=sancov",
            "-Cllvm-args=-sanitizer-coverage-level=3",
            "-Zsanitizer=address",
            "-Cpanic=abort",
        ];
        if assertions {
            flags.push("-Cdebug-assertions");
        }
        flags.extend(other_flags.split(' '));
        let rustflags = flags.join(" ");

        let mut cmd = process::Command::new("cargo");

        let mut artefact_arg = ffi::OsString::from("-artifact_prefix=");
        artefact_arg.push(self.artifacts_for(&target)?);

        // Merge the asan options, so users can still provide their own options
        // to e.g. disable the leak sanitizer. Options are colon-separated.
        let mut asan_opts = env::var("ASAN_OPTIONS").unwrap_or_default();
        if !asan_opts.is_empty() {
            asan_opts.push(':');
        }
        asan_opts.push_str("detect_odr_violation=0");

        cmd.env("RUSTFLAGS", rustflags)
           .env("ASAN_OPTIONS", &asan_opts)
           .arg("run")
           .arg("--manifest-path")
           .arg(self.manifest_path());
        if release {
            cmd.arg("--release");
        }
        cmd.arg("--verbose")
           .arg("--bin")
           .arg(&target)
           .arg("--target")
           // won't pass rustflags to build scripts
           .arg(target_triple)
           .arg("--")
           .arg(artefact_arg);

        if let Some(args) = exec_args {
            for arg in args {
                cmd.arg(arg);
            }
        }
        if let Some(corpus) = corpus {
            for arg in corpus {
                cmd.arg(arg);
            }
        } else {
            cmd.arg(self.corpus_for(&target)?);
        }

        exec_cmd(&mut cmd).chain_err(|| format!("could not execute command: {:?}", cmd))?;
        Ok(())
    }

    fn path(&self) -> path::PathBuf {
        self.root_project.join("fuzz")
    }

    fn manifest_path(&self) -> path::PathBuf {
        self.path().join("Cargo.toml")
    }

    fn corpus_for(&self, target: &str) -> Result<path::PathBuf> {
        let mut p = self.path();
        p.push("corpus");
        p.push(target);
        fs::create_dir_all(&p)
            .chain_err(|| format!("could not make a corpus directory at {:?}", p))?;
        Ok(p)
    }

    fn artifacts_for(&self, target: &str) -> Result<path::PathBuf> {
        let mut p = self.path();
        p.push("artifacts");
        p.push(target);
        p.push(""); // trailing slash, necessary for libfuzzer, because it does simple concat
        fs::create_dir_all(&p)
            .chain_err(|| format!("could not make a artifact directory at {:?}", p))?;
        Ok(p)
    }

    fn target_path(&self, target: &str) -> path::PathBuf {
        let mut root = self.path();
        root.push("fuzzers");
        root.push(target);
        root.set_extension("rs");
        root
    }

    fn manifest(&self) -> Result<toml::Value> {
        let filename = self.manifest_path();
        let mut file = fs::File::open(&filename).chain_err(||
            format!("could not read the manifest file: {:?}", filename)
        )?;
        let mut data = Vec::new();
        file.read_to_end(&mut data)?;
        toml::from_slice(&data).chain_err(||
            format!("could not decode the manifest file at {:?}", filename)
        )
    }

    fn root_project_name(&self) -> Result<String> {
        let filename = self.root_project.join("Cargo.toml");
        let mut file = fs::File::open(&filename)?;
        let mut data = Vec::new();
        file.read_to_end(&mut data)?;
        let value: toml::Value = toml::from_slice(&data)?;
        let name = value.as_table().and_then(|v| v.get("package"))
                                   .and_then(toml::Value::as_table)
                                   .and_then(|v| v.get("name"))
                                   .and_then(toml::Value::as_str);
        if let Some(name) = name {
            Ok(String::from(name))
        } else {
            Err(format!("{:?} (package.name) is malformed", filename).into())
        }
    }
}

fn collect_targets(value: &toml::Value) -> Vec<String> {
    let bins = value.as_table().and_then(|v| v.get("bin"))
                               .and_then(toml::Value::as_array);
    if let Some(bins) = bins {
        bins.iter().map(|bin|
            bin.as_table().and_then(|v| v.get("name")).and_then(toml::Value::as_str)
        ).filter_map(|name| name.map(String::from)).collect()
    } else {
        Vec::new()
    }
}

fn is_fuzz_manifest(value: &toml::Value) -> bool {
    let is_fuzz = value.as_table().and_then(|v| v.get("package"))
                                  .and_then(toml::Value::as_table)
                                  .and_then(|v| v.get("metadata"))
                                  .and_then(toml::Value::as_table)
                                  .and_then(|v| v.get("cargo-fuzz"))
                                  .and_then(toml::Value::as_bool);
    is_fuzz == Some(true)
}

/// Returns the path for the first found non-fuzz Cargo package
fn find_package() -> Result<path::PathBuf> {
    let mut dir = env::current_dir()?;
    let mut data = Vec::new();
    loop {
        let manifest_path = dir.join("Cargo.toml");
        match fs::File::open(&manifest_path) {
            Err(_) => {},
            Ok(mut f) => {
                f.read_to_end(&mut data)?;
                let value: toml::Value = toml::from_slice(&data)
                    .chain_err(||
                        format!("could not decode the manifest file at {:?}", manifest_path)
                    )?;
                if !is_fuzz_manifest(&value) {
                    // Not a cargo-fuzz project => must be a proper cargo project :)
                    return Ok(dir);
                }
            }
        }
        if !dir.pop() { break; }
    }
    Err("could not find a cargo project".into())
}

#[cfg(unix)]
fn exec_cmd(cmd: &mut process::Command) -> Result<process::ExitStatus> {
    use std::os::unix::process::CommandExt;
    Err(cmd.exec().into())
}

#[cfg(not(unix))]
fn exec_cmd(cmd: &mut process::Command) -> Result<process::ExitStatus> {
    cmd.status().map_err(|e| e.into())
}
<commit_msg>Added `--sanitizer` option for using other sanitizers.<commit_after>// Copyright 2016 rust-fuzz developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

extern crate toml;
extern crate clap;
extern crate term;
#[macro_use]
extern crate error_chain;

use clap::{App, Arg, SubCommand, ArgMatches, AppSettings};
use std::{env, fs, path, ffi, process};
use std::io::Write;
use std::io::Read;

#[macro_use]
mod templates;
mod utils;

error_chain! {
    foreign_links {
        Toml(toml::de::Error);
        Io(::std::io::Error);
    }
}

fn main() {
    let app = App::new("cargo-fuzz")
        .version(option_env!("CARGO_PKG_VERSION").unwrap_or("0.0.0"))
        .about(option_env!("CARGO_PKG_DESCRIPTION").unwrap_or(""))
        .setting(AppSettings::SubcommandRequiredElseHelp)
        .setting(AppSettings::GlobalVersion)
        // cargo passes in the subcommand name to the invoked executable. Use a hidden, optional
        // positional argument to deal with it?
        .arg(Arg::with_name("dummy").possible_value("fuzz").required(false).hidden(true))
        .subcommand(SubCommand::with_name("init").about("Initialize the fuzz folder"))
        .subcommand(SubCommand::with_name("run").about("Run the fuzz target in fuzz/fuzzers")
            .arg(Arg::with_name("release").long("release").short("O")
                 .help("Build artifacts in release mode, with optimizations"))
            .arg(Arg::with_name("debug_assertions").long("debug-assertions").short("a")
                 .help("Build artifacts with debug assertions enabled (default if not -O)"))
            .arg(Arg::with_name("sanitizer").long("sanitizer").short("s")
                 .takes_value(true)
                 .possible_values(&["address", "leak", "memory", "thread"])
                 .default_value("address")
                 .help("Use different sanitizer"))
            .arg(Arg::with_name("TARGET").required(true)
                 .help("name of the fuzz target"))
            .arg(Arg::with_name("CORPUS").multiple(true)
                 .help("custom corpus directory or artefact files"))
            .arg(Arg::with_name("ARGS").multiple(true).last(true)
                 .help("additional libFuzzer arguments passed to the binary"))
        )
        .subcommand(SubCommand::with_name("add").about("Add a new fuzz target")
                    .arg(Arg::with_name("TARGET").required(true)
                         .help("name of the fuzz target"))
        )
        .subcommand(SubCommand::with_name("list").about("List all fuzz targets"));
    let args = app.get_matches();

    ::std::process::exit(match args.subcommand() {
        ("init", _) => FuzzProject::init().map(|_| ()),
        ("add", matches) =>
            FuzzProject::new().and_then(|p| p.add_target(matches.expect("arguments present"))),
        ("list", _) => FuzzProject::new().and_then(|p| p.list_targets()),
        ("run", matches) =>
            FuzzProject::new().and_then(|p| p.exec_target(matches.expect("arguments present"))),
        (s, _) => panic!("unimplemented subcommand {}!", s),
    }.map(|_| 0).unwrap_or_else(|err| {
        utils::report_error(&err);
        1
    }));
}

struct FuzzProject {
    /// Path to the root cargo project
    ///
    /// Not the project with fuzz targets, but the project being fuzzed
    root_project: path::PathBuf,
    targets: Vec<String>,
}

impl FuzzProject {
    fn new() -> Result<Self> {
        let mut project = FuzzProject {
            root_project: find_package()?,
            targets: Vec::new()
        };
        let manifest = project.manifest()?;
        if !is_fuzz_manifest(&manifest) {
            return Err(format!("manifest `{:?}` does not look a cargo-fuzz manifest. \
                                Add following lines to override:\n\
                                [package.metadata]\ncargo-fuzz = true",
                                project.manifest_path()).into());
        }
        project.targets = collect_targets(&manifest);
        Ok(project)
    }

    /// Create the fuzz project structure
    ///
    /// This will not clone libfuzzer-sys
    fn init() -> Result<Self> {
        let project = FuzzProject {
            root_project: find_package()?,
            targets: Vec::new(),
        };
        let fuzz_project = project.path();
        let root_project_name = try!(project.root_project_name());

        // TODO: check if the project is already initialized
        fs::create_dir(&fuzz_project)?;
        fs::create_dir(fuzz_project.join("fuzzers"))?;

        let mut cargo = fs::File::create(fuzz_project.join("Cargo.toml"))?;
        cargo.write_fmt(toml_template!(root_project_name))?;

        let mut ignore = fs::File::create(fuzz_project.join(".gitignore"))?;
        ignore.write_fmt(gitignore_template!())?;

        const TARGET: &'static str = "fuzzer_script_1";
        project.create_target_template(TARGET)
               .chain_err(|| format!("could not create template file for target {:?}", TARGET))?;
        Ok(project)
    }

    fn list_targets(&self) -> Result<()> {
        for bin in &self.targets {
            utils::print_message(bin, term::color::GREEN);
        }
        Ok(())
    }

    fn add_target(&self, args: &ArgMatches) -> Result<()> {
        let target: String = args.value_of_os("TARGET").expect("TARGET is required").to_os_string()
            .into_string().map_err(|_| "TARGET must be valid unicode")?;
        // Create corpus and artifact directories for the newly added target
        self.corpus_for(&target)?;
        self.artifacts_for(&target)?;
        self.create_target_template(&target)
            .chain_err(|| format!("could not add target {:?}", target))
    }

    /// Add a new fuzz target script with a given name
    fn create_target_template(&self, target: &str) -> Result<()> {
        let target_path = self.target_path(target);
        let mut script = fs::OpenOptions::new().write(true).create_new(true).open(&target_path)
            .chain_err(|| format!("could not create target script file at {:?}", target_path))?;
        script.write_fmt(target_template!(self.root_project_name()?.replace("-", "_")))?;

        let mut cargo = fs::OpenOptions::new().append(true)
            .open(self.manifest_path())?;
        Ok(cargo.write_fmt(toml_bin_template!(target))?)
    }

    /// Fuzz a given fuzz target
    fn exec_target<'a>(&self, args: &ArgMatches<'a>) -> Result<()> {
        let target: String = args.value_of_os("TARGET").expect("TARGET is required").to_os_string()
            .into_string().map_err(|_| "TARGET must be valid unicode")?;
        let release: bool = args.is_present("release");
        let assertions: bool = args.is_present("debug_assertions");
        let sanitizer: &str = args.value_of("sanitizer").expect("no sanitizer");
        let corpus = args.values_of_os("CORPUS");
        let exec_args = args.values_of_os("ARGS")
                            .map(|v| v.collect::<Vec<_>>());
        let target_triple = "x86_64-unknown-linux-gnu";

        let other_flags = env::var("RUSTFLAGS").unwrap_or_default();
        let mut rustflags: String = format!(
            "-Cpasses=sancov \
             -Cllvm-args=-sanitizer-coverage-level=3 \
             -Zsanitizer={sanitizer} \
             -Cpanic=abort",
            sanitizer = sanitizer,
        );
        if assertions {
            rustflags.push_str(" -Cdebug-assertions");
        }
        if !other_flags.is_empty() {
            rustflags.push_str(" ");
            rustflags.push_str(&other_flags);
        }

        let mut cmd = process::Command::new("cargo");

        let mut artefact_arg = ffi::OsString::from("-artifact_prefix=");
        artefact_arg.push(self.artifacts_for(&target)?);

        // For asan and tsan we have default options. Merge them to the given options,
        // so users can still provide their own options to e.g. disable the leak sanitizer.
        // Options are colon-separated.
        match sanitizer {
            "address" => {
                let mut asan_opts = env::var("ASAN_OPTIONS").unwrap_or_default();
                if !asan_opts.is_empty() {
                    asan_opts.push(':');
                }
                asan_opts.push_str("detect_odr_violation=0");
                cmd.env("ASAN_OPTIONS", &asan_opts);
            }

            "thread" => {
                let mut tsan_opts = env::var("TSAN_OPTIONS").unwrap_or_default();
                if !tsan_opts.is_empty() {
                    tsan_opts.push(':');
                }
                tsan_opts.push_str("report_signal_unsafe=0");
                cmd.env("TSAN_OPTIONS", &tsan_opts);
            }

            _ => {}
        }

        cmd.env("RUSTFLAGS", rustflags)
           .arg("run")
           .arg("--manifest-path")
           .arg(self.manifest_path());
        if release {
            cmd.arg("--release");
        }
        cmd.arg("--verbose")
           .arg("--bin")
           .arg(&target)
           .arg("--target")
           // won't pass rustflags to build scripts
           .arg(target_triple)
           .arg("--")
           .arg(artefact_arg);

        if let Some(args) = exec_args {
            for arg in args {
                cmd.arg(arg);
            }
        }
        if let Some(corpus) = corpus {
            for arg in corpus {
                cmd.arg(arg);
            }
        } else {
            cmd.arg(self.corpus_for(&target)?);
        }

        exec_cmd(&mut cmd).chain_err(|| format!("could not execute command: {:?}", cmd))?;
        Ok(())
    }

    fn path(&self) -> path::PathBuf {
        self.root_project.join("fuzz")
    }

    fn manifest_path(&self) -> path::PathBuf {
        self.path().join("Cargo.toml")
    }

    fn corpus_for(&self, target: &str) -> Result<path::PathBuf> {
        let mut p = self.path();
        p.push("corpus");
        p.push(target);
        fs::create_dir_all(&p)
            .chain_err(|| format!("could not make a corpus directory at {:?}", p))?;
        Ok(p)
    }

    fn artifacts_for(&self, target: &str) -> Result<path::PathBuf> {
        let mut p = self.path();
        p.push("artifacts");
        p.push(target);
        p.push(""); // trailing slash, necessary for libfuzzer, because it does simple concat
        fs::create_dir_all(&p)
            .chain_err(|| format!("could not make a artifact directory at {:?}", p))?;
        Ok(p)
    }

    fn target_path(&self, target: &str) -> path::PathBuf {
        let mut root = self.path();
        root.push("fuzzers");
        root.push(target);
        root.set_extension("rs");
        root
    }

    fn manifest(&self) -> Result<toml::Value> {
        let filename = self.manifest_path();
        let mut file = fs::File::open(&filename).chain_err(||
            format!("could not read the manifest file: {:?}", filename)
        )?;
        let mut data = Vec::new();
        file.read_to_end(&mut data)?;
        toml::from_slice(&data).chain_err(||
            format!("could not decode the manifest file at {:?}", filename)
        )
    }

    fn root_project_name(&self) -> Result<String> {
        let filename = self.root_project.join("Cargo.toml");
        let mut file = fs::File::open(&filename)?;
        let mut data = Vec::new();
        file.read_to_end(&mut data)?;
        let value: toml::Value = toml::from_slice(&data)?;
        let name = value.as_table().and_then(|v| v.get("package"))
                                   .and_then(toml::Value::as_table)
                                   .and_then(|v| v.get("name"))
                                   .and_then(toml::Value::as_str);
        if let Some(name) = name {
            Ok(String::from(name))
        } else {
            Err(format!("{:?} (package.name) is malformed", filename).into())
        }
    }
}

fn collect_targets(value: &toml::Value) -> Vec<String> {
    let bins = value.as_table().and_then(|v| v.get("bin"))
                               .and_then(toml::Value::as_array);
    if let Some(bins) = bins {
        bins.iter().map(|bin|
            bin.as_table().and_then(|v| v.get("name")).and_then(toml::Value::as_str)
        ).filter_map(|name| name.map(String::from)).collect()
    } else {
        Vec::new()
    }
}

fn is_fuzz_manifest(value: &toml::Value) -> bool {
    let is_fuzz = value.as_table().and_then(|v| v.get("package"))
                                  .and_then(toml::Value::as_table)
                                  .and_then(|v| v.get("metadata"))
                                  .and_then(toml::Value::as_table)
                                  .and_then(|v| v.get("cargo-fuzz"))
                                  .and_then(toml::Value::as_bool);
    is_fuzz == Some(true)
}

/// Returns the path for the first found non-fuzz Cargo package
fn find_package() -> Result<path::PathBuf> {
    let mut dir = env::current_dir()?;
    let mut data = Vec::new();
    loop {
        let manifest_path = dir.join("Cargo.toml");
        match fs::File::open(&manifest_path) {
            Err(_) => {},
            Ok(mut f) => {
                f.read_to_end(&mut data)?;
                let value: toml::Value = toml::from_slice(&data)
                    .chain_err(||
                        format!("could not decode the manifest file at {:?}", manifest_path)
                    )?;
                if !is_fuzz_manifest(&value) {
                    // Not a cargo-fuzz project => must be a proper cargo project :)
                    return Ok(dir);
                }
            }
        }
        if !dir.pop() { break; }
    }
    Err("could not find a cargo project".into())
}

#[cfg(unix)]
fn exec_cmd(cmd: &mut process::Command) -> Result<process::ExitStatus> {
    use std::os::unix::process::CommandExt;
    Err(cmd.exec().into())
}

#[cfg(not(unix))]
fn exec_cmd(cmd: &mut process::Command) -> Result<process::ExitStatus> {
    cmd.status().map_err(|e| e.into())
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate rustc_serialize;

mod state;

use rustc_serialize::json;
use hyper::Get;
use hyper::server::{Server, Request, Response};
use hyper::uri::RequestUri::AbsolutePath;

macro_rules! try_return(
    ($e:expr) => {{
        match $e {
            Ok(v) => v,
            Err(e) => { println!("Error: {}", e); return; }
        }
    }}
    );

fn handle_request(req: Request, mut res: Response) {
    match req.uri {
        AbsolutePath(ref path) => match (&req.method, &path[..]) {
            (&Get, "/") => {
                try_return!(res.send(b"Hey, what up."));
                return;
            },
            (&Get, "/state") => {
                let game = state::initial_state();
                let encoded = json::encode(&game).unwrap();
                try_return!(res.send(encoded.as_bytes()));
                return;
            }
            _ => {
                *res.status_mut() = hyper::NotFound;
                return;
            }
        },
        _ => {
            return;
        }
    };
}

fn main() {
    let server = Server::http("localhost:3001").unwrap();
    let _guard = server.handle(handle_request);
    println!("Starting server on localhost:3001");
}
<commit_msg>Add /turn POST API with stubbed in response of the req.body<commit_after>extern crate hyper;
extern crate rustc_serialize;

mod state;

use std::io::Read;
use rustc_serialize::json;
use hyper::{Get, Post};
use hyper::header::ContentLength;
use hyper::server::{Server, Request, Response};
use hyper::uri::RequestUri::AbsolutePath;

macro_rules! try_return(
    ($e:expr) => {{
        match $e {
            Ok(v) => v,
            Err(e) => { println!("Error: {}", e); return; }
        }
    }}
    );

fn handle_request(mut req: Request, mut res: Response) {
    let mut body: String  = "".to_string();
    req.read_to_string(&mut body);

    let path = match req.uri {
        AbsolutePath(ref path) => {
            path
        },
        _ => panic!("Unsupported URI format."),
    };

    match path.as_ref() {
        "/" => {
            match req.method {
                Get => {
                    try_return!(res.send(b"Hey, what up."));
                },
                _ => {
                    *res.status_mut() = hyper::BadRequest;
                    (*res.headers_mut()).set(ContentLength(0));
                }
            }
        },
        "/state" => {
            match req.method {
                Get => {
                    let game = state::initial_state();
                    let encoded = json::encode(&game).unwrap();
                    try_return!(res.send(encoded.as_bytes()));
                },
                _ => {
                    *res.status_mut() = hyper::BadRequest;
                    (*res.headers_mut()).set(ContentLength(0));
                }
            }
        },
        "/turn" => {
            match req.method {
                Post => {
                    try_return!(res.send(body.as_bytes()));
                },
                _ => {
                    *res.status_mut() = hyper::BadRequest;
                    (*res.headers_mut()).set(ContentLength(0));
                }
            }
        },
        _ => {
            *res.status_mut() = hyper::NotFound;
            (*res.headers_mut()).set(ContentLength(0));
        }
    }
}

fn main() {
    let server = Server::http("localhost:3001").unwrap();
    let _guard = server.handle(handle_request);
    println!("Starting server on localhost:3001");
}
<|endoftext|>