<commit_before>
// use std::fmt::Debug;

// pub fn insertion_sort<T: Debug>(array: &mut Vec<T>) {
pub fn insertion_sort(array: &mut Vec<f64>) {
    let n = array.len();

    if n > 1 {
        println!("  simplesorts::insertion_sort():  N = {:?}", n);
        for (i,elem) in array.iter().enumerate() {
            println!("    simplesorts::insertion_sort():  i={}   {:?}", i, elem);
        }
    }
}
<commit_msg>Use slices for input and output<commit_after>
use std::fmt::Debug;

pub fn insertion_sort<T: Clone + Debug>(input: &[T]) -> &[T] {
    let n = input.len();

    let output = input.clone();

    println!("  simplesorts::insertion_sort():  n = {:?}", n);
    println!("  simplesorts::insertion_sort():  input:  {:?}", input);
    println!("  simplesorts::insertion_sort():  output: {:?}", output);

    for (i,elem) in input.iter().enumerate() {
        println!("    simplesorts::insertion_sort():  i={}   {:?}", i, elem);
    }

    return output;
}
<|endoftext|>


<commit_before>

#[cfg(windows)]
mod mmap {
    use libc::{CreateFileW, CreateFileMappingW, MapViewOfFile, CloseHandle, UnmapViewOfFile,
               GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, INVALID_HANDLE_VALUE, PAGE_READONLY,
               FILE_MAP_READ, HANDLE, TRUE};
    use libc::consts::os::extra::{FILE_FLAG_RANDOM_ACCESS};
    use libc::types::os::arch::extra::{LPCVOID};
    use std::ptr;
    struct Handle {
        hand: HANDLE,
    }
    impl Drop for Handle {
        fn drop(&mut self) {
            assert_eq!(unsafe { CloseHandle(self.hand) }, TRUE);
        }
    }
    struct MapView {
        data: LPCVOID,
    }
    impl Drop for MapView {
        fn drop(&mut self) {
            assert_eq!(unsafe { UnmapViewOfFile(self.data) }, TRUE);
        }
    }
    pub struct MapFile {
        view: MapView,
        map: Handle,
        file: Handle,
    }
    impl MapFile {
        pub fn data(&self) -> LPCVOID { self.view.data }
    }
    fn create_file(path: &Path) -> Result<Handle, &'static str> {
        let name = path.as_str().unwrap().to_utf16().append([0]);
        let file = unsafe {
            CreateFileW(name.as_ptr(), GENERIC_READ, FILE_SHARE_READ, ptr::mut_null(),
                        OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, ptr::mut_null())
        };
        if file.to_uint() == INVALID_HANDLE_VALUE as uint { return Err("Failed to open file"); }
        Ok(Handle{hand: file})
    }
    fn create_mapping(file: &Handle) -> Result<Handle, &'static str> {
        let map = unsafe {
            CreateFileMappingW(file.hand, ptr::mut_null(), PAGE_READONLY, 0, 0, ptr::null())
        };
        if map.is_null() { return Err("Failed to create file mapping"); }
        Ok(Handle{hand: map})
    }
    fn map_view(map: &Handle) -> Result<MapView, &'static str> {
        let view = unsafe { MapViewOfFile(map.hand, FILE_MAP_READ, 0, 0, 0) };
        if view.is_null() { return Err("Failed to map view of file"); }
        Ok(MapView{data: view as *_})
    }
    pub fn open(path: &Path) -> Result<MapFile, &'static str> {
        let file = try!(create_file(path));
        let map = try!(create_mapping(&file));
        let view = try!(map_view(&map));
        Ok(MapFile{file: file, map: map, view: view})
    }
}
#[cfg(unix)]
mod mmap {
    use libc::{close, fstat, mmap, munmap, O_RDONLY, PROT_READ, stat, c_int, c_void};
    use libc::consts::os::posix88::{MAP_SHARED};
    use posix_open = libc::open;
    use std::mem::{uninitialized, transmute};
    use std::ptr;
    use std::io::fs::stat;
    struct Handle {
        hand: c_int,
    }
    impl Drop for Handle {
        fn drop(&mut self) {
            assert_eq!(unsafe { close(self.hand) }, 0);
        }
    }
    struct Mapping {
        data: *mut c_void,
        size: u64,
    }
    impl Drop for Mapping {
        fn drop(&mut self) {
            assert_eq!(unsafe { munmap(self.data as *c_void, self.size) }, 0);
        }
    }
    pub struct MapFile {
        map: Mapping,
        file: Handle,
    }
    impl MapFile {
        pub fn data(&self) -> * c_void { self.map.data as *_ }
    }
    fn open_file(path: &Path) -> Result<Handle, &'static str> {
        let name = path.to_c_str();
        let handle = unsafe {
             posix_open(name.unwrap(), O_RDONLY, 0)
        };
        if (handle == -1) { return Err("Failed to open file") }
        Ok(Handle{hand: handle})
    }
    fn file_size(path: &Path) -> Result<u64, &'static str> {
        match path.stat() {
            Ok(stat) => Ok(stat.size),
            Err(_) => Err("Failed to get file size")
        }
    }
    fn map_file(file: &Handle, size: u64) -> Result<Mapping, &'static str> {
        let map = unsafe {
            mmap(ptr::null(), size as u64, PROT_READ, MAP_SHARED, file.hand, 0)
        };
        if map.to_uint() == -1 { return Err("Failed to map file"); }
        Ok(Mapping{data: map, size: size})
    }
    pub fn open(path: &Path) -> Result<MapFile, &'static str> {
        let file = try!(open_file(path));
        let size = try!(file_size(path));
        let map = try!(map_file(&file, size));
        Ok(MapFile{file: file, map: map})
    }
}
pub struct File {
    map: mmap::MapFile,
    data: *u8,
    header: *Header,
    nodetable: *NodeData,
    stringtable: *u64,
}
impl File {
    pub fn open(path: &Path) -> Result<File, &'static str> {
        use std::mem::transmute;
        let map = try!(mmap::open(path));
        let data = map.data();
        let header: *Header = unsafe{ transmute(data) };
        if unsafe { (*header).magic } != 0x34474B50 {
            return Err("Not a valid NX PKG4 file");
        }
        unsafe {
            Ok(File{map: map, data: transmute(data), header: header,
                    nodetable: transmute(data.offset((*header).nodeoffset as int)),
                    stringtable: transmute(data.offset((*header).stringoffset as int))})
        }
    }
    fn header(&self) -> &Header {
        use std::mem::transmute;
        unsafe { transmute(self.header) }
    }
    pub fn root<'a>(&'a self) -> Node<'a> {
        unsafe { Node{data: &*self.nodetable, file: self,} }
    }
    fn get_str<'a>(&'a self, index: u32) -> Option<&'a str> {
        use std::str;
        use std::slice::raw;
        use std::mem::transmute;
        unsafe {
            let off = *self.stringtable.offset(index as int);
            let ptr = self.data.offset(off as int);
            let size: *u16 = transmute(ptr);
            raw::buf_as_slice(ptr.offset(2), (*size) as uint, |buf| {
                let bytes: &'a [u8] = transmute(buf);
                str::from_utf8(bytes)
            })
        }
    }
}
#[packed]
struct Header {
    magic: u32,
    nodecount: u32,
    nodeoffset: u64,
    stringcount: u32,
    stringoffset: u64,
    bitmapcount: u32,
    bitmapoffset: u64,
    audiocount: u32,
    audiooffset: u64,
}
#[packed]
struct String {
    length: u16,
}
pub struct Node<'a> {
    data: &'a NodeData,
    file: &'a File,
}
impl <'a> Node<'a> {
    pub fn iter(&self) -> NodeIterator<'a> {
        unsafe {
            let data = self.file.nodetable.offset(self.data.children as int);
            NodeIterator{data: data, count: self.data.count, file: self.file,}
        }
    }
    pub fn name(&self) -> Option<&'a str> { self.file.get_str(self.data.name) }
    pub fn empty(&self) -> bool { self.data.count == 0 }
}
struct NodeIterator<'a> {
    data: *NodeData,
    count: u16,
    file: &'a File,
}
impl <'a> Iterator<Node<'a>> for NodeIterator<'a> {
    fn next(&mut self) -> Option<Node<'a>> {
        match self.count {
            0 => None,
            _ => {
                self.count -= 1;
                let node = Node{data: unsafe { &*self.data }, file: self.file,};
                self.data = unsafe { self.data.offset(1) };
                Some(node)
            }
        }
    }
}
#[packed]
struct NodeData {
    name: u32,
    children: u32,
    count: u16,
    dtype: u16,
    data: u64,
}
#[packed]
struct NodeInteger {
    value: i64,
}
#[packed]
struct NodeFloat {
    value: f64,
}
#[packed]
struct NodeString {
    index: u32,
    unused: u32,
}
#[packed]
struct NodeVector {
    x: i32,
    y: i32,
}
#[packed]
struct NodeBitmap {
    index: u32,
    width: u16,
    height: u16,
}
#[packed]
struct NodeAudio {
    index: u32,
    length: u32,
}
<commit_msg>nx::mmap[unix]: Fix warnings emitted by rustc compiler<commit_after>

#[cfg(windows)]
mod mmap {
    use libc::{CreateFileW, CreateFileMappingW, MapViewOfFile, CloseHandle, UnmapViewOfFile,
               GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, INVALID_HANDLE_VALUE, PAGE_READONLY,
               FILE_MAP_READ, HANDLE, TRUE};
    use libc::consts::os::extra::{FILE_FLAG_RANDOM_ACCESS};
    use libc::types::os::arch::extra::{LPCVOID};
    use std::ptr;
    struct Handle {
        hand: HANDLE,
    }
    impl Drop for Handle {
        fn drop(&mut self) {
            assert_eq!(unsafe { CloseHandle(self.hand) }, TRUE);
        }
    }
    struct MapView {
        data: LPCVOID,
    }
    impl Drop for MapView {
        fn drop(&mut self) {
            assert_eq!(unsafe { UnmapViewOfFile(self.data) }, TRUE);
        }
    }
    pub struct MapFile {
        view: MapView,
        map: Handle,
        file: Handle,
    }
    impl MapFile {
        pub fn data(&self) -> LPCVOID { self.view.data }
    }
    fn create_file(path: &Path) -> Result<Handle, &'static str> {
        let name = path.as_str().unwrap().to_utf16().append([0]);
        let file = unsafe {
            CreateFileW(name.as_ptr(), GENERIC_READ, FILE_SHARE_READ, ptr::mut_null(),
                        OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, ptr::mut_null())
        };
        if file.to_uint() == INVALID_HANDLE_VALUE as uint { return Err("Failed to open file"); }
        Ok(Handle{hand: file})
    }
    fn create_mapping(file: &Handle) -> Result<Handle, &'static str> {
        let map = unsafe {
            CreateFileMappingW(file.hand, ptr::mut_null(), PAGE_READONLY, 0, 0, ptr::null())
        };
        if map.is_null() { return Err("Failed to create file mapping"); }
        Ok(Handle{hand: map})
    }
    fn map_view(map: &Handle) -> Result<MapView, &'static str> {
        let view = unsafe { MapViewOfFile(map.hand, FILE_MAP_READ, 0, 0, 0) };
        if view.is_null() { return Err("Failed to map view of file"); }
        Ok(MapView{data: view as *_})
    }
    pub fn open(path: &Path) -> Result<MapFile, &'static str> {
        let file = try!(create_file(path));
        let map = try!(create_mapping(&file));
        let view = try!(map_view(&map));
        Ok(MapFile{file: file, map: map, view: view})
    }
}
#[cfg(unix)]
mod mmap {
    use libc::{close, mmap, munmap, O_RDONLY, PROT_READ, c_int, c_void};
    use libc::consts::os::posix88::{MAP_SHARED};
    use posix_open = libc::open;
    use std::ptr;
    use std::io::fs::stat;
    struct Handle {
        hand: c_int,
    }
    impl Drop for Handle {
        fn drop(&mut self) {
            assert_eq!(unsafe { close(self.hand) }, 0);
        }
    }
    struct Mapping {
        data: *mut c_void,
        size: u64,
    }
    impl Drop for Mapping {
        fn drop(&mut self) {
            assert_eq!(unsafe { munmap(self.data as *c_void, self.size) }, 0);
        }
    }
    pub struct MapFile {
        map: Mapping,
        file: Handle,
    }
    impl MapFile {
        pub fn data(&self) -> * c_void { self.map.data as *_ }
    }
    fn open_file(path: &Path) -> Result<Handle, &'static str> {
        let name = path.to_c_str();
        let handle = unsafe {
             posix_open(name.unwrap(), O_RDONLY, 0)
        };
        if handle == -1 { return Err("Failed to open file") }
        Ok(Handle{hand: handle})
    }
    fn file_size(path: &Path) -> Result<u64, &'static str> {
        match path.stat() {
            Ok(stat) => Ok(stat.size),
            Err(_) => Err("Failed to get file size")
        }
    }
    fn map_file(file: &Handle, size: u64) -> Result<Mapping, &'static str> {
        let map = unsafe {
            mmap(ptr::null(), size as u64, PROT_READ, MAP_SHARED, file.hand, 0)
        };
        if map.to_uint() == -1 { return Err("Failed to map file"); }
        Ok(Mapping{data: map, size: size})
    }
    pub fn open(path: &Path) -> Result<MapFile, &'static str> {
        let file = try!(open_file(path));
        let size = try!(file_size(path));
        let map = try!(map_file(&file, size));
        Ok(MapFile{file: file, map: map})
    }
}
pub struct File {
    map: mmap::MapFile,
    data: *u8,
    header: *Header,
    nodetable: *NodeData,
    stringtable: *u64,
}
impl File {
    pub fn open(path: &Path) -> Result<File, &'static str> {
        use std::mem::transmute;
        let map = try!(mmap::open(path));
        let data = map.data();
        let header: *Header = unsafe{ transmute(data) };
        if unsafe { (*header).magic } != 0x34474B50 {
            return Err("Not a valid NX PKG4 file");
        }
        unsafe {
            Ok(File{map: map, data: transmute(data), header: header,
                    nodetable: transmute(data.offset((*header).nodeoffset as int)),
                    stringtable: transmute(data.offset((*header).stringoffset as int))})
        }
    }
    fn header(&self) -> &Header {
        use std::mem::transmute;
        unsafe { transmute(self.header) }
    }
    pub fn root<'a>(&'a self) -> Node<'a> {
        unsafe { Node{data: &*self.nodetable, file: self,} }
    }
    fn get_str<'a>(&'a self, index: u32) -> Option<&'a str> {
        use std::str;
        use std::slice::raw;
        use std::mem::transmute;
        unsafe {
            let off = *self.stringtable.offset(index as int);
            let ptr = self.data.offset(off as int);
            let size: *u16 = transmute(ptr);
            raw::buf_as_slice(ptr.offset(2), (*size) as uint, |buf| {
                let bytes: &'a [u8] = transmute(buf);
                str::from_utf8(bytes)
            })
        }
    }
}
#[packed]
struct Header {
    magic: u32,
    nodecount: u32,
    nodeoffset: u64,
    stringcount: u32,
    stringoffset: u64,
    bitmapcount: u32,
    bitmapoffset: u64,
    audiocount: u32,
    audiooffset: u64,
}
#[packed]
struct String {
    length: u16,
}
pub struct Node<'a> {
    data: &'a NodeData,
    file: &'a File,
}
impl <'a> Node<'a> {
    pub fn iter(&self) -> NodeIterator<'a> {
        unsafe {
            let data = self.file.nodetable.offset(self.data.children as int);
            NodeIterator{data: data, count: self.data.count, file: self.file,}
        }
    }
    pub fn name(&self) -> Option<&'a str> { self.file.get_str(self.data.name) }
    pub fn empty(&self) -> bool { self.data.count == 0 }
}
struct NodeIterator<'a> {
    data: *NodeData,
    count: u16,
    file: &'a File,
}
impl <'a> Iterator<Node<'a>> for NodeIterator<'a> {
    fn next(&mut self) -> Option<Node<'a>> {
        match self.count {
            0 => None,
            _ => {
                self.count -= 1;
                let node = Node{data: unsafe { &*self.data }, file: self.file,};
                self.data = unsafe { self.data.offset(1) };
                Some(node)
            }
        }
    }
}
#[packed]
struct NodeData {
    name: u32,
    children: u32,
    count: u16,
    dtype: u16,
    data: u64,
}
#[packed]
struct NodeInteger {
    value: i64,
}
#[packed]
struct NodeFloat {
    value: f64,
}
#[packed]
struct NodeString {
    index: u32,
    unused: u32,
}
#[packed]
struct NodeVector {
    x: i32,
    y: i32,
}
#[packed]
struct NodeBitmap {
    index: u32,
    width: u16,
    height: u16,
}
#[packed]
struct NodeAudio {
    index: u32,
    length: u32,
}
<|endoftext|>


<commit_before>//! The most basic Amethyst example.

// transitions! {
//     Intro => MainMenu;
//     MainMenu => OptionsMenu, Game;
//     Game => Paused;
//     Paused => OptionsMenu, Game, MainMenu;
// }

macro_rules! transitions {
    { $( $start:ident => $($target:ident),+ );+ ; } => {
        $(
            enum $start {
                $($target),+
            }
        )+
    }
}

trait State {
    fn new() -> Self where Self: Sized;
    fn on_start(&mut self) {}
    fn on_stop(&mut self) {}
    fn on_leave(&mut self) {}
    fn on_return(&mut self) {}
    fn handle_events(&mut self, _events: &Vec<i32>) {}
    fn fixed_update(&mut self, _delta: f32) -> Action { Action::Nothing }
    fn update(&mut self, _delta: f32) -> Action { Action::Pop }
}

enum Action {
    Nothing,
    Pop,
    Push(Box<State>),
}

struct PushdownAutomaton {
    running: bool,
    states: Vec<Box<State>>,
}

impl PushdownAutomaton {
    pub fn new<T: 'static>(initial_state: T) -> PushdownAutomaton
        where T: State
    {
        PushdownAutomaton {
            running: false,
            states: vec![Box::new(initial_state)],
        }
    }

    pub fn start(&mut self) {
        if self.is_running() {
            panic!("Error: Automaton started more than once.");
        }

        self.states.last_mut().unwrap().on_start();
        self.running = true;
    }

    pub fn is_running(&self) -> bool {
        self.running
    }

    pub fn update(&mut self, delta: f32) {
        let action = self.states.last_mut().unwrap().update(delta);
        self.check_action(action);
    }

    fn push(&mut self, state: Box<State>) {
        if let Some(current) = self.states.last_mut() {
            current.on_leave();
        }

        self.states.push(state);
        self.states.last_mut().unwrap().on_start();
    }

    pub fn pop(&mut self) {
        self.states.pop().unwrap().on_stop();

        if let Some(next) = self.states.last_mut() {
            next.on_return();
        } else {
            self.running = false;
        }
    }

    fn check_action(&mut self, action: Action) {
        match action {
            Action::Nothing => (),
            Action::Pop => self.pop(),
            Action::Push(state) => self.push(state),
        }
    }
}

struct Intro;
impl State for Intro {
    fn new() -> Intro {
        Intro
    }

    fn update(&mut self, _delta: f32) -> Action {
        Action::Pop
    }
}

fn main() {
    let mut game = PushdownAutomaton::new(Intro::new());
    game.start();

    while game.is_running() {
        game.update(0.0);
    }
}
<commit_msg>actually remove state_experiments.rs<commit_after><|endoftext|>


<commit_before>extern crate nannou;
extern crate shade_runner;

use nannou::prelude::*;
use std::cell::RefCell;
use std::ffi::CStr;
use std::path::PathBuf;
use std::sync::Arc;

struct Model {
    render_pass: Arc<vk::RenderPassAbstract + Send + Sync>,
    pipeline: Option<Arc<vk::GraphicsPipelineAbstract + Send + Sync>>,
    vertex_buffer: Arc<vk::CpuAccessibleBuffer<[Vertex]>>,
    view_fbo: RefCell<ViewFbo>,
    shade_watcher: shade_runner::Watch,
    shade_msg: shade_runner::Message,
    vert_shader: Arc<vk::pipeline::shader::ShaderModule>,
    frag_shader: Arc<vk::pipeline::shader::ShaderModule>,
    device: Arc<vk::Device>,
}

#[derive(Debug, Clone)]
struct Vertex {
    position: [f32; 2],
}

vk::impl_vertex!(Vertex, position);

fn main() {
    nannou::app(model).view(view).update(update).run();
}

fn model(app: &App) -> Model {
    app.new_window()
        .with_dimensions(512, 512)
        .view(view)
        .build()
        .unwrap();

    // The gpu device associated with the window's swapchain
    let device = app.main_window().swapchain().device().clone();

    // We now create a buffer that will store the shape of our triangle.
    let vertex_buffer = {
        let positions = [[-0.5, -0.25], [0.0, 0.5], [0.25, -0.1]];
        let vertices = positions.iter().map(|&position| Vertex { position });
        vk::CpuAccessibleBuffer::from_iter(device.clone(), vk::BufferUsage::all(), vertices)
            .unwrap()
    };
    let nannou_root = std::env::current_dir().expect("failed to get root directory");
    let mut vert_path = nannou_root.clone();
    vert_path.push(PathBuf::from("examples/vulkan/shaders/hotload_vert.glsl"));
    let mut frag_path = nannou_root.clone();
    frag_path.push(PathBuf::from("examples/vulkan/shaders/hotload_frag.glsl"));
    let shade_watcher = shade_runner::Watch::create(vert_path, frag_path).expect("failed to create watcher");
    let shade_msg = shade_watcher
        .rx
        .recv()
        .expect("Failed to receive shader")
        .expect("failed to compile shader");
    let vs = unsafe {
        vk::pipeline::shader::ShaderModule::from_words(device.clone(), &shade_msg.shaders.vertex)
    }
    .unwrap();

    let fs = unsafe {
        vk::pipeline::shader::ShaderModule::from_words(device.clone(), &shade_msg.shaders.fragment)
    }
    .unwrap();

    // The next step is to create a *render pass*, which is an object that describes where the
    // output of the graphics pipeline will go. It describes the layout of the images
    // where the colors, depth and/or stencil information will be written.
    let render_pass = Arc::new(
        vk::single_pass_renderpass!(
            device.clone(),
            attachments: {
                // `color` is a custom name we give to the first and only attachment.
                color: {
                    // `load: Clear` means that we ask the GPU to clear the content of this
                    // attachment at the start of the drawing.
                    load: Clear,
                    // `store: Store` means that we ask the GPU to store the output of the draw
                    // in the actual image. We could also ask it to discard the result.
                    store: Store,
                    // `format: <ty>` indicates the type of the format of the image. This has to
                    // be one of the types of the `vulkano::format` module (or alternatively one
                    // of your structs that implements the `FormatDesc` trait). Here we use the
                    // same format as the swapchain.
                    format: app.main_window().swapchain().format(),
                    // TODO:
                    samples: app.main_window().msaa_samples(),
                }
            },
            pass: {
                // We use the attachment named `color` as the one and only color attachment.
                color: [color],
                // No depth-stencil attachment is indicated with empty brackets.
                depth_stencil: {}
            }
        )
        .unwrap(),
    );

    let pipeline = None;
    // The render pass we created above only describes the layout of our framebuffer. Before we
    // can draw we also need to create the actual framebuffer.
    let view_fbo = RefCell::new(ViewFbo::default());

    let mut model = Model {
        render_pass,
        pipeline,
        vertex_buffer,
        view_fbo,
        shade_watcher,
        shade_msg,
        vert_shader: vs,
        frag_shader: fs,
        device,
    };
    update_pipeline(&mut model);
    model
}

fn update(_app: &App, model: &mut Model, _: Update) {
    let shader_msg = model.shade_watcher.rx.try_recv();
    if let Ok(shade_msg) = shader_msg {
        match shade_msg {
            Ok(shade_msg) => {
                model.vert_shader = unsafe {
                    vk::pipeline::shader::ShaderModule::from_words(
                        model.device.clone(),
                        &shade_msg.shaders.vertex,
                    )
                }
                .unwrap();

                model.frag_shader = unsafe {
                    vk::pipeline::shader::ShaderModule::from_words(
                        model.device.clone(),
                        &shade_msg.shaders.fragment,
                    )
                }
                .unwrap();
                model.shade_msg = shade_msg;
                update_pipeline(model);
            }
            Err(e) => {
                println!("Error compiling shader {:?}", e);
            }
        }
    }
}

// Draw the state of your `Model` into the given `Frame` here.
fn view(_app: &App, model: &Model, frame: Frame) -> Frame {
    // Dynamic viewports allow us to recreate just the viewport when the window is resized
    // Otherwise we would have to recreate the whole pipeline.
    let [w, h] = frame.swapchain_image().dimensions();
    let viewport = vk::ViewportBuilder::new().build([w as _, h as _]);
    let dynamic_state = vk::DynamicState::default().viewports(vec![viewport]);

    // Update the view_fbo.
    model
        .view_fbo
        .borrow_mut()
        .update(&frame, model.render_pass.clone(), |builder, image| {
            builder.add(image)
        })
        .unwrap();

    // Specify the color to clear the framebuffer with i.e. blue.
    let clear_values = vec![[0.0, 0.0, 1.0, 1.0].into()];

    // Submit the draw commands.
    frame
        .add_commands()
        .begin_render_pass(model.view_fbo.borrow().expect_inner(), false, clear_values)
        .unwrap()
        .draw(
            model.pipeline.clone().unwrap(),
            &dynamic_state,
            vec![model.vertex_buffer.clone()],
            (),
            (),
        )
        .unwrap()
        .end_render_pass()
        .expect("failed to add `end_render_pass` command");

    frame
}

fn update_pipeline(model: &mut Model) {
    let Model {
        ref vert_shader,
        ref frag_shader,
        ref shade_msg,
        ref device,
        ref render_pass,
        ref mut pipeline,
        ..
    } = model;
    let entry = shade_msg.entry.clone();
    let vert_main = unsafe {
        vert_shader.graphics_entry_point(
            CStr::from_bytes_with_nul_unchecked(b"main\0"),
            entry.vert_input,
            entry.vert_output,
            entry.vert_layout,
            vk::pipeline::shader::GraphicsShaderType::Vertex,
        )
    };
    let frag_main = unsafe {
        frag_shader.graphics_entry_point(
            CStr::from_bytes_with_nul_unchecked(b"main\0"),
            entry.frag_input,
            entry.frag_output,
            entry.frag_layout,
            vk::pipeline::shader::GraphicsShaderType::Fragment,
        )
    };
    *pipeline = Some(Arc::new(
        vk::GraphicsPipeline::start()
            // We need to indicate the layout of the vertices.
            // The type `SingleBufferDefinition` actually contains a template parameter
            // corresponding to the type of each vertex.
            .vertex_input_single_buffer::<Vertex>()
            // A Vulkan shader can in theory contain multiple entry points, so we have to specify
            // which one. The `main` word of `main_entry_point` actually corresponds to the name of
            // the entry point.
            .vertex_shader(vert_main, ())
            // The content of the vertex buffer describes a list of triangles.
            .triangle_list()
            // Use a resizable viewport set to draw over the entire window
            .viewports_dynamic_scissors_irrelevant(1)
            // See `vertex_shader`.
            .fragment_shader(frag_main, ())
            // We have to indicate which subpass of which render pass this pipeline is going to be
            // used in. The pipeline will only be usable from this particular subpass.
            .render_pass(vk::Subpass::from(render_pass.clone(), 0).unwrap())
            // Now that our builder is filled, we call `build()` to obtain an actual pipeline.
            .build(device.clone())
            .unwrap(),
    ));
}
<commit_msg>small pr suggestions<commit_after>extern crate nannou;
extern crate shade_runner;

use nannou::prelude::*;
use std::cell::RefCell;
use std::ffi::CStr;
use std::sync::Arc;
use std::time::Duration;

struct Model {
    render_pass: Arc<vk::RenderPassAbstract + Send + Sync>,
    pipeline: Option<Arc<vk::GraphicsPipelineAbstract + Send + Sync>>,
    vertex_buffer: Arc<vk::CpuAccessibleBuffer<[Vertex]>>,
    view_fbo: RefCell<ViewFbo>,
    shade_watcher: shade_runner::Watch,
    shade_msg: shade_runner::Message,
    vert_shader: Arc<vk::pipeline::shader::ShaderModule>,
    frag_shader: Arc<vk::pipeline::shader::ShaderModule>,
    device: Arc<vk::Device>,
}

#[derive(Debug, Clone)]
struct Vertex {
    position: [f32; 2],
}

vk::impl_vertex!(Vertex, position);

fn main() {
    nannou::app(model).view(view).update(update).run();
}

fn model(app: &App) -> Model {
    app.new_window()
        .with_dimensions(512, 512)
        .view(view)
        .build()
        .unwrap();

    // The gpu device associated with the window's swapchain
    let device = app.main_window().swapchain().device().clone();

    // We now create a buffer that will store the shape of our triangle.
    let vertex_buffer = {
        let positions = [[-0.5, -0.25], [0.0, 0.5], [0.25, -0.1]];
        let vertices = positions.iter().map(|&position| Vertex { position });
        vk::CpuAccessibleBuffer::from_iter(device.clone(), vk::BufferUsage::all(), vertices)
            .unwrap()
    };
    let vert_path = concat!(env!("CARGO_MANIFEST_DIR"), "/examples/vulkan/shaders/hotload_vert.glsl");
    let frag_path = concat!(env!("CARGO_MANIFEST_DIR"), "/examples/vulkan/shaders/hotload_frag.glsl");
    let shade_watcher = shade_runner::Watch::create(vert_path, frag_path, Duration::from_millis(50)).expect("failed to create watcher");
    let shade_msg = shade_watcher
        .rx
        .recv()
        .expect("Failed to receive shader")
        .expect("failed to compile shader");
    let vs = unsafe {
        vk::pipeline::shader::ShaderModule::from_words(device.clone(), &shade_msg.shaders.vertex)
    }
    .unwrap();

    let fs = unsafe {
        vk::pipeline::shader::ShaderModule::from_words(device.clone(), &shade_msg.shaders.fragment)
    }
    .unwrap();

    // The next step is to create a *render pass*, which is an object that describes where the
    // output of the graphics pipeline will go. It describes the layout of the images
    // where the colors, depth and/or stencil information will be written.
    let render_pass = Arc::new(
        vk::single_pass_renderpass!(
            device.clone(),
            attachments: {
                // `color` is a custom name we give to the first and only attachment.
                color: {
                    // `load: Clear` means that we ask the GPU to clear the content of this
                    // attachment at the start of the drawing.
                    load: Clear,
                    // `store: Store` means that we ask the GPU to store the output of the draw
                    // in the actual image. We could also ask it to discard the result.
                    store: Store,
                    // `format: <ty>` indicates the type of the format of the image. This has to
                    // be one of the types of the `vulkano::format` module (or alternatively one
                    // of your structs that implements the `FormatDesc` trait). Here we use the
                    // same format as the swapchain.
                    format: app.main_window().swapchain().format(),
                    // TODO:
                    samples: app.main_window().msaa_samples(),
                }
            },
            pass: {
                // We use the attachment named `color` as the one and only color attachment.
                color: [color],
                // No depth-stencil attachment is indicated with empty brackets.
                depth_stencil: {}
            }
        )
        .unwrap(),
    );

    let pipeline = None;
    // The render pass we created above only describes the layout of our framebuffer. Before we
    // can draw we also need to create the actual framebuffer.
    let view_fbo = RefCell::new(ViewFbo::default());

    let mut model = Model {
        render_pass,
        pipeline,
        vertex_buffer,
        view_fbo,
        shade_watcher,
        shade_msg,
        vert_shader: vs,
        frag_shader: fs,
        device,
    };
    update_pipeline(&mut model);
    model
}

fn update(_app: &App, model: &mut Model, _: Update) {
    let shader_msg = model.shade_watcher.rx.try_iter().last();
    if let Some(shade_msg) = shader_msg {
        match shade_msg {
            Ok(shade_msg) => {
                model.vert_shader = unsafe {
                    vk::pipeline::shader::ShaderModule::from_words(
                        model.device.clone(),
                        &shade_msg.shaders.vertex,
                    )
                }
                .unwrap();

                model.frag_shader = unsafe {
                    vk::pipeline::shader::ShaderModule::from_words(
                        model.device.clone(),
                        &shade_msg.shaders.fragment,
                    )
                }
                .unwrap();
                model.shade_msg = shade_msg;
                update_pipeline(model);
            }
            Err(e) => {
                println!("Error compiling shader {:?}", e);
            }
        }
    }
}

// Draw the state of your `Model` into the given `Frame` here.
fn view(_app: &App, model: &Model, frame: Frame) -> Frame {
    // Dynamic viewports allow us to recreate just the viewport when the window is resized
    // Otherwise we would have to recreate the whole pipeline.
    let [w, h] = frame.swapchain_image().dimensions();
    let viewport = vk::ViewportBuilder::new().build([w as _, h as _]);
    let dynamic_state = vk::DynamicState::default().viewports(vec![viewport]);

    // Update the view_fbo.
    model
        .view_fbo
        .borrow_mut()
        .update(&frame, model.render_pass.clone(), |builder, image| {
            builder.add(image)
        })
        .unwrap();

    // Specify the color to clear the framebuffer with i.e. blue.
    let clear_values = vec![[0.0, 0.0, 1.0, 1.0].into()];

    // Submit the draw commands.
    frame
        .add_commands()
        .begin_render_pass(model.view_fbo.borrow().expect_inner(), false, clear_values)
        .unwrap()
        .draw(
            model.pipeline.clone().unwrap(),
            &dynamic_state,
            vec![model.vertex_buffer.clone()],
            (),
            (),
        )
        .unwrap()
        .end_render_pass()
        .expect("failed to add `end_render_pass` command");

    frame
}

fn update_pipeline(model: &mut Model) {
    let Model {
        ref vert_shader,
        ref frag_shader,
        ref shade_msg,
        ref device,
        ref render_pass,
        ref mut pipeline,
        ..
    } = model;
    let entry = shade_msg.entry.clone();
    let vert_main = unsafe {
        vert_shader.graphics_entry_point(
            CStr::from_bytes_with_nul_unchecked(b"main\0"),
            entry.vert_input,
            entry.vert_output,
            entry.vert_layout,
            vk::pipeline::shader::GraphicsShaderType::Vertex,
        )
    };
    let frag_main = unsafe {
        frag_shader.graphics_entry_point(
            CStr::from_bytes_with_nul_unchecked(b"main\0"),
            entry.frag_input,
            entry.frag_output,
            entry.frag_layout,
            vk::pipeline::shader::GraphicsShaderType::Fragment,
        )
    };
    *pipeline = Some(Arc::new(
        vk::GraphicsPipeline::start()
            // We need to indicate the layout of the vertices.
            // The type `SingleBufferDefinition` actually contains a template parameter
            // corresponding to the type of each vertex.
            .vertex_input_single_buffer::<Vertex>()
            // A Vulkan shader can in theory contain multiple entry points, so we have to specify
            // which one. The `main` word of `main_entry_point` actually corresponds to the name of
            // the entry point.
            .vertex_shader(vert_main, ())
            // The content of the vertex buffer describes a list of triangles.
            .triangle_list()
            // Use a resizable viewport set to draw over the entire window
            .viewports_dynamic_scissors_irrelevant(1)
            // See `vertex_shader`.
            .fragment_shader(frag_main, ())
            // We have to indicate which subpass of which render pass this pipeline is going to be
            // used in. The pipeline will only be usable from this particular subpass.
            .render_pass(vk::Subpass::from(render_pass.clone(), 0).unwrap())
            // Now that our builder is filled, we call `build()` to obtain an actual pipeline.
            .build(device.clone())
            .unwrap(),
    ));
}
<|endoftext|>


<commit_before>#![allow(clippy::exhaustive_structs)]

use ruma_common::{
    api::{
        ruma_api, IncomingRequest as _, MatrixVersion, OutgoingRequest as _,
        OutgoingRequestAppserviceExt, SendAccessToken,
    },
    user_id, OwnedUserId,
};

ruma_api! {
    metadata: {
        description: "Does something.",
        method: POST,
        name: "my_endpoint",
        unstable_path: "/_matrix/foo/:bar/:user",
        rate_limited: false,
        authentication: None,
    }

    request: {
        pub hello: String,
        #[ruma_api(header = CONTENT_TYPE)]
        pub world: String,
        #[ruma_api(query)]
        pub q1: String,
        #[ruma_api(query)]
        pub q2: u32,
        #[ruma_api(path)]
        pub bar: String,
        #[ruma_api(path)]
        pub user: OwnedUserId,
    }

    response: {
        pub hello: String,
        #[ruma_api(header = CONTENT_TYPE)]
        pub world: String,
        #[serde(skip_serializing_if = "Option::is_none")]
        pub optional_flag: Option<bool>,
    }
}

#[test]
fn request_serde() {
    let req = Request {
        hello: "hi".to_owned(),
        world: "test".to_owned(),
        q1: "query_param_special_chars %/&@!".to_owned(),
        q2: 55,
        bar: "barVal".to_owned(),
        user: user_id!("@bazme:ruma.io").to_owned(),
    };

    let http_req = req
        .clone()
        .try_into_http_request::<Vec<u8>>(
            "https://homeserver.tld",
            SendAccessToken::None,
            &[MatrixVersion::V1_1],
        )
        .unwrap();
    let req2 = Request::try_from_http_request(http_req, &["barVal", "@bazme:ruma.io"]).unwrap();

    assert_eq!(req.hello, req2.hello);
    assert_eq!(req.world, req2.world);
    assert_eq!(req.q1, req2.q1);
    assert_eq!(req.q2, req2.q2);
    assert_eq!(req.bar, req2.bar);
    assert_eq!(req.user, req2.user);
}

#[test]
fn invalid_uri_should_not_panic() {
    let req = Request {
        hello: "hi".to_owned(),
        world: "test".to_owned(),
        q1: "query_param_special_chars %/&@!".to_owned(),
        q2: 55,
        bar: "barVal".to_owned(),
        user: user_id!("@bazme:ruma.io").to_owned(),
    };

    let result = req.try_into_http_request::<Vec<u8>>(
        "invalid uri",
        SendAccessToken::None,
        &[MatrixVersion::V1_1],
    );
    assert!(result.is_err());
}

#[test]
fn request_with_user_id_serde() {
    let req = Request {
        hello: "hi".to_owned(),
        world: "test".to_owned(),
        q1: "query_param_special_chars %/&@!".to_owned(),
        q2: 55,
        bar: "barVal".to_owned(),
        user: user_id!("@bazme:ruma.io").to_owned(),
    };

    let user_id = user_id!("@_virtual_:ruma.io");
    let http_req = req
        .try_into_http_request_with_user_id::<Vec<u8>>(
            "https://homeserver.tld",
            SendAccessToken::None,
            user_id,
            &[MatrixVersion::V1_1],
        )
        .unwrap();

    let query = http_req.uri().query().unwrap();

    assert_eq!(
        query,
        "q1=query_param_special_chars+%25%2F%26%40%21&q2=55&user_id=%40_virtual_%3Aruma.io"
    );
}

mod without_query {
    use ruma_common::{api::MatrixVersion, OwnedUserId};

    use super::{ruma_api, user_id, OutgoingRequestAppserviceExt, SendAccessToken};

    ruma_api! {
        metadata: {
            description: "Does something without query.",
            method: POST,
            name: "my_endpoint",
            unstable_path: "/_matrix/foo/:bar/:user",
            rate_limited: false,
            authentication: None,
        }

        request: {
            pub hello: String,
            #[ruma_api(header = CONTENT_TYPE)]
            pub world: String,
            #[ruma_api(path)]
            pub bar: String,
            #[ruma_api(path)]
            pub user: OwnedUserId,
        }

        response: {
            pub hello: String,
            #[ruma_api(header = CONTENT_TYPE)]
            pub world: String,
            #[serde(skip_serializing_if = "Option::is_none")]
            pub optional_flag: Option<bool>,
        }
    }

    #[test]
    fn request_without_query_with_user_id_serde() {
        let req = Request {
            hello: "hi".to_owned(),
            world: "test".to_owned(),
            bar: "barVal".to_owned(),
            user: user_id!("@bazme:ruma.io").to_owned(),
        };

        let user_id = user_id!("@_virtual_:ruma.io");
        let http_req = req
            .try_into_http_request_with_user_id::<Vec<u8>>(
                "https://homeserver.tld",
                SendAccessToken::None,
                user_id,
                &[MatrixVersion::V1_1],
            )
            .unwrap();

        let query = http_req.uri().query().unwrap();

        assert_eq!(query, "user_id=%40_virtual_%3Aruma.io");
    }
}
<commit_msg>api: Make some test assertions more helpful<commit_after>#![allow(clippy::exhaustive_structs)]

use ruma_common::{
    api::{
        ruma_api, IncomingRequest as _, MatrixVersion, OutgoingRequest as _,
        OutgoingRequestAppserviceExt, SendAccessToken,
    },
    user_id, OwnedUserId,
};

ruma_api! {
    metadata: {
        description: "Does something.",
        method: POST,
        name: "my_endpoint",
        unstable_path: "/_matrix/foo/:bar/:user",
        rate_limited: false,
        authentication: None,
    }

    request: {
        pub hello: String,
        #[ruma_api(header = CONTENT_TYPE)]
        pub world: String,
        #[ruma_api(query)]
        pub q1: String,
        #[ruma_api(query)]
        pub q2: u32,
        #[ruma_api(path)]
        pub bar: String,
        #[ruma_api(path)]
        pub user: OwnedUserId,
    }

    response: {
        pub hello: String,
        #[ruma_api(header = CONTENT_TYPE)]
        pub world: String,
        #[serde(skip_serializing_if = "Option::is_none")]
        pub optional_flag: Option<bool>,
    }
}

#[test]
fn request_serde() {
    let req = Request {
        hello: "hi".to_owned(),
        world: "test".to_owned(),
        q1: "query_param_special_chars %/&@!".to_owned(),
        q2: 55,
        bar: "barVal".to_owned(),
        user: user_id!("@bazme:ruma.io").to_owned(),
    };

    let http_req = req
        .clone()
        .try_into_http_request::<Vec<u8>>(
            "https://homeserver.tld",
            SendAccessToken::None,
            &[MatrixVersion::V1_1],
        )
        .unwrap();
    let req2 = Request::try_from_http_request(http_req, &["barVal", "@bazme:ruma.io"]).unwrap();

    assert_eq!(req.hello, req2.hello);
    assert_eq!(req.world, req2.world);
    assert_eq!(req.q1, req2.q1);
    assert_eq!(req.q2, req2.q2);
    assert_eq!(req.bar, req2.bar);
    assert_eq!(req.user, req2.user);
}

#[test]
fn invalid_uri_should_not_panic() {
    let req = Request {
        hello: "hi".to_owned(),
        world: "test".to_owned(),
        q1: "query_param_special_chars %/&@!".to_owned(),
        q2: 55,
        bar: "barVal".to_owned(),
        user: user_id!("@bazme:ruma.io").to_owned(),
    };

    let result = req.try_into_http_request::<Vec<u8>>(
        "invalid uri",
        SendAccessToken::None,
        &[MatrixVersion::V1_1],
    );
    result.unwrap_err();
}

#[test]
fn request_with_user_id_serde() {
    let req = Request {
        hello: "hi".to_owned(),
        world: "test".to_owned(),
        q1: "query_param_special_chars %/&@!".to_owned(),
        q2: 55,
        bar: "barVal".to_owned(),
        user: user_id!("@bazme:ruma.io").to_owned(),
    };

    let user_id = user_id!("@_virtual_:ruma.io");
    let http_req = req
        .try_into_http_request_with_user_id::<Vec<u8>>(
            "https://homeserver.tld",
            SendAccessToken::None,
            user_id,
            &[MatrixVersion::V1_1],
        )
        .unwrap();

    let query = http_req.uri().query().unwrap();

    assert_eq!(
        query,
        "q1=query_param_special_chars+%25%2F%26%40%21&q2=55&user_id=%40_virtual_%3Aruma.io"
    );
}

mod without_query {
    use ruma_common::{api::MatrixVersion, OwnedUserId};

    use super::{ruma_api, user_id, OutgoingRequestAppserviceExt, SendAccessToken};

    ruma_api! {
        metadata: {
            description: "Does something without query.",
            method: POST,
            name: "my_endpoint",
            unstable_path: "/_matrix/foo/:bar/:user",
            rate_limited: false,
            authentication: None,
        }

        request: {
            pub hello: String,
            #[ruma_api(header = CONTENT_TYPE)]
            pub world: String,
            #[ruma_api(path)]
            pub bar: String,
            #[ruma_api(path)]
            pub user: OwnedUserId,
        }

        response: {
            pub hello: String,
            #[ruma_api(header = CONTENT_TYPE)]
            pub world: String,
            #[serde(skip_serializing_if = "Option::is_none")]
            pub optional_flag: Option<bool>,
        }
    }

    #[test]
    fn request_without_query_with_user_id_serde() {
        let req = Request {
            hello: "hi".to_owned(),
            world: "test".to_owned(),
            bar: "barVal".to_owned(),
            user: user_id!("@bazme:ruma.io").to_owned(),
        };

        let user_id = user_id!("@_virtual_:ruma.io");
        let http_req = req
            .try_into_http_request_with_user_id::<Vec<u8>>(
                "https://homeserver.tld",
                SendAccessToken::None,
                user_id,
                &[MatrixVersion::V1_1],
            )
            .unwrap();

        let query = http_req.uri().query().unwrap();

        assert_eq!(query, "user_id=%40_virtual_%3Aruma.io");
    }
}
<|endoftext|>


<commit_before>#[cfg(test)] use std::rand::random;

/// Test helper to standardize how random files and directories are generated.
#[cfg(test)]
pub fn random_name() -> String {
    format!("test_{}", random::<f64>())
}

<commit_msg>We don't need to apply cfg(test) to everything as this module is only loaded under those circumstances.<commit_after>use std::rand::random;

/// Test helper to standardize how random files and directories are generated.
pub fn random_name() -> String {
    format!("test_{}", random::<f64>())
}

<|endoftext|>


<commit_before>// Copyright 2013-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use libc::{c_char, c_int};
use std::boxed::Box as Box_;
use std::mem::transmute;
use std::{slice, str};
use ffi;
use glib;
use glib::object::IsA;
use glib::translate::*;
use glib::signal::{SignalHandlerId, connect};
use glib_ffi;
use TextBuffer;
use TextIter;

pub trait TextBufferExtManual {
    fn connect_insert_text<F: Fn(&TextBuffer, &TextIter, &str) + 'static>(&self, f: F) -> SignalHandlerId;
}

impl<O: IsA<TextBuffer> + IsA<glib::object::Object>> TextBufferExtManual for O {
    fn connect_insert_text<F: Fn(&TextBuffer, &TextIter, &str) + 'static>(&self, f: F) -> SignalHandlerId {
        unsafe {
            let f: Box_<Box_<Fn(&TextBuffer, &TextIter, &str) + 'static>> = Box_::new(Box_::new(f));
            connect(self.to_glib_none().0, "insert-text",
                transmute(insert_text_trampoline as usize), Box_::into_raw(f) as *mut _)
        }
    }
}

unsafe extern "C" fn insert_text_trampoline(this: *mut ffi::GtkTextBuffer,
                                            location: *mut ffi::GtkTextIter,
                                            text: *mut c_char,
                                            len: c_int,
                                            f: glib_ffi::gpointer) {
    callback_guard!();
    let f: &&(Fn(&TextBuffer, &TextIter, &str) + 'static) = transmute(f);
    f(&from_glib_borrow(this),
      &from_glib_borrow(location),
      str::from_utf8(slice::from_raw_parts(text as *const u8, len as usize)).unwrap())
}
<commit_msg>Make location in TextBuffer insert-text callback mutable.<commit_after>// Copyright 2013-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use libc::{c_char, c_int};
use std::boxed::Box as Box_;
use std::mem::transmute;
use std::{slice, str};
use ffi;
use glib;
use glib::object::IsA;
use glib::translate::*;
use glib::signal::{SignalHandlerId, connect};
use glib_ffi;
use TextBuffer;
use TextIter;

pub trait TextBufferExtManual {
    fn connect_insert_text<F: Fn(&TextBuffer, &mut TextIter, &str) + 'static>(&self, f: F) -> SignalHandlerId;
}

impl<O: IsA<TextBuffer> + IsA<glib::object::Object>> TextBufferExtManual for O {
    fn connect_insert_text<F: Fn(&TextBuffer, &mut TextIter, &str) + 'static>(&self, f: F) -> SignalHandlerId {
        unsafe {
            let f: Box_<Box_<Fn(&TextBuffer, &mut TextIter, &str) + 'static>> = Box_::new(Box_::new(f));
            connect(self.to_glib_none().0, "insert-text",
                transmute(insert_text_trampoline as usize), Box_::into_raw(f) as *mut _)
        }
    }
}

unsafe extern "C" fn insert_text_trampoline(this: *mut ffi::GtkTextBuffer,
                                            location: *mut ffi::GtkTextIter,
                                            text: *mut c_char,
                                            len: c_int,
                                            f: glib_ffi::gpointer) {
    callback_guard!();
    let f: &&(Fn(&TextBuffer, &TextIter, &str) + 'static) = transmute(f);
    f(&from_glib_borrow(this),
      &mut from_glib_borrow(location),
      str::from_utf8(slice::from_raw_parts(text as *const u8, len as usize)).unwrap())
}
<|endoftext|>


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

use std::io::{self, Write};
use std::fmt::Arguments;

use time;
use log::{self, Log, LogMetadata, LogRecord, SetLoggerError};

pub use log::LogLevelFilter;

const ENABLED_TARGETS: &[&str] = &["tikv::", "tests::", "benches::"];

pub fn init_log<W: LogWriter + Sync + Send + 'static>(
    writer: W,
    level: LogLevelFilter,
) -> Result<(), SetLoggerError> {
    log::set_logger(|filter| {
        filter.set(level);
        Box::new(Logger {
            level: level,
            writer: writer,
            tikv_only: false,
        })
    })
}

pub fn init_log_for_tikv_only<W: LogWriter + Sync + Send + 'static>(
    writer: W,
    level: LogLevelFilter,
) -> Result<(), SetLoggerError> {
    log::set_logger(|filter| {
        filter.set(level);
        Box::new(Logger {
            level: level,
            writer: writer,
            tikv_only: true,
        })
    })
}

pub trait LogWriter {
    fn write(&self, args: Arguments);
}

struct Logger<W: LogWriter> {
    level: LogLevelFilter,
    writer: W,
    tikv_only: bool,
}

impl<W: LogWriter + Sync + Send> Log for Logger<W> {
    fn enabled(&self, meta: &LogMetadata) -> bool {
        meta.level() <= self.level
    }

    fn log(&self, record: &LogRecord) {
        if self.tikv_only
            && ENABLED_TARGETS
                .iter()
                .all(|target| !record.target().starts_with(target))
        {
            return;
        }
        if self.enabled(record.metadata()) {
            let t = time::now();
            let time_str = time::strftime("%Y/%m/%d %H:%M:%S.%f", &t).unwrap();
            // TODO allow formatter to be configurable.
            self.writer.write(format_args!(
                "{} {}:{}: [{}] {}\n",
                &time_str[..time_str.len() - 6],
                record.location().file().rsplit('/').nth(0).unwrap(),
                record.location().line(),
                record.level(),
                record.args()
            ));
        }
    }
}

pub struct StderrLogger;

impl LogWriter for StderrLogger {
    #[inline]
    fn write(&self, args: Arguments) {
        let _ = io::stderr().write_fmt(args);
    }
}

pub fn get_level_by_string(lv: &str) -> LogLevelFilter {
    #![allow(match_same_arms)]
    match &*lv.to_owned().to_lowercase() {
        "trace" => LogLevelFilter::Trace,
        "debug" => LogLevelFilter::Debug,
        "info" => LogLevelFilter::Info,
        "warn" => LogLevelFilter::Warn,
        "error" => LogLevelFilter::Error,
        "off" => LogLevelFilter::Off,
        _ => LogLevelFilter::Info,
    }
}
<commit_msg>util/logger: collect grpc logs (#2756)<commit_after>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

use std::io::{self, Write};
use std::fmt::Arguments;

use grpc;
use time;
use log::{self, Log, LogMetadata, LogRecord, SetLoggerError};

pub use log::LogLevelFilter;

const ENABLED_TARGETS: &[&str] = &["tikv::", "tests::", "benches::"];

pub fn init_log<W: LogWriter + Sync + Send + 'static>(
    writer: W,
    level: LogLevelFilter,
) -> Result<(), SetLoggerError> {
    log::set_logger(|filter| {
        filter.set(level);
        grpc::redirect_log();
        Box::new(Logger {
            level: level,
            writer: writer,
            tikv_only: false,
        })
    })
}

pub fn init_log_for_tikv_only<W: LogWriter + Sync + Send + 'static>(
    writer: W,
    level: LogLevelFilter,
) -> Result<(), SetLoggerError> {
    log::set_logger(|filter| {
        filter.set(level);
        Box::new(Logger {
            level: level,
            writer: writer,
            tikv_only: true,
        })
    })
}

pub trait LogWriter {
    fn write(&self, args: Arguments);
}

struct Logger<W: LogWriter> {
    level: LogLevelFilter,
    writer: W,
    tikv_only: bool,
}

impl<W: LogWriter + Sync + Send> Log for Logger<W> {
    fn enabled(&self, meta: &LogMetadata) -> bool {
        meta.level() <= self.level
    }

    fn log(&self, record: &LogRecord) {
        if self.tikv_only
            && ENABLED_TARGETS
                .iter()
                .all(|target| !record.target().starts_with(target))
        {
            return;
        }
        if self.enabled(record.metadata()) {
            let t = time::now();
            let time_str = time::strftime("%Y/%m/%d %H:%M:%S.%f", &t).unwrap();
            // TODO allow formatter to be configurable.
            self.writer.write(format_args!(
                "{} {}:{}: [{}] {}\n",
                &time_str[..time_str.len() - 6],
                record.location().file().rsplit('/').nth(0).unwrap(),
                record.location().line(),
                record.level(),
                record.args()
            ));
        }
    }
}

pub struct StderrLogger;

impl LogWriter for StderrLogger {
    #[inline]
    fn write(&self, args: Arguments) {
        let _ = io::stderr().write_fmt(args);
    }
}

pub fn get_level_by_string(lv: &str) -> LogLevelFilter {
    #![allow(match_same_arms)]
    match &*lv.to_owned().to_lowercase() {
        "trace" => LogLevelFilter::Trace,
        "debug" => LogLevelFilter::Debug,
        "info" => LogLevelFilter::Info,
        "warn" => LogLevelFilter::Warn,
        "error" => LogLevelFilter::Error,
        "off" => LogLevelFilter::Off,
        _ => LogLevelFilter::Info,
    }
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use std::cell::RefCell;

use std::vec::Vec;
use autograd::variable::*;

type RcMut<T> = Rc<RefCell<T>>;
type OptRcMut<T> = Option<RcMut<T>>;

pub struct Function<T> {
    saved_variables: Vec<SavedVariable<T>>,
    next_functions: Vec<(RcMut<Function<T>>, usize)>,
}
<commit_msg>start work on Function interface<commit_after>use std::rc::Rc;
use std::cell::RefCell;

use std::vec::Vec;
use autograd::variable::*;
use RcMut;

pub struct Function<T> {
    saved_variables: Vec<SavedVariable<T>>,
    next_functions: Vec<(RcMut<Function<T>>, usize)>,
}
impl<T> Function<T> {
    pub fn new() -> Self {
        Function {
            saved_variables: Vec::new(),
            next_functions: Vec::new(),
        }
    }
    pub fn do_forward(&mut self,
                      func: &mut FuncIntf<T>,
                      mut args: &mut Vec<Variable<T>>)
                      -> Vec<Variable<T>> {
        // do start graph stuff
        let v = func.forward(&mut args);
        // do end graph stuff
        v
    }
}

pub trait FuncIntf<T> {
    fn delegate(&mut self) -> &mut Function<T>;
    fn forward(&mut self, input: &mut Vec<Variable<T>>) -> Vec<Variable<T>>;
    // Borrowing rules prevent this, but each FuncIntf implementer needs to implement
    // the following function:
    //    fn f(&mut self, input: &mut Vec<Variable<T>>) -> Vec<Variable<T>> {
    //    	  self.delegate().do_forward(&mut self, input)
    //    }
}
<|endoftext|>


<commit_before>use url::Url;
use util::{CargoResult,ProcessBuilder,io_error,human_error,process};
use std::str;
use std::io::UserDir;
use std::io::fs::mkdir_recursive;
use serialize::{Encodable,Encoder};

macro_rules! git(
    ($config:expr, $str:expr, $($rest:expr),*) => (
        try!(git_inherit($config, format_strbuf!($str, $($rest),*)))
    );
)

macro_rules! git_output(
    ($config:expr, $str:expr, $($rest:expr),*) => (
        try!(git_output($config, format_strbuf!($str, $($rest),*)))
    );
)

#[deriving(Eq,Clone)]
struct GitConfig {
    path: Path,
    uri: Url,
    reference: StrBuf
}

#[deriving(Eq,Clone,Encodable)]
struct EncodableGitConfig {
    path: StrBuf,
    uri: StrBuf,
    reference: StrBuf
}

impl<E, S: Encoder<E>> Encodable<S, E> for GitConfig {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        EncodableGitConfig {
            path: format_strbuf!("{}", self.path.display()),
            uri: format_strbuf!("{}", self.uri),
            reference: self.reference.clone()
        }.encode(s)
    }
}

#[deriving(Eq,Clone)]
pub struct GitCommand {
    config: GitConfig
}

#[deriving(Eq,Clone,Encodable)]
pub struct GitRepo {
    config: GitConfig,
    revision: StrBuf
}

impl GitCommand {
    pub fn new(path: Path, uri: Url, reference: StrBuf) -> GitCommand {
        GitCommand { config: GitConfig { path: path, uri: uri, reference: reference } }
    }

    pub fn checkout(&self) -> CargoResult<GitRepo> {
        let config = &self.config;

        if config.path.exists() {
            git!(config, "fetch --force --quiet --tags {} refs/heads/*:refs/heads/*", config.uri);
        } else {
            let dirname = Path::new(config.path.dirname());
            let mut checkout_config = self.config.clone();
            checkout_config.path = dirname;

            try!(mkdir_recursive(&checkout_config.path, UserDir).map_err(|err|
                human_error(format_strbuf!("Couldn't recursively create `{}`", checkout_config.path.display()), format_strbuf!("path={}", checkout_config.path.display()), io_error(err))));

            git!(&checkout_config, "clone {} {} --bare --no-hardlinks --quiet", config.uri, config.path.display());
        }

        Ok(GitRepo { config: config.clone(), revision: try!(rev_for(config)) })
    }
}

fn rev_for(config: &GitConfig) -> CargoResult<StrBuf> {
    Ok(git_output!(config, "rev-parse {}", config.reference))
}

fn git(config: &GitConfig, str: &str) -> ProcessBuilder {
    println!("Executing git {} @ {}", str, config.path.display());
    process("git").args(str.split(' ').collect::<Vec<&str>>().as_slice()).cwd(config.path.clone())
}

fn git_inherit(config: &GitConfig, str: StrBuf) -> CargoResult<()> {
    git(config, str.as_slice()).exec().map_err(|err|
        human_error(format_strbuf!("Couldn't execute `git {}`: {}", str, err), None::<&str>, err))
}

fn git_output(config: &GitConfig, str: StrBuf) -> CargoResult<StrBuf> {
    let output = try!(git(config, str.as_slice()).exec_with_output().map_err(|err|
        human_error(format_strbuf!("Couldn't execute `git {}`", str), None::<&str>, err)));

    Ok(to_str(output.output.as_slice()))
}

fn to_str(vec: &[u8]) -> StrBuf {
    format_strbuf!("{}", str::from_utf8_lossy(vec))
}
<commit_msg>A few updates to GitSource<commit_after>use url::Url;
use util::{CargoResult,ProcessBuilder,io_error,human_error,process};
use std::str;
use std::io::{UserDir,AllPermissions};
use std::io::fs::{mkdir_recursive,rmdir_recursive,chmod};
use serialize::{Encodable,Encoder};

macro_rules! git(
    ($config:expr, $str:expr, $($rest:expr),*) => (
        try!(git_inherit(&$config, format_strbuf!($str, $($rest),*)))
    );

    ($config:expr, $str:expr) => (
        try!(git_inherit(&$config, format_strbuf!($str)))
    );
)

macro_rules! git_output(
    ($config:expr, $str:expr, $($rest:expr),*) => (
        try!(git_output(&$config, format_strbuf!($str, $($rest),*)))
    );

    ($config:expr, $str:expr) => (
        try!(git_output(&$config, format_strbuf!($str)))
    );
)

#[deriving(Eq,Clone)]
struct GitConfig {
    path: Path,
    uri: Url,
    reference: StrBuf
}

#[deriving(Eq,Clone,Encodable)]
struct EncodableGitConfig {
    path: StrBuf,
    uri: StrBuf,
    reference: StrBuf
}

impl<E, S: Encoder<E>> Encodable<S, E> for GitConfig {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        EncodableGitConfig {
            path: format_strbuf!("{}", self.path.display()),
            uri: format_strbuf!("{}", self.uri),
            reference: self.reference.clone()
        }.encode(s)
    }
}

#[deriving(Eq,Clone)]
pub struct GitCommand {
    config: GitConfig
}

#[deriving(Eq,Clone,Encodable)]
pub struct GitRepo {
    config: GitConfig,
    revision: StrBuf
}

impl GitCommand {
    pub fn new(path: Path, uri: Url, reference: StrBuf) -> GitCommand {
        GitCommand { config: GitConfig { path: path, uri: uri, reference: reference } }
    }

    pub fn checkout(&self) -> CargoResult<GitRepo> {
        let config = &self.config;

        if config.path.exists() {
            git!(*config, "fetch --force --quiet --tags {} refs/heads/*:refs/heads/*", config.uri);
        } else {
            let dirname = Path::new(config.path.dirname());
            let mut checkout_config = self.config.clone();
            checkout_config.path = dirname;

            try!(mkdir_recursive(&checkout_config.path, UserDir).map_err(|err|
                human_error(format_strbuf!("Couldn't recursively create `{}`", checkout_config.path.display()), format_strbuf!("path={}", checkout_config.path.display()), io_error(err))));

            git!(checkout_config, "clone {} {} --bare --no-hardlinks --quiet", config.uri, config.path.display());
        }

        Ok(GitRepo { config: config.clone(), revision: try!(rev_for(config)) })
    }
}

impl GitRepo {
    fn copy_to(destination: &Path) -> CargoResult<()> {
        Ok(())
    }

    fn clone_to(&self, destination: &Path) -> CargoResult<()> {
        try!(mkdir_recursive(&Path::new(destination.dirname()), UserDir).map_err(io_error));
        try!(rmdir_recursive(destination).map_err(io_error));
        git!(self.config, "clone --no-checkout --quiet {} {}", self.config.path.display(), destination.display());
        try!(chmod(destination, AllPermissions).map_err(io_error));

        let mut dest_config = self.config.clone();
        dest_config.path = destination.clone();

        git!(dest_config, "fetch --force --quiet --tags {}", self.config.path.display());
        git!(dest_config, "reset --hard {}", self.revision);
        git!(dest_config, "submodule update --init --recursive");

        Ok(())
    }
}

fn rev_for(config: &GitConfig) -> CargoResult<StrBuf> {
    Ok(git_output!(*config, "rev-parse {}", config.reference))
}

fn git(config: &GitConfig, str: &str) -> ProcessBuilder {
    println!("Executing git {} @ {}", str, config.path.display());
    process("git").args(str.split(' ').collect::<Vec<&str>>().as_slice()).cwd(config.path.clone())
}

fn git_inherit(config: &GitConfig, str: StrBuf) -> CargoResult<()> {
    git(config, str.as_slice()).exec().map_err(|err|
        human_error(format_strbuf!("Couldn't execute `git {}`: {}", str, err), None::<&str>, err))
}

fn git_output(config: &GitConfig, str: StrBuf) -> CargoResult<StrBuf> {
    let output = try!(git(config, str.as_slice()).exec_with_output().map_err(|err|
        human_error(format_strbuf!("Couldn't execute `git {}`", str), None::<&str>, err)));

    Ok(to_str(output.output.as_slice()))
}

fn to_str(vec: &[u8]) -> StrBuf {
    format_strbuf!("{}", str::from_utf8_lossy(vec))
}
<|endoftext|>


<commit_before>extern crate regex;
#[cfg(windows)]
extern crate winreg;

pub use super::super::compiler::*;

use super::postprocess;
use super::super::utils::filter;
use super::super::io::memstream::MemStream;
use super::super::io::tempfile::TempFile;
use super::super::lazy::Lazy;

use std::fs::File;
use std::io::{Cursor, Error, Write};
use std::path::{Path, PathBuf};
use std::process::Command;
use std::sync::Arc;
use self::regex::bytes::{NoExpand, Regex};

pub struct VsCompiler {
    temp_dir: PathBuf,
    toolchains: ToolchainHolder,
}

impl VsCompiler {
    pub fn new(temp_dir: &Path) -> Self {
        VsCompiler {
            temp_dir: temp_dir.to_path_buf(),
            toolchains: ToolchainHolder::new(),
        }
    }
}

struct VsToolchain {
    temp_dir: PathBuf,
    path: PathBuf,
    identifier: Lazy<Option<String>>,
}

impl VsToolchain {
    pub fn new(path: PathBuf, temp_dir: PathBuf) -> Self {
        VsToolchain {
            temp_dir: temp_dir,
            path: path,
            identifier: Lazy::new(),
        }
    }
}

impl Compiler for VsCompiler {
    fn resolve_toolchain(&self, command: &CommandInfo) -> Option<Arc<Toolchain>> {
        if command.program
            .file_name()
            .and_then(|n| n.to_str())
            .map(|n| n.to_lowercase())
            .map_or(false, |n| (n == "cl.exe") || (n == "cl")) {
            command.find_executable().and_then(|path| {
                self.toolchains.resolve(&path,
                                        |path| Arc::new(VsToolchain::new(path, self.temp_dir.clone())))
            })
        } else {
            None
        }
    }

    #[cfg(unix)]
    fn discovery_toolchains(&self) -> Vec<Arc<Toolchain>> {
        Vec::new()
    }

    #[cfg(windows)]
    fn discovery_toolchains(&self) -> Vec<Arc<Toolchain>> {
        use self::winreg::RegKey;
        use self::winreg::enums::*;
        use std::ffi::OsString;

        lazy_static!{
			static ref RE:self::regex::Regex = self::regex::Regex::new(r"^\d+\.\d+$").unwrap();
		}
        vec!["SOFTWARE\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7", "SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VC7"]
            .iter()
            .filter_map(|reg_path| RegKey::predef(HKEY_LOCAL_MACHINE).open_subkey_with_flags(reg_path, KEY_READ).ok())
            .flat_map(|key| -> Vec<OsString> {
                key.enum_values()
                    .filter_map(|x| x.ok())
                    .map(|(name, _)| name)
                    .filter(|name| RE.is_match(&name))
                    .filter_map(|name: String| -> Option<OsString> { key.get_value(name).ok() })
                    .collect()
            })
            .map(|path| -> Arc<Toolchain> {
                Arc::new(VsToolchain::new(Path::new(&path).join("bin/cl.exe"), self.temp_dir.clone()))
            })
            .filter(|toolchain| toolchain.identifier().is_some())
            .collect()
    }

    fn create_task(&self, command: CommandInfo, args: &[String]) -> Result<Option<CompilationTask>, String> {
        self.resolve_toolchain(&command)
            .ok_or(format!("Can't get toolchain for {}", command.program.display()))
            .and_then(|toolchain| super::prepare::create_task(toolchain, command, args))
    }

    fn preprocess_step(&self, task: &CompilationTask) -> Result<PreprocessResult, Error> {
        // Make parameters list for preprocessing.
        let mut args = filter(&task.args, |arg: &Arg| -> Option<String> {
            match arg {
                &Arg::Flag { ref scope, ref flag } => {
                    match scope {
                        &Scope::Preprocessor |
                        &Scope::Shared => Some("/".to_string() + &flag),
                        &Scope::Ignore | &Scope::Compiler => None,
                    }
                }
                &Arg::Param { ref scope, ref flag, ref value } => {
                    match scope {
                        &Scope::Preprocessor |
                        &Scope::Shared => Some("/".to_string() + &flag + &value),
                        &Scope::Ignore | &Scope::Compiler => None,
                    }
                }
                &Arg::Input { .. } => None,
                &Arg::Output { .. } => None,
            }
        });

        // Add preprocessor paramters.
        args.push("/nologo".to_string());
        args.push("/T".to_string() + &task.language);
        args.push("/E".to_string());
        args.push("/we4002".to_string()); // C4002: too many actual parameters for macro 'identifier'
        args.push(task.input_source.display().to_string());

        let mut command = task.command.to_command();
        command.args(&args)
            .arg(&join_flag("/Fo", &task.output_object)); // /Fo option also set output path for #import directive
        let output = try!(command.output());
        if output.status.success() {
            let mut content = MemStream::new();
            if task.input_precompiled.is_some() || task.output_precompiled.is_some() {
                try!(postprocess::filter_preprocessed(&mut Cursor::new(output.stdout),
                                                      &mut content,
                                                      &task.marker_precompiled,
                                                      task.output_precompiled.is_some()));
            } else {
                try!(content.write(&output.stdout));
            };
            Ok(PreprocessResult::Success(content))
        } else {
            Ok(PreprocessResult::Failed(OutputInfo {
                status: output.status.code(),
                stdout: Vec::new(),
                stderr: output.stderr,
            }))
        }
    }

    // Compile preprocessed file.
    fn compile_prepare_step(&self, task: CompilationTask, preprocessed: MemStream) -> Result<CompileStep, Error> {
        let mut args = filter(&task.args, |arg: &Arg| -> Option<String> {
            match arg {
                &Arg::Flag { ref scope, ref flag } => {
                    match scope {
                        &Scope::Compiler | &Scope::Shared => Some("/".to_string() + &flag),
                        &Scope::Preprocessor if task.output_precompiled.is_some() => Some("/".to_string() + &flag),
                        &Scope::Ignore |
                        &Scope::Preprocessor => None,
                    }
                }
                &Arg::Param { ref scope, ref flag, ref value } => {
                    match scope {
                        &Scope::Compiler | &Scope::Shared => Some("/".to_string() + &flag + &value),
                        &Scope::Preprocessor if task.output_precompiled.is_some() => {
                            Some("/".to_string() + &flag + &value)
                        }
                        &Scope::Ignore |
                        &Scope::Preprocessor => None,
                    }
                }
                &Arg::Input { .. } => None,
                &Arg::Output { .. } => None,
            }
        });
        args.push("/nologo".to_string());
        args.push("/T".to_string() + &task.language);
        match &task.input_precompiled {
            &Some(ref path) => {
                args.push("/Yu".to_string());
                args.push("/Fp".to_string() + &path.display().to_string());
            }
            &None => {}
        }
        if task.output_precompiled.is_some() {
            args.push("/Yc".to_string());
        }
        Ok(CompileStep::new(task, preprocessed, args, true))
    }
}

impl Toolchain for VsToolchain {
    fn identifier(&self) -> Option<String> {
        self.identifier.get(|| vs_identifier(&self.path))
    }

    fn compile_step(&self, task: CompileStep) -> Result<OutputInfo, Error> {
        // Input file path.
        let input_temp = TempFile::new_in(&self.temp_dir, ".i");
        try!(File::create(input_temp.path()).and_then(|mut s| task.preprocessed.copy(&mut s)));
        // Run compiler.

        let mut command = Command::new(&self.path);
        command.env_clear()
            .arg("/c")
            .args(&task.args)
            .arg(input_temp.path().to_str().unwrap())
            .arg(&join_flag("/Fo", &task.output_object));
        // Output files.
        match &task.output_precompiled {
            &Some(ref path) => {
                command.arg(join_flag("/Fp", path));
            }
            &None => {}
        }
        match &task.input_precompiled {
            &Some(ref path) => {
                command.arg(join_flag("/Fp", path));
            }
            &None => {}
        }
        // Save input file name for output filter.
        let temp_file = input_temp.path()
            .file_name()
            .and_then(|o| o.to_str())
            .map(|o| o.as_bytes())
            .unwrap_or(b"");
        // Execute.
        command.output().map(|o| {
            OutputInfo {
                status: o.status.code(),
                stdout: prepare_output(temp_file, o.stdout, o.status.code() == Some(0)),
                stderr: o.stderr,
            }
        })
    }
}

#[cfg(unix)]
fn vs_identifier(_: &Path) -> Option<String> {
    None
}

#[cfg(windows)]
fn vs_identifier(path: &Path) -> Option<String> {
    // extern crate winapi;
    extern crate kernel32;
    extern crate version;

    use winapi::*;
    use std::convert::Into;
    use std::ffi::OsStr;
    use std::ptr;
    use std::slice;
    use std::os::windows::ffi::OsStrExt;

    #[repr(C)]
    struct LANGANDCODEPAGE {
        language: WORD,
        codepage: WORD,
    };

    fn utf16<'a, T: Into<&'a OsStr>>(value: T) -> Vec<u16> {
        value.into().encode_wide().chain(Some(0).into_iter()).collect()
    };

    let path_raw = utf16(path.as_os_str());
    // Get version info size
    let size = unsafe { version::GetFileVersionInfoSizeW(path_raw.as_ptr(), ptr::null_mut()) };
    if size == 0 {
        return None;
    }
    // Load version info
    let mut data: Vec<u8> = Vec::with_capacity(size as usize);
    unsafe {
        data.set_len(size as usize);
        if version::GetFileVersionInfoW(path_raw.as_ptr(), 0, size, data.as_mut_ptr() as *mut c_void) == 0 {
            return None;
        }
    }
    // Read translation
    let translation_key = unsafe {
        let mut value_size: DWORD = 0;
        let mut value_data: LPVOID = ptr::null_mut();
        if version::VerQueryValueW(data.as_ptr() as LPCVOID,
                                   utf16(OsStr::new("\\VarFileInfo\\Translation")).as_ptr(),
                                   &mut value_data,
                                   &mut value_size) == 0 {
            return None;
        }
        let codepage = value_data as *const LANGANDCODEPAGE;
        format!("\\StringFileInfo\\{:04X}{:04X}",
                (*codepage).language,
                (*codepage).codepage)
    };
    // Read product version
    let product_version = unsafe {
        let mut value_size: DWORD = 0;
        let mut value_data: LPVOID = ptr::null_mut();
        if version::VerQueryValueW(data.as_ptr() as LPCVOID,
                                   utf16(OsStr::new(&(translation_key + "\\ProductVersion"))).as_ptr(),
                                   &mut value_data,
                                   &mut value_size) == 0 {
            return None;
        }
        if value_size == 0 {
            return None;
        }
        String::from_utf16_lossy(slice::from_raw_parts(value_data as *mut u16, (value_size - 1) as usize))
    };
    Some("cl ".to_string() + &product_version)
}

fn prepare_output(line: &[u8], mut buffer: Vec<u8>, success: bool) -> Vec<u8> {
    // Remove strage file name from output
    let mut begin = match (line.len() < buffer.len()) && buffer.starts_with(line) && is_eol(buffer[line.len()]) {
        true => line.len(),
        false => 0,
    };
    while begin < buffer.len() && is_eol(buffer[begin]) {
        begin += 1;
    }
    buffer = buffer.split_off(begin);
    if success {
        // Remove some redundant lines
        lazy_static! {
			static ref RE: Regex = Regex::new(r"(?m)^\S+[^:]*\(\d+\) : warning C4628: .*$\n?").unwrap();
		}
        buffer = RE.replace_all(&buffer, NoExpand(b""))
    }
    buffer
}

fn is_eol(c: u8) -> bool {
    match c {
        b'\r' | b'\n' => true,
        _ => false,
    }
}

fn join_flag(flag: &str, path: &Path) -> String {
    flag.to_string() + &path.to_str().unwrap()
}

#[cfg(test)]
mod test {
    use std::io::Write;

    fn check_prepare_output(original: &str, expected: &str, line: &str, success: bool) {
        let mut stream: Vec<u8> = Vec::new();
        stream.write(&original.as_bytes()[..]).unwrap();

        let result = super::prepare_output(line.as_bytes(), stream, success);
        assert_eq!(String::from_utf8_lossy(&result), expected);
    }

    #[test]
    fn test_prepare_output_simple() {
        check_prepare_output(r#"BLABLABLA
foo.c : warning C4411: foo bar
"#,
                             r#"foo.c : warning C4411: foo bar
"#,
                             "BLABLABLA",
                             true);
    }

    #[test]
    fn test_prepare_output_c4628_remove() {
        check_prepare_output(r#"BLABLABLA
foo.c(41) : warning C4411: foo bar
foo.c(42) : warning C4628: foo bar
foo.c(43) : warning C4433: foo bar
"#,
                             r#"foo.c(41) : warning C4411: foo bar
foo.c(43) : warning C4433: foo bar
"#,
                             "BLABLABLA",
                             true);
    }

    #[test]
    fn test_prepare_output_c4628_keep() {
        check_prepare_output(r#"BLABLABLA
foo.c(41) : warning C4411: foo bar
foo.c(42) : warning C4628: foo bar
foo.c(43) : warning C4433: foo bar
"#,
                             r#"foo.c(41) : warning C4411: foo bar
foo.c(42) : warning C4628: foo bar
foo.c(43) : warning C4433: foo bar
"#,
                             "BLABLABLA",
                             false);
    }
}
<commit_msg>Add requirement environment variables for cl.exe compiler<commit_after>extern crate regex;
#[cfg(windows)]
extern crate winreg;

pub use super::super::compiler::*;

use super::postprocess;
use super::super::utils::filter;
use super::super::io::memstream::MemStream;
use super::super::io::tempfile::TempFile;
use super::super::lazy::Lazy;

use std::fs::File;
use std::io::{Cursor, Error, Write};
use std::env;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::sync::Arc;
use self::regex::bytes::{NoExpand, Regex};

pub struct VsCompiler {
    temp_dir: PathBuf,
    toolchains: ToolchainHolder,
}

impl VsCompiler {
    pub fn new(temp_dir: &Path) -> Self {
        VsCompiler {
            temp_dir: temp_dir.to_path_buf(),
            toolchains: ToolchainHolder::new(),
        }
    }
}

struct VsToolchain {
    temp_dir: PathBuf,
    path: PathBuf,
    identifier: Lazy<Option<String>>,
}

impl VsToolchain {
    pub fn new(path: PathBuf, temp_dir: PathBuf) -> Self {
        VsToolchain {
            temp_dir: temp_dir,
            path: path,
            identifier: Lazy::new(),
        }
    }
}

impl Compiler for VsCompiler {
    fn resolve_toolchain(&self, command: &CommandInfo) -> Option<Arc<Toolchain>> {
        if command.program
            .file_name()
            .and_then(|n| n.to_str())
            .map(|n| n.to_lowercase())
            .map_or(false, |n| (n == "cl.exe") || (n == "cl")) {
            command.find_executable().and_then(|path| {
                self.toolchains.resolve(&path,
                                        |path| Arc::new(VsToolchain::new(path, self.temp_dir.clone())))
            })
        } else {
            None
        }
    }

    #[cfg(unix)]
    fn discovery_toolchains(&self) -> Vec<Arc<Toolchain>> {
        Vec::new()
    }

    #[cfg(windows)]
    fn discovery_toolchains(&self) -> Vec<Arc<Toolchain>> {
        use self::winreg::RegKey;
        use self::winreg::enums::*;
        use std::ffi::OsString;

        lazy_static!{
			static ref RE:self::regex::Regex = self::regex::Regex::new(r"^\d+\.\d+$").unwrap();
		}
        vec!["SOFTWARE\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7", "SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VC7"]
            .iter()
            .filter_map(|reg_path| RegKey::predef(HKEY_LOCAL_MACHINE).open_subkey_with_flags(reg_path, KEY_READ).ok())
            .flat_map(|key| -> Vec<OsString> {
                key.enum_values()
                    .filter_map(|x| x.ok())
                    .map(|(name, _)| name)
                    .filter(|name| RE.is_match(&name))
                    .filter_map(|name: String| -> Option<OsString> { key.get_value(name).ok() })
                    .collect()
            })
            .map(|path| -> Arc<Toolchain> {
                Arc::new(VsToolchain::new(Path::new(&path).join("bin/cl.exe"), self.temp_dir.clone()))
            })
            .filter(|toolchain| toolchain.identifier().is_some())
            .collect()
    }

    fn create_task(&self, command: CommandInfo, args: &[String]) -> Result<Option<CompilationTask>, String> {
        self.resolve_toolchain(&command)
            .ok_or(format!("Can't get toolchain for {}", command.program.display()))
            .and_then(|toolchain| super::prepare::create_task(toolchain, command, args))
    }

    fn preprocess_step(&self, task: &CompilationTask) -> Result<PreprocessResult, Error> {
        // Make parameters list for preprocessing.
        let mut args = filter(&task.args, |arg: &Arg| -> Option<String> {
            match arg {
                &Arg::Flag { ref scope, ref flag } => {
                    match scope {
                        &Scope::Preprocessor |
                        &Scope::Shared => Some("/".to_string() + &flag),
                        &Scope::Ignore | &Scope::Compiler => None,
                    }
                }
                &Arg::Param { ref scope, ref flag, ref value } => {
                    match scope {
                        &Scope::Preprocessor |
                        &Scope::Shared => Some("/".to_string() + &flag + &value),
                        &Scope::Ignore | &Scope::Compiler => None,
                    }
                }
                &Arg::Input { .. } => None,
                &Arg::Output { .. } => None,
            }
        });

        // Add preprocessor paramters.
        args.push("/nologo".to_string());
        args.push("/T".to_string() + &task.language);
        args.push("/E".to_string());
        args.push("/we4002".to_string()); // C4002: too many actual parameters for macro 'identifier'
        args.push(task.input_source.display().to_string());

        let mut command = task.command.to_command();
        command.args(&args)
            .arg(&join_flag("/Fo", &task.output_object)); // /Fo option also set output path for #import directive
        let output = try!(command.output());
        if output.status.success() {
            let mut content = MemStream::new();
            if task.input_precompiled.is_some() || task.output_precompiled.is_some() {
                try!(postprocess::filter_preprocessed(&mut Cursor::new(output.stdout),
                                                      &mut content,
                                                      &task.marker_precompiled,
                                                      task.output_precompiled.is_some()));
            } else {
                try!(content.write(&output.stdout));
            };
            Ok(PreprocessResult::Success(content))
        } else {
            Ok(PreprocessResult::Failed(OutputInfo {
                status: output.status.code(),
                stdout: Vec::new(),
                stderr: output.stderr,
            }))
        }
    }

    // Compile preprocessed file.
    fn compile_prepare_step(&self, task: CompilationTask, preprocessed: MemStream) -> Result<CompileStep, Error> {
        let mut args = filter(&task.args, |arg: &Arg| -> Option<String> {
            match arg {
                &Arg::Flag { ref scope, ref flag } => {
                    match scope {
                        &Scope::Compiler | &Scope::Shared => Some("/".to_string() + &flag),
                        &Scope::Preprocessor if task.output_precompiled.is_some() => Some("/".to_string() + &flag),
                        &Scope::Ignore |
                        &Scope::Preprocessor => None,
                    }
                }
                &Arg::Param { ref scope, ref flag, ref value } => {
                    match scope {
                        &Scope::Compiler | &Scope::Shared => Some("/".to_string() + &flag + &value),
                        &Scope::Preprocessor if task.output_precompiled.is_some() => {
                            Some("/".to_string() + &flag + &value)
                        }
                        &Scope::Ignore |
                        &Scope::Preprocessor => None,
                    }
                }
                &Arg::Input { .. } => None,
                &Arg::Output { .. } => None,
            }
        });
        args.push("/nologo".to_string());
        args.push("/T".to_string() + &task.language);
        match &task.input_precompiled {
            &Some(ref path) => {
                args.push("/Yu".to_string());
                args.push("/Fp".to_string() + &path.display().to_string());
            }
            &None => {}
        }
        if task.output_precompiled.is_some() {
            args.push("/Yc".to_string());
        }
        Ok(CompileStep::new(task, preprocessed, args, true))
    }
}

impl Toolchain for VsToolchain {
    fn identifier(&self) -> Option<String> {
        self.identifier.get(|| vs_identifier(&self.path))
    }

    fn compile_step(&self, task: CompileStep) -> Result<OutputInfo, Error> {
        // Input file path.
        let input_temp = TempFile::new_in(&self.temp_dir, ".i");
        try!(File::create(input_temp.path()).and_then(|mut s| task.preprocessed.copy(&mut s)));
        // Run compiler.
        let mut command = Command::new(&self.path);
        command.env_clear()
            .arg("/c")
            .args(&task.args)
            .arg(input_temp.path().to_str().unwrap())
            .arg(&join_flag("/Fo", &task.output_object));
        // Copy required environment variables.
        for (name, value) in vec!["SystemDrive", "SystemRoot", "TEMP", "TMP"]
            .iter()
            .filter_map(|name| env::var(name).ok().map(|value| (name, value))) {
            command.env(name, value);
        }
        // Output files.
        match &task.output_precompiled {
            &Some(ref path) => {
                command.arg(join_flag("/Fp", path));
            }
            &None => {}
        }
        match &task.input_precompiled {
            &Some(ref path) => {
                command.arg(join_flag("/Fp", path));
            }
            &None => {}
        }
        // Save input file name for output filter.
        let temp_file = input_temp.path()
            .file_name()
            .and_then(|o| o.to_str())
            .map(|o| o.as_bytes())
            .unwrap_or(b"");
        // Execute.
        command.output().map(|o| {
            OutputInfo {
                status: o.status.code(),
                stdout: prepare_output(temp_file, o.stdout, o.status.code() == Some(0)),
                stderr: o.stderr,
            }
        })
    }
}

#[cfg(unix)]
fn vs_identifier(_: &Path) -> Option<String> {
    None
}

#[cfg(windows)]
fn vs_identifier(path: &Path) -> Option<String> {
    // extern crate winapi;
    extern crate kernel32;
    extern crate version;

    use winapi::*;
    use std::convert::Into;
    use std::ffi::OsStr;
    use std::ptr;
    use std::slice;
    use std::os::windows::ffi::OsStrExt;

    #[repr(C)]
    struct LANGANDCODEPAGE {
        language: WORD,
        codepage: WORD,
    };

    fn utf16<'a, T: Into<&'a OsStr>>(value: T) -> Vec<u16> {
        value.into().encode_wide().chain(Some(0).into_iter()).collect()
    };

    let path_raw = utf16(path.as_os_str());
    // Get version info size
    let size = unsafe { version::GetFileVersionInfoSizeW(path_raw.as_ptr(), ptr::null_mut()) };
    if size == 0 {
        return None;
    }
    // Load version info
    let mut data: Vec<u8> = Vec::with_capacity(size as usize);
    unsafe {
        data.set_len(size as usize);
        if version::GetFileVersionInfoW(path_raw.as_ptr(), 0, size, data.as_mut_ptr() as *mut c_void) == 0 {
            return None;
        }
    }
    // Read translation
    let translation_key = unsafe {
        let mut value_size: DWORD = 0;
        let mut value_data: LPVOID = ptr::null_mut();
        if version::VerQueryValueW(data.as_ptr() as LPCVOID,
                                   utf16(OsStr::new("\\VarFileInfo\\Translation")).as_ptr(),
                                   &mut value_data,
                                   &mut value_size) == 0 {
            return None;
        }
        let codepage = value_data as *const LANGANDCODEPAGE;
        format!("\\StringFileInfo\\{:04X}{:04X}",
                (*codepage).language,
                (*codepage).codepage)
    };
    // Read product version
    let product_version = unsafe {
        let mut value_size: DWORD = 0;
        let mut value_data: LPVOID = ptr::null_mut();
        if version::VerQueryValueW(data.as_ptr() as LPCVOID,
                                   utf16(OsStr::new(&(translation_key + "\\ProductVersion"))).as_ptr(),
                                   &mut value_data,
                                   &mut value_size) == 0 {
            return None;
        }
        if value_size == 0 {
            return None;
        }
        String::from_utf16_lossy(slice::from_raw_parts(value_data as *mut u16, (value_size - 1) as usize))
    };
    Some("cl ".to_string() + &product_version)
}

fn prepare_output(line: &[u8], mut buffer: Vec<u8>, success: bool) -> Vec<u8> {
    // Remove strage file name from output
    let mut begin = match (line.len() < buffer.len()) && buffer.starts_with(line) && is_eol(buffer[line.len()]) {
        true => line.len(),
        false => 0,
    };
    while begin < buffer.len() && is_eol(buffer[begin]) {
        begin += 1;
    }
    buffer = buffer.split_off(begin);
    if success {
        // Remove some redundant lines
        lazy_static! {
			static ref RE: Regex = Regex::new(r"(?m)^\S+[^:]*\(\d+\) : warning C4628: .*$\n?").unwrap();
		}
        buffer = RE.replace_all(&buffer, NoExpand(b""))
    }
    buffer
}

fn is_eol(c: u8) -> bool {
    match c {
        b'\r' | b'\n' => true,
        _ => false,
    }
}

fn join_flag(flag: &str, path: &Path) -> String {
    flag.to_string() + &path.to_str().unwrap()
}

#[cfg(test)]
mod test {
    use std::io::Write;

    fn check_prepare_output(original: &str, expected: &str, line: &str, success: bool) {
        let mut stream: Vec<u8> = Vec::new();
        stream.write(&original.as_bytes()[..]).unwrap();

        let result = super::prepare_output(line.as_bytes(), stream, success);
        assert_eq!(String::from_utf8_lossy(&result), expected);
    }

    #[test]
    fn test_prepare_output_simple() {
        check_prepare_output(r#"BLABLABLA
foo.c : warning C4411: foo bar
"#,
                             r#"foo.c : warning C4411: foo bar
"#,
                             "BLABLABLA",
                             true);
    }

    #[test]
    fn test_prepare_output_c4628_remove() {
        check_prepare_output(r#"BLABLABLA
foo.c(41) : warning C4411: foo bar
foo.c(42) : warning C4628: foo bar
foo.c(43) : warning C4433: foo bar
"#,
                             r#"foo.c(41) : warning C4411: foo bar
foo.c(43) : warning C4433: foo bar
"#,
                             "BLABLABLA",
                             true);
    }

    #[test]
    fn test_prepare_output_c4628_keep() {
        check_prepare_output(r#"BLABLABLA
foo.c(41) : warning C4411: foo bar
foo.c(42) : warning C4628: foo bar
foo.c(43) : warning C4433: foo bar
"#,
                             r#"foo.c(41) : warning C4411: foo bar
foo.c(42) : warning C4628: foo bar
foo.c(43) : warning C4433: foo bar
"#,
                             "BLABLABLA",
                             false);
    }
}
<|endoftext|>