<commit_before>//! Virtualize processor hardware for multiple software environments using Virtual Machine Extensions.

use crate::bits64::rflags::{self, RFlags};
use crate::vmx::{Result, VmFail};

/// Helper used to extract VMX-specific Result in accordance with
/// conventions described in Intel SDM, Volume 3C, Section 30.2.
#[inline(always)]
fn vmx_capture_status() -> Result<()> {
    let flags = unsafe { rflags::read() };

    if flags.contains(RFlags::FLAGS_ZF) {
        Err(VmFail::VmFailValid)
    } else if flags.contains(RFlags::FLAGS_CF) {
        Err(VmFail::VmFailInvalid)
    } else {
        Ok(())
    }
}

/// Enable VMX operation.
///
/// `addr` specifies a 4KB-aligned physical address of VMXON region initialized
/// in accordance with Intel SDM, Volume 3C, Section 24.11.5.
pub unsafe fn vmxon(addr: u64) -> Result<()> {
    asm!("vmxon $0" : /* no outputs */ : "m"(addr));
    vmx_capture_status()
}

/// Disable VMX operation.
pub unsafe fn vmxoff() -> Result<()> {
    asm!("vmxoff");
    vmx_capture_status()
}

/// Clear VMCS.
///
/// Ensures that VMCS data maintained on the processor is copied to the VMCS region
/// located at 4KB-aligned physical address `addr` and initializes some parts of it.
pub unsafe fn vmclear(addr: u64) -> Result<()> {
    asm!("vmclear $0" : /* no outputs */ : "m"(addr));
    vmx_capture_status()
}

/// Load current VMCS pointer.
///
/// Marks the current-VMCS pointer valid and loads it with the physical address `addr`.
pub unsafe fn vmptrld(addr: u64) -> Result<()> {
    asm!("vmptrld $0" : /* no outputs */ : "m"(addr));
    vmx_capture_status()
}

/// Return current VMCS pointer.
pub unsafe fn vmptrst() -> Result<u64> {
    let value: u64 = 0;
    asm!("vmptrst ($0)" : /* no outputs */ : "r"(&value) : "memory");
    vmx_capture_status().and(Ok(value))
}

/// Read a specified field from a VMCS.
pub unsafe fn vmread(field: u32) -> Result<u64> {
    let field: u64 = field.into();
    let value: u64;
    asm!("vmread $1, $0" : "=r"(value) : "r"(field));
    vmx_capture_status().and(Ok(value))
}

/// Write to a specified field in a VMCS.
pub unsafe fn vmwrite(field: u32, value: u64) -> Result<()> {
    let field: u64 = field.into();
    asm!("vmwrite $1, $0" : /* no outputs */ : "r"(field), "r"(value));
    vmx_capture_status()
}

/// Launch virtual machine.
pub unsafe fn vmlaunch() -> Result<()> {
    asm!("vmlaunch");
    vmx_capture_status()
}

/// Resume virtual machine.
pub unsafe fn vmresume() -> Result<()> {
    asm!("vmresume");
    vmx_capture_status()
}
<commit_msg>Document the use of inline for vmx_capture_status()<commit_after>//! Virtualize processor hardware for multiple software environments using Virtual Machine Extensions.

use crate::bits64::rflags::{self, RFlags};
use crate::vmx::{Result, VmFail};

/// Helper used to extract VMX-specific Result in accordance with
/// conventions described in Intel SDM, Volume 3C, Section 30.2.
// We inline this to provide an obstruction-free path from this function's
// call site to the moment where `rflags::read()` reads RFLAGS. Otherwise it's
// possible for RFLAGS register to be clobbered by a function prologue,
// see https://github.com/gz/rust-x86/pull/50.
#[inline(always)]
fn vmx_capture_status() -> Result<()> {
    let flags = unsafe { rflags::read() };

    if flags.contains(RFlags::FLAGS_ZF) {
        Err(VmFail::VmFailValid)
    } else if flags.contains(RFlags::FLAGS_CF) {
        Err(VmFail::VmFailInvalid)
    } else {
        Ok(())
    }
}

/// Enable VMX operation.
///
/// `addr` specifies a 4KB-aligned physical address of VMXON region initialized
/// in accordance with Intel SDM, Volume 3C, Section 24.11.5.
pub unsafe fn vmxon(addr: u64) -> Result<()> {
    asm!("vmxon $0" : /* no outputs */ : "m"(addr));
    vmx_capture_status()
}

/// Disable VMX operation.
pub unsafe fn vmxoff() -> Result<()> {
    asm!("vmxoff");
    vmx_capture_status()
}

/// Clear VMCS.
///
/// Ensures that VMCS data maintained on the processor is copied to the VMCS region
/// located at 4KB-aligned physical address `addr` and initializes some parts of it.
pub unsafe fn vmclear(addr: u64) -> Result<()> {
    asm!("vmclear $0" : /* no outputs */ : "m"(addr));
    vmx_capture_status()
}

/// Load current VMCS pointer.
///
/// Marks the current-VMCS pointer valid and loads it with the physical address `addr`.
pub unsafe fn vmptrld(addr: u64) -> Result<()> {
    asm!("vmptrld $0" : /* no outputs */ : "m"(addr));
    vmx_capture_status()
}

/// Return current VMCS pointer.
pub unsafe fn vmptrst() -> Result<u64> {
    let value: u64 = 0;
    asm!("vmptrst ($0)" : /* no outputs */ : "r"(&value) : "memory");
    vmx_capture_status().and(Ok(value))
}

/// Read a specified field from a VMCS.
pub unsafe fn vmread(field: u32) -> Result<u64> {
    let field: u64 = field.into();
    let value: u64;
    asm!("vmread $1, $0" : "=r"(value) : "r"(field));
    vmx_capture_status().and(Ok(value))
}

/// Write to a specified field in a VMCS.
pub unsafe fn vmwrite(field: u32, value: u64) -> Result<()> {
    let field: u64 = field.into();
    asm!("vmwrite $1, $0" : /* no outputs */ : "r"(field), "r"(value));
    vmx_capture_status()
}

/// Launch virtual machine.
pub unsafe fn vmlaunch() -> Result<()> {
    asm!("vmlaunch");
    vmx_capture_status()
}

/// Resume virtual machine.
pub unsafe fn vmresume() -> Result<()> {
    asm!("vmresume");
    vmx_capture_status()
}
<|endoftext|>


<commit_before>// Copyright (c) <2015> <lummax>
// Licensed under MIT (http://opensource.org/licenses/MIT)

use std::collections::VecMap;
use std::num::Int;
use std::{os, mem};

use gc_object::GCObjectRef;
use constants::{BLOCK_SIZE, LINE_SIZE, NUM_LINES_PER_BLOCK};

pub struct BlockInfo {
    mmap: os::MemoryMap,
    line_counter: VecMap<u8>,
    hole_count: u8,
}

impl BlockInfo {
    pub fn new(mmap: os::MemoryMap) -> BlockInfo {
        debug_assert!(mmap.len() > mem::size_of::<BlockInfo>());
        let mut block = BlockInfo {
            mmap: mmap,
            line_counter: VecMap::with_capacity(NUM_LINES_PER_BLOCK),
            hole_count: 0,
        };
        block.clear_line_counts();
        return block;
    }

    pub fn increment_lines(&mut self, object: GCObjectRef) {
        self.update_line_nums(object, true);
    }

    pub fn decrement_lines(&mut self, object: GCObjectRef) {
        self.update_line_nums(object, false);
    }

    pub fn count_holes_and_marked_lines(&self) -> (u8, u8) {
        return (self.hole_count,
                self.line_counter.values().filter(|&e| *e != 0).count() as u8);
    }

    pub fn count_holes_and_available_lines(&self) -> (u8, u8) {
        return (self.hole_count,
                self.line_counter.values().filter(|&e| *e == 0).count() as u8);
    }

    pub fn clear_line_counts(&mut self) {
        for index in range(0, NUM_LINES_PER_BLOCK) {
            self.line_counter.insert(index, 0);
        }
    }

    pub fn reset(&mut self) {
        self.clear_line_counts();
        self.hole_count = 0;
        self.evacuation_candidate = false;
    }

    pub fn is_empty(&self) -> bool {
        return self.line_counter.values().all(|v| *v == 0);
    }

    pub fn offset(&self, offset: uint) -> GCObjectRef {
        return unsafe{ self.mmap.data().offset(offset as int) } as GCObjectRef;
    }

    pub fn scan_block(&self, last_high_offset: u16) -> Option<(u16, u16)> {
        debug!("Scanning block {:p} for a hole", self);
        let last_high_index = last_high_offset as uint / LINE_SIZE;
        let mut low_index = NUM_LINES_PER_BLOCK - 1;
        for index in range(last_high_index + 1, NUM_LINES_PER_BLOCK) {
            if self.line_counter.get(&index).map_or(true, |c| *c == 0) {
                // +1 to skip the next line in case an object straddles lines
                low_index = index + 1;
                break;
            }
        }
        debug!("Found low index {} in block {:p}", low_index, self);
        let mut high_index = NUM_LINES_PER_BLOCK;
        for index in range(low_index + 1, NUM_LINES_PER_BLOCK) {
            if self.line_counter.get(&index).map_or(false, |c| *c != 0) {
                high_index = index;
                break;
            }
        }
        debug!("Found high index {} in block {:p}", high_index, self);
        return if low_index < (NUM_LINES_PER_BLOCK - 1) {
            Some(((low_index * LINE_SIZE) as u16,
            (high_index * LINE_SIZE - 1) as u16))
        } else {
            debug!("Found no hole in block {:p}", self);
            None
        };
    }

    pub fn count_holes(&mut self) {
        let holes = self.line_counter.values()
            .fold((0, false), |(holes, in_hole), &elem|
                  match (in_hole, elem) {
                    (false, 0) => (holes + 1, true),
                    (_, _) => (holes, false),
                  }).0;
        self.hole_count = holes;
    }
}

impl BlockInfo {
    fn object_to_line_num(object: GCObjectRef) -> uint {
        return (object as uint % BLOCK_SIZE) / LINE_SIZE;
    }

    fn update_line_nums(&mut self, object: GCObjectRef, increment: bool) {
        // This calculates how many lines are affected starting from a
        // LINE_SIZE aligned address. So it might not mark enough lines. But
        // that does not matter as we always skip a line in scan_block()
        let line_num = BlockInfo::object_to_line_num(object);
        let object_size = unsafe{ (*object).object_size() };
        for line in range(line_num, line_num + (object_size / LINE_SIZE) + 1) {
            match increment {
                true => {
                    if self.line_counter.contains_key(&line) {
                        if let Some(val) = self.line_counter.get_mut(&line) {
                            *val += 1;
                        }
                    } else { self.line_counter.insert(line, 1); }
                    debug!("Incremented line count for line {} to {}", line,
                           self.line_counter.get(&line).unwrap());
                },
                false => {
                    if self.line_counter.contains_key(&line) {
                        if let Some(val) = self.line_counter.get_mut(&line) {
                            *val = Int::saturating_sub(*val, 1);
                        }
                    } else { self.line_counter.insert(line, 0); }
                    debug!("Decremented line count for line {} to {}", line,
                           self.line_counter.get(&line).unwrap());
                }
            }
        }
    }
}

<commit_msg>Implement evacuation_candidate in BlockInfo<commit_after>// Copyright (c) <2015> <lummax>
// Licensed under MIT (http://opensource.org/licenses/MIT)

use std::collections::VecMap;
use std::num::Int;
use std::{os, mem};

use gc_object::GCObjectRef;
use constants::{BLOCK_SIZE, LINE_SIZE, NUM_LINES_PER_BLOCK};

pub struct BlockInfo {
    mmap: os::MemoryMap,
    line_counter: VecMap<u8>,
    hole_count: u8,
    evacuation_candidate: bool,
}

impl BlockInfo {
    pub fn new(mmap: os::MemoryMap) -> BlockInfo {
        debug_assert!(mmap.len() > mem::size_of::<BlockInfo>());
        let mut block = BlockInfo {
            mmap: mmap,
            line_counter: VecMap::with_capacity(NUM_LINES_PER_BLOCK),
            hole_count: 0,
            evacuation_candidate: false,
        };
        block.clear_line_counts();
        return block;
    }

    pub fn set_evacuation_candidate(&mut self, hole_count: u8) {
        debug!("Set block {:p} to evacuation_candidate={} ({} holes)",
               &self, self.hole_count >= hole_count, self.hole_count);
        self.evacuation_candidate = self.hole_count >= hole_count;
    }

    pub fn is_evacuation_candidate(&self) -> bool{
        return self.evacuation_candidate;
    }

    pub fn increment_lines(&mut self, object: GCObjectRef) {
        self.update_line_nums(object, true);
    }

    pub fn decrement_lines(&mut self, object: GCObjectRef) {
        self.update_line_nums(object, false);
    }

    pub fn count_holes_and_marked_lines(&self) -> (u8, u8) {
        return (self.hole_count,
                self.line_counter.values().filter(|&e| *e != 0).count() as u8);
    }

    pub fn count_holes_and_available_lines(&self) -> (u8, u8) {
        return (self.hole_count,
                self.line_counter.values().filter(|&e| *e == 0).count() as u8);
    }

    pub fn clear_line_counts(&mut self) {
        for index in range(0, NUM_LINES_PER_BLOCK) {
            self.line_counter.insert(index, 0);
        }
    }

    pub fn reset(&mut self) {
        self.clear_line_counts();
        self.hole_count = 0;
        self.evacuation_candidate = false;
    }

    pub fn is_empty(&self) -> bool {
        return self.line_counter.values().all(|v| *v == 0);
    }

    pub fn offset(&self, offset: uint) -> GCObjectRef {
        return unsafe{ self.mmap.data().offset(offset as int) } as GCObjectRef;
    }

    pub fn scan_block(&self, last_high_offset: u16) -> Option<(u16, u16)> {
        debug!("Scanning block {:p} for a hole", self);
        let last_high_index = last_high_offset as uint / LINE_SIZE;
        let mut low_index = NUM_LINES_PER_BLOCK - 1;
        for index in range(last_high_index + 1, NUM_LINES_PER_BLOCK) {
            if self.line_counter.get(&index).map_or(true, |c| *c == 0) {
                // +1 to skip the next line in case an object straddles lines
                low_index = index + 1;
                break;
            }
        }
        debug!("Found low index {} in block {:p}", low_index, self);
        let mut high_index = NUM_LINES_PER_BLOCK;
        for index in range(low_index + 1, NUM_LINES_PER_BLOCK) {
            if self.line_counter.get(&index).map_or(false, |c| *c != 0) {
                high_index = index;
                break;
            }
        }
        debug!("Found high index {} in block {:p}", high_index, self);
        return if low_index < (NUM_LINES_PER_BLOCK - 1) {
            Some(((low_index * LINE_SIZE) as u16,
            (high_index * LINE_SIZE - 1) as u16))
        } else {
            debug!("Found no hole in block {:p}", self);
            None
        };
    }

    pub fn count_holes(&mut self) {
        let holes = self.line_counter.values()
            .fold((0, false), |(holes, in_hole), &elem|
                  match (in_hole, elem) {
                    (false, 0) => (holes + 1, true),
                    (_, _) => (holes, false),
                  }).0;
        self.hole_count = holes;
    }
}

impl BlockInfo {
    fn object_to_line_num(object: GCObjectRef) -> uint {
        return (object as uint % BLOCK_SIZE) / LINE_SIZE;
    }

    fn update_line_nums(&mut self, object: GCObjectRef, increment: bool) {
        // This calculates how many lines are affected starting from a
        // LINE_SIZE aligned address. So it might not mark enough lines. But
        // that does not matter as we always skip a line in scan_block()
        let line_num = BlockInfo::object_to_line_num(object);
        let object_size = unsafe{ (*object).object_size() };
        for line in range(line_num, line_num + (object_size / LINE_SIZE) + 1) {
            match increment {
                true => {
                    if self.line_counter.contains_key(&line) {
                        if let Some(val) = self.line_counter.get_mut(&line) {
                            *val += 1;
                        }
                    } else { self.line_counter.insert(line, 1); }
                    debug!("Incremented line count for line {} to {}", line,
                           self.line_counter.get(&line).unwrap());
                },
                false => {
                    if self.line_counter.contains_key(&line) {
                        if let Some(val) = self.line_counter.get_mut(&line) {
                            *val = Int::saturating_sub(*val, 1);
                        }
                    } else { self.line_counter.insert(line, 0); }
                    debug!("Decremented line count for line {} to {}", line,
                           self.line_counter.get(&line).unwrap());
                }
            }
        }
    }
}

<|endoftext|>


<commit_before>use rustc_plugin::Registry;

use syntax::ext::base::IdentTT;
use syntax::parse::token;

use syntax::ast;
use syntax::ptr::P;
use syntax::codemap::{Span, DUMMY_SP};
use syntax::ext::base::{DummyResult, ExtCtxt, MacEager, MacResult, SyntaxExtension, NormalTT, TTMacroExpander};
use syntax::ext::build::AstBuilder;
use syntax::ext::hygiene::Mark;
use syntax::tokenstream::TokenTree;
use syntax::util::small_vector::SmallVector;
use syntax::parse::PResult;
use syntax::parse::parser::Parser;

use itertools::Itertools;

pub fn register_store(reg: &mut Registry) {
    // Store definitions
    reg.register_syntax_extension(token::intern("define_store_action"),
            NormalTT(Box::new(expand_define_store_action), None, false));

//    reg.register_syntax_extension(token::intern("define_store"),
//            IdentTT(Box::new(expand_define_store), None, false));
}

trait Store {
}

trait StoreAction {
    type Store: Store;

    fn name() -> &'static str;
    fn apply_mut(store: &mut Self::Store);
}

macro_rules! write_action_case {
    ($ecx: expr, $w: expr, $store_name:expr, $action_name:expr, $e:expr) => ({
        let q_store_name = $store_name;
        let q_action_name = $action_name;
        let q_expr = $e;
        let out = $w;
        quote_stmt!($ecx, {
            //write!($w, "test");
            //write!($w, "\t\tcase '{}': return {};\n", "1", "2");
            write!($out, "\t\tcase '{}': return {};\n",
                $q_action_name,
                format!("{{ {}: {} }}",
                    $q_store_name,
                    stringify!($q_expr)
                )
            )
        })
    })
}

/// TODO: Document
pub fn expand_define_store<'cx>(ecx: &'cx mut ExtCtxt, span: Span, ident: ast::Ident, tts: Vec<TokenTree>) -> Box<MacResult + 'cx> {
    let mut parser = ecx.new_parser_from_tts(&tts);

    let store_name = ident.name.to_string();
    let struct_name = format!("{}Store", store_name);
    let struct_ident = ecx.ident_of(&struct_name[..]);

    let stmt = quote_stmt!(ecx, {
        struct $struct_ident {

        }
    }).unwrap();
    let stmts = vec![stmt];
    let block = ecx.block(DUMMY_SP, stmts);
    MacEager::expr(ecx.expr_block(block))
}

fn parse_action_expr<'cx, 'a>(ecx: &'cx mut ExtCtxt, span: Span, parser: &mut Parser<'a>) -> PResult<'a, P<ast::Expr>> {
    // Expression
    parser.parse_expr()
}

fn parse_default_expr<'cx, 'a>(ecx: &'cx mut ExtCtxt, span: Span, parser: &mut Parser<'a>) -> PResult<'a, P<ast::Expr>> {
    // Expression
    parser.parse_expr()
}

fn parse_define_store_action<'cx, 'a>(ecx: &'cx mut ExtCtxt, span: Span, parser: &mut Parser<'a>) -> PResult<'a, Box<MacResult + 'cx>> {
    // Output stream
    let w = try!(parser.parse_ident());
    try!(parser.expect(&token::Comma));

    // Store identifier
    let store_name = try!(parser.parse_ident()).name.to_string();
    try!(parser.expect(&token::Comma));

    // Token 'action'
    try!(parser.parse_ident());

    // Action name
    let action_name = try!(parser.parse_ident()).name.to_string();

    // =>
    try!(parser.expect(&token::FatArrow));

    // expression
    let expr = try!(parse_action_expr(ecx, span, parser));

    let stmt = write_action_case!(ecx, w, store_name, action_name, expr).unwrap();

    let stmts = vec![stmt];
    let block = ecx.block(DUMMY_SP, stmts);
    Ok(MacEager::expr(ecx.expr_block(block)))
}

pub fn expand_define_store_action<'cx>(ecx: &'cx mut ExtCtxt, span: Span, tts: &[TokenTree]) -> Box<MacResult + 'cx> {
    let mut parser = ecx.new_parser_from_tts(&tts);
    match parse_define_store_action(ecx, span, &mut parser) {
        Ok(mac_result) => mac_result,
        Err(mut err) => {
            err.emit();
            DummyResult::any(span)
        }
    }
}
<commit_msg>Cleanup plugin/actions<commit_after>use rustc_plugin::Registry;

use syntax::ext::base::IdentTT;
use syntax::parse::token;

use syntax::ast;
use syntax::ptr::P;
use syntax::codemap::{Span, DUMMY_SP};
use syntax::ext::base::{DummyResult, ExtCtxt, MacEager, MacResult, SyntaxExtension, NormalTT, TTMacroExpander};
use syntax::ext::build::AstBuilder;
use syntax::ext::hygiene::Mark;
use syntax::tokenstream::TokenTree;
use syntax::util::small_vector::SmallVector;
use syntax::parse::PResult;
use syntax::parse::parser::Parser;

use itertools::Itertools;

pub fn register_store(reg: &mut Registry) {
    // Store definitions
    reg.register_syntax_extension(token::intern("define_store_action"),
            NormalTT(Box::new(expand_define_store_action), None, false));
}

trait Store {
}

trait StoreAction {
    type Store: Store;

    fn name() -> &'static str;
    fn apply_mut(store: &mut Self::Store);
}

macro_rules! write_action_case {
    ($ecx: expr, $w: expr, $store_name:expr, $action_name:expr, $e:expr) => ({
        let q_store_name = $store_name;
        let q_action_name = $action_name;
        let q_expr = $e;
        let out = $w;
        quote_stmt!($ecx, {
            write!($out, "\t\tcase '{}': return {};\n",
                $q_action_name,
                format!("{{ {}: {} }}",
                    $q_store_name,
                    stringify!($q_expr)
                )
            )
        })
    })
}

fn parse_action_expr<'cx, 'a>(ecx: &'cx mut ExtCtxt, span: Span, parser: &mut Parser<'a>) -> PResult<'a, P<ast::Expr>> {
    // Expression
    parser.parse_expr()
}

fn parse_default_expr<'cx, 'a>(ecx: &'cx mut ExtCtxt, span: Span, parser: &mut Parser<'a>) -> PResult<'a, P<ast::Expr>> {
    // Expression
    parser.parse_expr()
}

fn parse_define_store_action<'cx, 'a>(ecx: &'cx mut ExtCtxt, span: Span, parser: &mut Parser<'a>) -> PResult<'a, Box<MacResult + 'cx>> {
    // Output stream
    let w = try!(parser.parse_ident());
    try!(parser.expect(&token::Comma));

    // Store identifier
    let store_name = try!(parser.parse_ident()).name.to_string();
    try!(parser.expect(&token::Comma));

    // Token 'action'
    try!(parser.parse_ident());

    // Action name
    let action_name = try!(parser.parse_ident()).name.to_string();

    // =>
    try!(parser.expect(&token::FatArrow));

    // expression
    let expr = try!(parse_action_expr(ecx, span, parser));

    let stmt = write_action_case!(ecx, w, store_name, action_name, expr).unwrap();

    let stmts = vec![stmt];
    let block = ecx.block(DUMMY_SP, stmts);
    Ok(MacEager::expr(ecx.expr_block(block)))
}

pub fn expand_define_store_action<'cx>(ecx: &'cx mut ExtCtxt, span: Span, tts: &[TokenTree]) -> Box<MacResult + 'cx> {
    let mut parser = ecx.new_parser_from_tts(&tts);
    match parse_define_store_action(ecx, span, &mut parser) {
        Ok(mac_result) => mac_result,
        Err(mut err) => {
            err.emit();
            DummyResult::any(span)
        }
    }
}
<|endoftext|>


<commit_before>use std::sync::{Mutex, Arc};
use std::net::{SocketAddr, ToSocketAddrs};
use std::f64::consts::PI;
use std::collections::VecDeque;
use opengl_graphics::GlGraphics;
use piston::input::{RenderArgs, UpdateArgs};

use std::{thread, time};
use std::net::TcpStream;
use network::{Command, Message};

use bincode::{serialize_into, deserialize_from, Infinite};

use state::WorldState;
use shapes::Unit;

pub struct NetworkClient {
    pub world_state: Arc<Mutex<WorldState>>,
    server_addr: SocketAddr,
    stream: Option<TcpStream>,
    commands: Arc<Mutex<VecDeque<Command>>>,
}

impl NetworkClient {
    pub fn new<T: ToSocketAddrs>(server_addrs: T, world_state:
                                 Arc<Mutex<WorldState>>,
                                 commands: Arc<Mutex<VecDeque<Command>>>) -> NetworkClient {
        let server_addr = server_addrs.to_socket_addrs().unwrap().next().unwrap();
        NetworkClient {
            world_state: world_state,
            server_addr: server_addr,
            stream: None,
            commands: commands,
        }
    }

    // todo: Maybe return client_id here? Would allow the application to reconnect...
    pub fn connect(&mut self) {
        let mut stream = TcpStream::connect(self.server_addr).unwrap();
        serialize_into(&mut stream, &Message::ClientHello, Infinite).unwrap();
        let server_hello = deserialize_from(&mut stream, Infinite);

        self.stream = Some(stream);
        if let Ok(Message::ServerHello(_, world_state)) = server_hello {
            let mut world_state_lock = self.world_state.lock().unwrap();
            *world_state_lock = world_state;
        } else {
            panic!("Could not connect to server");
        }
    }

    pub fn update(self) {
        let stream = self.stream.expect("Stream not here :(");
        let mut command_stream = stream.try_clone().unwrap();
        let commands = self.commands.clone();

        // Command sender loop
        thread::spawn(move || {
            loop {
                let command = {
                    let mut commands = commands.lock().unwrap();
                    commands.pop_front()
                };
                command.map(|cmd| {
                    println!("Got command: {:?}", cmd);
                    //let cmd = Message::Command(Command::Move(0.into(), [100f64, 100f64]));
                    serialize_into(&mut command_stream, &Message::Command(cmd), Infinite)
                        .map_err(|e|println!("Sending command failed: {}", e));
                });
                thread::sleep(time::Duration::from_millis(10));
            }
        });

        let mut game_state_stream = stream.try_clone().unwrap();
        let world_state = self.world_state.clone();
        thread::spawn(move || {
            loop {
                let game_state = deserialize_from(&mut game_state_stream,
                                                  Infinite);
                match game_state {
                    Ok(game) => {
                        //println!("{:?}", game);
                        let mut world_state_lock = world_state.lock().unwrap();
                        world_state_lock.game = game;

                    }
                    Err(e) => {
                        println!("{:?}", e);
                        thread::sleep(time::Duration::from_millis(200));
                    }
                }
            }
        });
    }
}

pub struct App {
    pub gl: GlGraphics, // OpenGL drawing backend.
    pub world_state: Arc<Mutex<WorldState>>,
    pub units: Vec<Unit>,
    pub commands: Arc<Mutex<VecDeque<Command>>>,
}

impl App {
    pub fn new(gl: GlGraphics) -> App {
        App {
            gl: gl,
            world_state: Arc::new(Mutex::new(WorldState::new(0, 0))),
            units: vec![],
            commands: Arc::new(Mutex::new(VecDeque::new())),
        }
    }

    pub fn select(&mut self, position: [f64;2]) {
        for u in &mut self.units {
            u.selected = u.is_hit(position);
        };
    }

    pub fn render(&mut self, args: &RenderArgs) {
        use graphics::{polygon, clear};
        use graphics::Transformed;
        use graphics::types::Polygon;

        const BLACK:  [f32; 4] = [0.0, 0.0,  0.0,  1.0];
        const YELLOW: [f32; 4] = [1.0, 1.0,  0.22, 1.0];
        const ORANGE: [f32; 4] = [1.0, 0.61, 0.22, 1.0];

        const FRONT_THICKNESS: f64 = 5.0;

        let units = &self.units;

        self.gl.draw(args.viewport(), |c, gl| {

            // Clear the screen.
            clear(BLACK, gl);

            for s in units.iter() {

                // Create a triangle polygon. The initial orientation is facing east.
                let triangle: Polygon = &s.get_shape();

                // Create a border on the front of the polygon. This is a trapezoid.
                // Because the angle of the trapezoid side is 22.5°, we know that `dx` is always `2 * dy`.
                let front: Polygon = &[
                    [s.size, s.size],                                           // Top right
                    [s.size, 0.0],                                                 // Bottom right
                    [s.size - FRONT_THICKNESS, FRONT_THICKNESS / 2.0],             // Bottom left
                    [s.size - FRONT_THICKNESS, s.size - FRONT_THICKNESS / 2.0], // Top left
                ];

                // Rotate the front to match the unit
                let transform_front = c.transform.trans(s.position[0], s.position[1])
                    .rot_rad(s.rotation)
                    .trans(-25.0, -25.0);

                // We don't need to apply any transformation to the units
                let transform_triangle = c.transform;

                // Draw the unit ORANGE if selected
                if s.selected {
                    polygon(ORANGE, triangle, transform_triangle, gl);
                    polygon(YELLOW, front, transform_front, gl);
                } else {
                    polygon(YELLOW, triangle, transform_triangle, gl);
                    polygon(ORANGE, front, transform_front, gl);
                }

            }
        });
    }

    pub fn update(&mut self, args: &UpdateArgs) {
        /*
        for s in &mut self.units {
            let diff = [s.target[0]-s.position[0], s.target[1]-s.position[1]];
            s.position[0] += diff[0]/2.0*args.dt;
            s.position[1] += diff[1]/2.0*args.dt;
        }
        */
    }

    pub fn move_selected(&mut self, position: [f64;2]) {
        for i in 0..self.units.len() {
            let s = &mut self.units[i];
            if s.selected {
                s.target = position;
                let dx = position[0] - s.position[0];
                let dy = position[1] - s.position[1];
                if dx.is_sign_negative() {
                    s.rotation = (dy / dx).atan() + PI;
                } else {
                    s.rotation = (dy / dx).atan();
                }
                let id = i as u32;
                let mut commands = self.commands.lock().unwrap();
                commands.push_back(Command::Move(id.into(), position));
                println!("dx: {}, dy: {}, new rotation: {}", dx, dy, s.rotation);
            }
        }
    }
}
<commit_msg>Fix remaining warnings<commit_after>use std::sync::{Mutex, Arc};
use std::net::{SocketAddr, ToSocketAddrs};
use std::f64::consts::PI;
use std::collections::VecDeque;
use opengl_graphics::GlGraphics;
use piston::input::{RenderArgs, UpdateArgs};

use std::{thread, time};
use std::net::TcpStream;
use network::{Command, Message};

use bincode::{serialize_into, deserialize_from, Infinite};

use state::WorldState;
use shapes::Unit;

pub struct NetworkClient {
    pub world_state: Arc<Mutex<WorldState>>,
    server_addr: SocketAddr,
    stream: Option<TcpStream>,
    commands: Arc<Mutex<VecDeque<Command>>>,
}

impl NetworkClient {
    pub fn new<T: ToSocketAddrs>(server_addrs: T, world_state:
                                 Arc<Mutex<WorldState>>,
                                 commands: Arc<Mutex<VecDeque<Command>>>) -> NetworkClient {
        let server_addr = server_addrs.to_socket_addrs().unwrap().next().unwrap();
        NetworkClient {
            world_state: world_state,
            server_addr: server_addr,
            stream: None,
            commands: commands,
        }
    }

    // todo: Maybe return client_id here? Would allow the application to reconnect...
    pub fn connect(&mut self) {
        let mut stream = TcpStream::connect(self.server_addr).unwrap();
        serialize_into(&mut stream, &Message::ClientHello, Infinite).unwrap();
        let server_hello = deserialize_from(&mut stream, Infinite);

        self.stream = Some(stream);
        if let Ok(Message::ServerHello(_, world_state)) = server_hello {
            let mut world_state_lock = self.world_state.lock().unwrap();
            *world_state_lock = world_state;
        } else {
            panic!("Could not connect to server");
        }
    }

    pub fn update(self) {
        let stream = self.stream.expect("Stream not here :(");
        let mut command_stream = stream.try_clone().unwrap();
        let commands = self.commands.clone();

        // Command sender loop
        thread::spawn(move || {
            loop {
                let command = {
                    let mut commands = commands.lock().unwrap();
                    commands.pop_front()
                };
                command.map(|cmd| {
                    println!("Got command: {:?}", cmd);
                    //let cmd = Message::Command(Command::Move(0.into(), [100f64, 100f64]));
                    serialize_into(&mut command_stream, &Message::Command(cmd), Infinite)
                        .unwrap_or_else(|e|println!("Sending command failed: {}", e));
                });
                thread::sleep(time::Duration::from_millis(10));
            }
        });

        let mut game_state_stream = stream.try_clone().unwrap();
        let world_state = self.world_state.clone();
        thread::spawn(move || {
            loop {
                let game_state = deserialize_from(&mut game_state_stream,
                                                  Infinite);
                match game_state {
                    Ok(game) => {
                        //println!("{:?}", game);
                        let mut world_state_lock = world_state.lock().unwrap();
                        world_state_lock.game = game;

                    }
                    Err(e) => {
                        println!("{:?}", e);
                        thread::sleep(time::Duration::from_millis(200));
                    }
                }
            }
        });
    }
}

pub struct App {
    pub gl: GlGraphics, // OpenGL drawing backend.
    pub world_state: Arc<Mutex<WorldState>>,
    pub units: Vec<Unit>,
    pub commands: Arc<Mutex<VecDeque<Command>>>,
}

impl App {
    pub fn new(gl: GlGraphics) -> App {
        App {
            gl: gl,
            world_state: Arc::new(Mutex::new(WorldState::new(0, 0))),
            units: vec![],
            commands: Arc::new(Mutex::new(VecDeque::new())),
        }
    }

    pub fn select(&mut self, position: [f64;2]) {
        for u in &mut self.units {
            u.selected = u.is_hit(position);
        };
    }

    pub fn render(&mut self, args: &RenderArgs) {
        use graphics::{polygon, clear};
        use graphics::Transformed;
        use graphics::types::Polygon;

        const BLACK:  [f32; 4] = [0.0, 0.0,  0.0,  1.0];
        const YELLOW: [f32; 4] = [1.0, 1.0,  0.22, 1.0];
        const ORANGE: [f32; 4] = [1.0, 0.61, 0.22, 1.0];

        const FRONT_THICKNESS: f64 = 5.0;

        let units = &self.units;

        self.gl.draw(args.viewport(), |c, gl| {

            // Clear the screen.
            clear(BLACK, gl);

            for s in units.iter() {

                // Create a triangle polygon. The initial orientation is facing east.
                let triangle: Polygon = &s.get_shape();

                // Create a border on the front of the polygon. This is a trapezoid.
                // Because the angle of the trapezoid side is 22.5°, we know that `dx` is always `2 * dy`.
                let front: Polygon = &[
                    [s.size, s.size],                                           // Top right
                    [s.size, 0.0],                                                 // Bottom right
                    [s.size - FRONT_THICKNESS, FRONT_THICKNESS / 2.0],             // Bottom left
                    [s.size - FRONT_THICKNESS, s.size - FRONT_THICKNESS / 2.0], // Top left
                ];

                // Rotate the front to match the unit
                let transform_front = c.transform.trans(s.position[0], s.position[1])
                    .rot_rad(s.rotation)
                    .trans(-25.0, -25.0);

                // We don't need to apply any transformation to the units
                let transform_triangle = c.transform;

                // Draw the unit ORANGE if selected
                if s.selected {
                    polygon(ORANGE, triangle, transform_triangle, gl);
                    polygon(YELLOW, front, transform_front, gl);
                } else {
                    polygon(YELLOW, triangle, transform_triangle, gl);
                    polygon(ORANGE, front, transform_front, gl);
                }

            }
        });
    }

    pub fn update(&mut self, _: &UpdateArgs) {
        /*
        for s in &mut self.units {
            let diff = [s.target[0]-s.position[0], s.target[1]-s.position[1]];
            s.position[0] += diff[0]/2.0*args.dt;
            s.position[1] += diff[1]/2.0*args.dt;
        }
        */
    }

    pub fn move_selected(&mut self, position: [f64;2]) {
        for i in 0..self.units.len() {
            let s = &mut self.units[i];
            if s.selected {
                s.target = position;
                let dx = position[0] - s.position[0];
                let dy = position[1] - s.position[1];
                if dx.is_sign_negative() {
                    s.rotation = (dy / dx).atan() + PI;
                } else {
                    s.rotation = (dy / dx).atan();
                }
                let id = i as u32;
                let mut commands = self.commands.lock().unwrap();
                commands.push_back(Command::Move(id.into(), position));
                println!("dx: {}, dy: {}, new rotation: {}", dx, dy, s.rotation);
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not
// distributed with this file, You can
// obtain one at
// http://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible
// With Secondary Licenses", as defined by
// the Mozilla Public License, v. 2.0.

use std::{str};
use std::ffi::{CStr, CString};
use std::thread;
use std::net::TcpStream;
use std::sync::mpsc::{channel, Sender, Receiver};

use super::libc::{c_int, c_char, uint8_t};
use super::simple_stream::bstream::Bstream;

/// This client's writer channel
static mut writer_tx: *mut Sender<Vec<u8>> = 0 as *mut Sender<Vec<u8>>;

/// This client's kill channel
static mut kill_tx: *mut Sender<()> = 0 as *mut Sender<()>;

#[no_mangle]
pub extern "C" fn hydrogen_start(address: *const c_char,
    data_handler: extern fn(*const uint8_t),
    on_connect_handler: extern fn(),
    on_disconnect_handler: extern fn()) -> c_int {

    trace!("Rust - start()");

    let mut r_address;
    unsafe {
        r_address = CStr::from_ptr(address);
    }
    let s_address = r_address.to_bytes();
    let host_address = match str::from_utf8(s_address) {
        Ok(safe_str) => safe_str,
        Err(_) => {
            error!("Invalid UTF-8");
            return -100 as c_int;
        }
    };

    // Create and register a way to kill this client
    let (k_tx, kill_rx): (Sender<()>, Receiver<()>) = channel();
    unsafe { kill_tx = &mut k_tx.clone(); }

    // Writer thread's channel
    let (w_tx, writer_rx): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = channel();
    unsafe { writer_tx = &mut w_tx.clone(); }

    debug!("Attempting connect to: {}", host_address);

    let result = TcpStream::connect(host_address);
    if result.is_err() {
        error!("Error connecting to {} - {}", host_address, result.unwrap_err());
        return -101 as c_int;
    }
    debug!("Connected");
    on_connect_handler();

    let stream = result.unwrap();
    let client = Bstream::new(stream);
    let r_client = client.clone();
    let w_client = client.clone();

    // Start the reader thread
    thread::Builder::new()
        .name("ReaderThread".to_string())
        .spawn(move||{
            reader_thread(r_client, data_handler)
        }).unwrap();

    // Start the writer thread
    thread::Builder::new()
        .name("WriterThread".to_string())
        .spawn(move||{
            writer_thread(writer_rx, w_client)
        }).unwrap();

    // Wait for the kill signal
    match kill_rx.recv() {
        Ok(_) => { }
        Err(e) => {
            error!("Error on kill channel: {}", e);
        }
    };
    on_disconnect_handler();

    // Exit out in standard C fashion
    0 as c_int
}

/// Writes the complete contents of buffer to the server
/// Returns -1 on error
#[no_mangle]
pub extern "C" fn hydrogen_write(buffer: *const uint8_t, len: usize) -> c_int {
    trace!("Rust.write");

    let n_buffer = unsafe { Vec::<u8>::from_raw_parts(buffer.offset(0) as *mut u8, len, len) };

    unsafe {
        match (*writer_tx).send(n_buffer) {
            Ok(_) => { }
            Err(e) => {
                warn!("Error sending buffer: {}", e);
                let _ = (*kill_tx).send(());
                return -1 as c_int;
            }
        };
    }

    0 as c_int
}

/// Forever listens to incoming data and when a complete message is received,
/// the passed callback is hit
fn reader_thread(client: Bstream, handler: extern fn(*const uint8_t)) {
    trace!("Rust.reader_thread started");

    let mut reader = client.clone();
    loop {
        match reader.read() {
            Ok(buffer) => {
                // Launch the handler in a new thread
                thread::Builder::new()
                    .name("Reader-Worker".to_string())
                    .spawn(move||{
                        handler(buffer.as_ptr());
                    }).unwrap();
            }
            Err(e) => {
                error!("Error: {}", e);
                break;
            }
        };
    }
    debug!("Rust.reader_thread finished");
    unsafe { let _ = (*kill_tx).send(()); }
}

/// Forever listens to Receiver<Vec<u8>> waiting on messages to come in
/// Once available, blocks until the entire message has been written
fn writer_thread(rx: Receiver<Vec<u8>>, client: Bstream) {
    trace!("Rust.writer_thread started");

    let mut writer = client.clone();
    loop {
        match rx.recv() {
            Ok(ref mut buffer) => {
                match writer.write(buffer) {
                    Ok(_) => { }
                    Err(e) => {
                        error!("Error: {}", e);
                        break;
                    }
                };
            }
            Err(e) => {
                error!("Error: {}", e);
                break;
            }
        };
    }

    debug!("Rust.writer_thread finished");
    unsafe { let _ = (*kill_tx).send(()); }
}

/// Drops the current connection and kills all current threads
#[no_mangle]
pub extern "C" fn hydrogen_kill() {
    unsafe { let _ = (*kill_tx).send(()); }
}
<commit_msg>Debugging statements<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not
// distributed with this file, You can
// obtain one at
// http://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible
// With Secondary Licenses", as defined by
// the Mozilla Public License, v. 2.0.

use std::{str};
use std::ffi::{CStr, CString};
use std::thread;
use std::net::TcpStream;
use std::sync::mpsc::{channel, Sender, Receiver};

use super::libc::{c_int, c_char, uint8_t};
use super::simple_stream::bstream::Bstream;

/// This client's writer channel
static mut writer_tx: *mut Sender<Vec<u8>> = 0 as *mut Sender<Vec<u8>>;

/// This client's kill channel
static mut kill_tx: *mut Sender<()> = 0 as *mut Sender<()>;

#[no_mangle]
pub extern "C" fn hydrogen_start(address: *const c_char,
    data_handler: extern fn(*const uint8_t, usize len),
    on_connect_handler: extern fn(),
    on_disconnect_handler: extern fn()) -> c_int {

    trace!("Rust - start()");

    let mut r_address;
    unsafe {
        r_address = CStr::from_ptr(address);
    }
    let s_address = r_address.to_bytes();
    let host_address = match str::from_utf8(s_address) {
        Ok(safe_str) => safe_str,
        Err(_) => {
            error!("Invalid UTF-8");
            return -100 as c_int;
        }
    };

    // Create and register a way to kill this client
    let (k_tx, kill_rx): (Sender<()>, Receiver<()>) = channel();
    unsafe { kill_tx = &mut k_tx.clone(); }

    // Writer thread's channel
    let (w_tx, writer_rx): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = channel();
    unsafe { writer_tx = &mut w_tx.clone(); }

    debug!("Attempting connect to: {}", host_address);

    let result = TcpStream::connect(host_address);
    if result.is_err() {
        error!("Error connecting to {} - {}", host_address, result.unwrap_err());
        return -101 as c_int;
    }
    debug!("Connected");
    on_connect_handler();

    let stream = result.unwrap();
    let client = Bstream::new(stream);
    let r_client = client.clone();
    let w_client = client.clone();

    // Start the reader thread
    thread::Builder::new()
        .name("ReaderThread".to_string())
        .spawn(move||{
            reader_thread(r_client, data_handler)
        }).unwrap();

    // Start the writer thread
    thread::Builder::new()
        .name("WriterThread".to_string())
        .spawn(move||{
            writer_thread(writer_rx, w_client)
        }).unwrap();

    // Wait for the kill signal
    match kill_rx.recv() {
        Ok(_) => { }
        Err(e) => {
            error!("Error on kill channel: {}", e);
        }
    };
    on_disconnect_handler();

    // Exit out in standard C fashion
    0 as c_int
}

/// Writes the complete contents of buffer to the server
/// Returns -1 on error
#[no_mangle]
pub extern "C" fn hydrogen_write(buffer: *const uint8_t, len: usize) -> c_int {
    trace!("Rust.write");

    let n_buffer = unsafe { Vec::<u8>::from_raw_parts(buffer.offset(0) as *mut u8, len, len) };

    unsafe {
        match (*writer_tx).send(n_buffer) {
            Ok(_) => { }
            Err(e) => {
                warn!("Error sending buffer: {}", e);
                let _ = (*kill_tx).send(());
                return -1 as c_int;
            }
        };
    }

    0 as c_int
}

/// Forever listens to incoming data and when a complete message is received,
/// the passed callback is hit
fn reader_thread(client: Bstream, handler: extern fn(*const uint8_t)) {
    trace!("Rust.reader_thread started");

    let mut reader = client.clone();
    loop {
        match reader.read() {
            Ok(buffer) => {
                // Launch the handler in a new thread
                thread::Builder::new()
                    .name("Reader-Worker".to_string())
                    .spawn(move||{
                        handler(buffer.as_ptr(), buffer.len());
                    }).unwrap();
            }
            Err(e) => {
                error!("Error: {}", e);
                break;
            }
        };
    }
    debug!("Rust.reader_thread finished");
    unsafe { let _ = (*kill_tx).send(()); }
}

/// Forever listens to Receiver<Vec<u8>> waiting on messages to come in
/// Once available, blocks until the entire message has been written
fn writer_thread(rx: Receiver<Vec<u8>>, client: Bstream) {
    trace!("Rust.writer_thread started");

    let mut writer = client.clone();
    loop {
        match rx.recv() {
            Ok(ref mut buffer) => {
                match writer.write(buffer) {
                    Ok(_) => { }
                    Err(e) => {
                        error!("Error: {}", e);
                        break;
                    }
                };
            }
            Err(e) => {
                error!("Error: {}", e);
                break;
            }
        };
    }

    debug!("Rust.writer_thread finished");
    unsafe { let _ = (*kill_tx).send(()); }
}

/// Drops the current connection and kills all current threads
#[no_mangle]
pub extern "C" fn hydrogen_kill() {
    unsafe { let _ = (*kill_tx).send(()); }
}
<|endoftext|>


<commit_before>#![allow(unused_variables)]

use block::Block;
use cocoa::base::{BOOL, id};
use cocoa::foundation::NSUInteger;
use libc::c_void;
use {MTLFeatureSet, MTLPipelineOption, MTLResourceOptions, MTLSize};

/// The `MTLDevice` protocol defines the interface to a single graphics processor (GPU). You use
/// an object that conforms to this protocol to query the capabilities of the processor and to
/// allocate objects used to access those capabilities.
///
/// Your app does not define classes that implement this protocol; it is used by Metal to provide
/// a device object to your app. To obtain a system device, call the `MTLCreateSystemDefaultDevice`
/// function or select a result from the `MTLCopyAllDevices` function.
///
/// Most objects in Metal that perform graphics rendering and computational work are associated
/// directly with a specific device. For example, texture objects are created by a device object
/// and can be used only with that device. Most methods on a `MTLDevice` object create non-transient
/// objects, including command queues, resources (such as buffers and textures), and pipeline
/// states. These objects can be expensive to create and you are encouraged to create them soon
/// after your app launches and reuse them throughout the lifetime of your app. Avoid creating these
/// objects in performance sensitive code.
pub trait MTLDevice {
    /// A Boolean value that indicates whether a device supports a packed depth/stencil buffer.
    /// (read-only)
    ///
    /// # Discussion
    ///
    /// If the value is `YES`, the device supports the `MTLPixelFormatDepth24Unorm_Stencil8` pixel
    /// format.
    unsafe fn depth24Stencil8PixelFormatSupported(self) -> BOOL;

    /// A Boolean value that indicates whether a device is configured as headless. (read-only)
    ///
    /// # Discussion
    ///
    /// If the value is `YES`, the device can not and does not have any displays attached.
    unsafe fn headless(self) -> BOOL;

    /// Boolean value that indicates whether a device is low-power. (read-only)
    ///
    /// # Discussion
    ///
    /// On multi-GPU systems that support automatic graphics switching, this property will return
    /// `YES` for the lower-power GPU.
    unsafe fn lowPower(self) -> BOOL;

    /// The maximum number of threads along each dimension of a threadgroup. (read-only)
    ///
    /// # Discussion
    ///
    /// This is the maximum compute grid size (width, height, depth) supported by the device.
    ///
    /// For more information on the specific capabilities of each feature set, see
    /// [Metal Programming Guide](https://developer.apple.com/library/prerelease/ios/documentation/
    ///     Miscellaneous/Conceptual/MetalProgrammingGuide/Introduction/
    ///     Introduction.html#//apple_ref/doc/uid/TP40014221
    /// ).
    unsafe fn maxThreadsPerGroup(self) -> MTLSize;

    /// A string that identifies the device. (read-only)
    ///
    /// # Discussion
    ///
    /// When this object is viewed in the Xcode debugger, its name is used to label the device.
    /// The name should only be used for informational purposes.
    unsafe fn name(self) -> id;

    /// Determines whether a device implements a particular feature set.
    ///
    /// # Parameters
    ///
    /// `featureSet` - A value that indicates the feature set you are interested in.
    ///
    /// # Return Value
    ///
    /// `YES` if the feature set is supported by the device; otherwise `NO`.
    ///
    /// # Discussion
    ///
    /// For more information on the specific capabilities of each feature set, see
    /// [Metal Programming Guide](https://developer.apple.com/library/prerelease/ios/documentation/
    ///     Miscellaneous/Conceptual/MetalProgrammingGuide/Introduction/
    ///     Introduction.html#//apple_ref/doc/uid/TP40014221
    /// ).
    unsafe fn supportsFeatureSet(self, featureSet: MTLFeatureSet) -> BOOL;

    /// Determines whether a device supports a given texture sample count.
    ///
    /// # Parameters
    ///
    /// `textureSampleCount` - The sample count you are interested in.
    ///
    /// # Return Value
    ///
    /// `YES` if the sample count is supported by the device; otherwise `NO`.
    ///
    /// # Discussion
    ///
    /// For more information on the specific capabilities of each feature set, see
    /// [Metal Programming Guide](https://developer.apple.com/library/prerelease/ios/documentation/
    ///     Miscellaneous/Conceptual/MetalProgrammingGuide/Introduction/
    ///     Introduction.html#//apple_ref/doc/uid/TP40014221
    /// ).
    unsafe fn supportsTextureSampleCount(self, textureSampleCount: NSUInteger) -> BOOL;

    unsafe fn newDefaultLibrary(self) -> id;
    unsafe fn newLibraryWithFile_error(self, filePath: id, error: *mut id) -> id;
    unsafe fn newLibraryWithSource_options_completionHandler(
        self, source: id, options: id, completionHandler: MTLNewLibraryCompletionHandler) -> id;

    #[cfg_attr(rustfmt, rustfmt_skip)] // This definition is too long to fit on one line
    unsafe fn newLibraryWithSource_options_error(self, source: id, options: id, error: *mut id)
                                                 -> id;
    unsafe fn newLibraryWithData_error(self, data: id, error: *mut id) -> id;

    unsafe fn newCommandQueue(self) -> id;

    #[cfg_attr(rustfmt, rustfmt_skip)] // This definition is too long to fit on one line
    unsafe fn newCommandQueueWithMaxCommandBufferCount(self, maxCommandBufferCount: NSUInteger)
                                                       -> id;

    unsafe fn newBufferWithLength_Options(self, length: NSUInteger, options: MTLResourceOptions) -> id;
    unsafe fn newBufferWithBytes_Length_Options(self, pointer: *mut c_void, length: NSUInteger,
                                                options: MTLResourceOptions)
                                                -> id;
    unsafe fn newBufferWithBytesNoCopy_length_options_deallocator(self, pointer: *mut c_void,
                                                                  length: NSUInteger,
                                                                  options: MTLResourceOptions,
                                                                  deallocator: Block<(*mut c_void,
                                                                                NSUInteger),
                                                                                ()>);

    unsafe fn newTextureWithDescriptor(self, descriptor: id) -> id;

    unsafe fn newSamplerStateWithDescriptor(self, descriptor: id) -> id;

    unsafe fn newStencilDepthStateWithDescriptor(self, descriptor: id) -> id;

    unsafe fn newRenderPipleineStateWithDescriptor_completionHandler(
            self, descriptor: id, completionHandler: MTLNewRenderPipleineStateCompletionHandler);

    unsafe fn newRenderPipelineStateWithDescriptor_options_completionHandler(
            self, descriptor: id, options: MTLPipelineOption,
            completionHandler: MTLNewRenderPipelineStateWithReflectionCompletionHandler);

    unsafe fn newRenderPipelineStateWithDescriptor_error(self, descriptor: id, error: id);

    unsafe fn newRenderPipelineStateWithDescriptor_options_reflection(self, descriptor: id,
                                                                      options: MTLPipelineOption,
                                                                      reflection: id, error: id);

    unsafe fn newComputePipelineStateWithFunction_completionHandler(
            self, function: id, completionHandler: MTLNewComputePipelineStateCompletionHandler);

    unsafe fn newComputePipelineStateWithFunction_options_completionHandler(
            self, function: id, options: MTLPipelineOption,
            completionHandler: MTLNewComputePipelineStateWithReflectionCompletionHandler);

    unsafe fn newComputePipelineStateWithFunction_error(self, function: id, error: id);

    unsafe fn newComputePipelineStateWithFunction_options_reflection_error(
            self, function: id, options: MTLPipelineOption, reflection: id, error: id);

    unsafe fn newComputePipelineStateWithDescriptor_options_completionHandler(
            self, descriptor: id, options: MTLPipelineOption,
            completionHandler: MTLNewComputePipelineStateWithReflectionCompletionHandler);

    unsafe fn newComputePipelineStateWithDescriptor_options_reflection_error(
            self, descriptor: id, options: MTLPipelineOption, reflection: id, error: id);
}

impl MTLDevice for id {
    unsafe fn depth24Stencil8PixelFormatSupported(self) -> BOOL {
        msg_send![self, isDepth24Stencil8PixelFormatSupported]
    }

    unsafe fn headless(self) -> BOOL {
        msg_send![self, isHeadless]
    }

    unsafe fn lowPower(self) -> BOOL {
        msg_send![self, isLowPower]
    }

    unsafe fn maxThreadsPerGroup(self) -> MTLSize {
        msg_send![self, maxThreadsPerThreadgroup]
    }

    unsafe fn name(self) -> id {
        msg_send![self, name]
    }

    unsafe fn supportsFeatureSet(self, featureSet: MTLFeatureSet) -> BOOL {
        msg_send![self, supportsFeatureSet:featureSet]
    }

    unsafe fn supportsTextureSampleCount(self, textureSampleCount: NSUInteger) -> BOOL {
        msg_send![self, supportsTextureSampleCount:textureSampleCount]
    }

    unsafe fn newDefaultLibrary(self) -> id {
        msg_send![self, newDefaultLibrary]
    }

    unsafe fn newLibraryWithFile_error(self, filePath: id, error: *mut id) -> id {
        msg_send![self, newLibraryWithFile:filePath error:error]
    }

    unsafe fn newLibraryWithSource_options_completionHandler(
        self, source: id, options: id, completionHandler: MTLNewLibraryCompletionHandler)
        -> id {
        msg_send![self, newLibraryWithSource:source options:options
                           completionHandler:completionHandler]
    }

    #[cfg_attr(rustfmt, rustfmt_skip)] // This definition is too long to fit on one line
    unsafe fn newLibraryWithSource_options_error(self, source: id, options: id, error: *mut id)
                                                 -> id {
        msg_send![self, newLibraryWithSource:source options:options error:error]
    }

    unsafe fn newLibraryWithData_error(self, data: id, error: *mut id) -> id {
        msg_send![self, newLibraryWithData:data error:error]
    }

    unsafe fn newCommandQueue(self) -> id {
        msg_send![self, newCommandQueue]
    }

    #[cfg_attr(rustfmt, rustfmt_skip)] // This definition is too long to fit on one line
    unsafe fn newCommandQueueWithMaxCommandBufferCount(self, maxCommandBufferCount: NSUInteger)
                                                       -> id {
        msg_send![self, newCommandQueueWithMaxCommandBufferCount:maxCommandBufferCount]
    }

    unsafe fn newBufferWithLength_Options(self, length: NSUInteger, options: MTLResourceOptions) -> id {
        msg_send![self, newBufferWithLength:length options:options]
    }

    unsafe fn newBufferWithBytes_Length_Options(self, pointer: *mut c_void, length: NSUInteger,
                                                options: MTLResourceOptions)
                                                -> id {
        msg_send![self, newBufferWithBytes:pointer length:length options:options]
    }

    unsafe fn newBufferWithBytesNoCopy_length_options_deallocator(self, pointer: *mut c_void,
                                                                  length: NSUInteger,
                                                                  options: MTLResourceOptions,
                                                                  deallocator: Block<(*mut c_void,
                                                                                NSUInteger),
                                                                                ()>) {
        msg_send![self, newBufferWithBytesNoCopy:pointer
                                          length:length
                                         options:options
                                     deallocator:deallocator]
    }

    unsafe fn newTextureWithDescriptor(self, descriptor: id) -> id {
        msg_send![self, newTextureWithDescriptor:descriptor]
    }

    unsafe fn newSamplerStateWithDescriptor(self, descriptor: id) -> id {
        msg_send![self, newSamplerStateWithDescriptor:descriptor]
    }

    unsafe fn newStencilDepthStateWithDescriptor(self, descriptor: id) -> id {
        msg_send![self, newStencilDepthStateWithDescriptor:descriptor]
    }

    unsafe fn newRenderPipleineStateWithDescriptor_completionHandler(
            self, descriptor: id,
            completionHandler: MTLNewRenderPipleineStateCompletionHandler) {
        msg_send![self, newRenderPipleineStateWithDescriptor:descriptor
                                           completionHandler:completionHandler]
    }

    unsafe fn newRenderPipelineStateWithDescriptor_options_completionHandler(
            self, descriptor: id, options: MTLPipelineOption,
            completionHandler: MTLNewRenderPipelineStateWithReflectionCompletionHandler) {
        msg_send![self, newRenderPipelineStateWithDescriptor:descriptor
                                                     options:options
                                           completionHandler:completionHandler]
    }

    unsafe fn newRenderPipelineStateWithDescriptor_error(self, descriptor: id, error: id) {
        msg_send![self, newRenderPipelineStateWithDescriptor:descriptor error:error]
    }

    unsafe fn newRenderPipelineStateWithDescriptor_options_reflection(self, descriptor: id,
                                                                      options: MTLPipelineOption,
                                                                      reflection: id, error: id) {
        msg_send![self, newRenderPipelineStateWithDescriptor:descriptor
                                                     options:options
                                                  reflection:reflection
                                                       error:error]
    }

    unsafe fn newComputePipelineStateWithFunction_completionHandler(
                  self,
                  function: id,
                  completionHandler: MTLNewComputePipelineStateCompletionHandler) {
        msg_send![self, newComputePipelineStateWithFunction:function
                                          completionHandler:completionHandler]
    }

    unsafe fn newComputePipelineStateWithFunction_options_completionHandler(
            self, function: id, options: MTLPipelineOption,
            completionHandler: MTLNewComputePipelineStateWithReflectionCompletionHandler) {
        msg_send![self, newComputePipelineStateWithFunction:function
                                                    options:options
                                          completionHandler:completionHandler]
    }

    unsafe fn newComputePipelineStateWithFunction_error(self, function: id, error: id) {
        msg_send![self, newComputePipelineStateWithFunction:function error:error]
    }

    unsafe fn newComputePipelineStateWithFunction_options_reflection_error(
            self, function: id, options: MTLPipelineOption, reflection: id, error: id) {
        msg_send![self, newComputePipelineStateWithFunction:function
                                                    options:options
                                                 reflection:reflection
                                                      error:error]
    }

    unsafe fn newComputePipelineStateWithDescriptor_options_completionHandler(
                   self,
                   descriptor: id,
                   options: MTLPipelineOption,
                   completionHandler: MTLNewComputePipelineStateWithReflectionCompletionHandler) {
        msg_send![self, newComputePipelineStateWithDescriptor:descriptor
                                                      options:options
                                            completionHandler:completionHandler]
    }
    unsafe fn newComputePipelineStateWithDescriptor_options_reflection_error(
            self, descriptor: id, options: MTLPipelineOption, reflection: id, error: id) {
        msg_send![self, newComputePipelineStateWithDescriptor:descriptor
                                                      options:options
                                                   reflection:reflection
                                                        error:error]
    }
}

pub type MTLNewLibraryCompletionHandler = Block<(id, id), ()>;
pub type MTLNewRenderPipleineStateCompletionHandler = Block<(id, id), ()>;
pub type MTLNewRenderPipelineStateWithReflectionCompletionHandler = Block<(id, id, id), ()>;
pub type MTLNewComputePipelineStateCompletionHandler = Block<(id, id), ()>;
pub type MTLNewComputePipelineStateWithReflectionCompletionHandler = Block<(id, id, id), ()>;
<commit_msg>Fix fn names<commit_after>#![allow(unused_variables)]

use block::Block;
use cocoa::base::{BOOL, id};
use cocoa::foundation::NSUInteger;
use libc::c_void;
use {MTLFeatureSet, MTLPipelineOption, MTLResourceOptions, MTLSize};

/// The `MTLDevice` protocol defines the interface to a single graphics processor (GPU). You use
/// an object that conforms to this protocol to query the capabilities of the processor and to
/// allocate objects used to access those capabilities.
///
/// Your app does not define classes that implement this protocol; it is used by Metal to provide
/// a device object to your app. To obtain a system device, call the `MTLCreateSystemDefaultDevice`
/// function or select a result from the `MTLCopyAllDevices` function.
///
/// Most objects in Metal that perform graphics rendering and computational work are associated
/// directly with a specific device. For example, texture objects are created by a device object
/// and can be used only with that device. Most methods on a `MTLDevice` object create non-transient
/// objects, including command queues, resources (such as buffers and textures), and pipeline
/// states. These objects can be expensive to create and you are encouraged to create them soon
/// after your app launches and reuse them throughout the lifetime of your app. Avoid creating these
/// objects in performance sensitive code.
pub trait MTLDevice {
    /// A Boolean value that indicates whether a device supports a packed depth/stencil buffer.
    /// (read-only)
    ///
    /// # Discussion
    ///
    /// If the value is `YES`, the device supports the `MTLPixelFormatDepth24Unorm_Stencil8` pixel
    /// format.
    unsafe fn depth24Stencil8PixelFormatSupported(self) -> BOOL;

    /// A Boolean value that indicates whether a device is configured as headless. (read-only)
    ///
    /// # Discussion
    ///
    /// If the value is `YES`, the device can not and does not have any displays attached.
    unsafe fn headless(self) -> BOOL;

    /// Boolean value that indicates whether a device is low-power. (read-only)
    ///
    /// # Discussion
    ///
    /// On multi-GPU systems that support automatic graphics switching, this property will return
    /// `YES` for the lower-power GPU.
    unsafe fn lowPower(self) -> BOOL;

    /// The maximum number of threads along each dimension of a threadgroup. (read-only)
    ///
    /// # Discussion
    ///
    /// This is the maximum compute grid size (width, height, depth) supported by the device.
    ///
    /// For more information on the specific capabilities of each feature set, see
    /// [Metal Programming Guide](https://developer.apple.com/library/prerelease/ios/documentation/
    ///     Miscellaneous/Conceptual/MetalProgrammingGuide/Introduction/
    ///     Introduction.html#//apple_ref/doc/uid/TP40014221
    /// ).
    unsafe fn maxThreadsPerGroup(self) -> MTLSize;

    /// A string that identifies the device. (read-only)
    ///
    /// # Discussion
    ///
    /// When this object is viewed in the Xcode debugger, its name is used to label the device.
    /// The name should only be used for informational purposes.
    unsafe fn name(self) -> id;

    /// Determines whether a device implements a particular feature set.
    ///
    /// # Parameters
    ///
    /// `featureSet` - A value that indicates the feature set you are interested in.
    ///
    /// # Return Value
    ///
    /// `YES` if the feature set is supported by the device; otherwise `NO`.
    ///
    /// # Discussion
    ///
    /// For more information on the specific capabilities of each feature set, see
    /// [Metal Programming Guide](https://developer.apple.com/library/prerelease/ios/documentation/
    ///     Miscellaneous/Conceptual/MetalProgrammingGuide/Introduction/
    ///     Introduction.html#//apple_ref/doc/uid/TP40014221
    /// ).
    unsafe fn supportsFeatureSet(self, featureSet: MTLFeatureSet) -> BOOL;

    /// Determines whether a device supports a given texture sample count.
    ///
    /// # Parameters
    ///
    /// `textureSampleCount` - The sample count you are interested in.
    ///
    /// # Return Value
    ///
    /// `YES` if the sample count is supported by the device; otherwise `NO`.
    ///
    /// # Discussion
    ///
    /// For more information on the specific capabilities of each feature set, see
    /// [Metal Programming Guide](https://developer.apple.com/library/prerelease/ios/documentation/
    ///     Miscellaneous/Conceptual/MetalProgrammingGuide/Introduction/
    ///     Introduction.html#//apple_ref/doc/uid/TP40014221
    /// ).
    unsafe fn supportsTextureSampleCount(self, textureSampleCount: NSUInteger) -> BOOL;

    unsafe fn newDefaultLibrary(self) -> id;
    unsafe fn newLibraryWithFile_error(self, filePath: id, error: *mut id) -> id;
    unsafe fn newLibraryWithSource_options_completionHandler(
        self, source: id, options: id, completionHandler: MTLNewLibraryCompletionHandler) -> id;

    #[cfg_attr(rustfmt, rustfmt_skip)] // This definition is too long to fit on one line
    unsafe fn newLibraryWithSource_options_error(self, source: id, options: id, error: *mut id)
                                                 -> id;
    unsafe fn newLibraryWithData_error(self, data: id, error: *mut id) -> id;

    unsafe fn newCommandQueue(self) -> id;

    #[cfg_attr(rustfmt, rustfmt_skip)] // This definition is too long to fit on one line
    unsafe fn newCommandQueueWithMaxCommandBufferCount(self, maxCommandBufferCount: NSUInteger)
                                                       -> id;

    unsafe fn newBufferWithLength_options(self, length: NSUInteger, options: MTLResourceOptions) -> id;
    unsafe fn newBufferWithBytes_length_options(self, pointer: *mut c_void, length: NSUInteger,
                                                options: MTLResourceOptions)
                                                -> id;
    unsafe fn newBufferWithBytesNoCopy_length_options_deallocator(self, pointer: *mut c_void,
                                                                  length: NSUInteger,
                                                                  options: MTLResourceOptions,
                                                                  deallocator: Block<(*mut c_void,
                                                                                NSUInteger),
                                                                                ()>);

    unsafe fn newTextureWithDescriptor(self, descriptor: id) -> id;

    unsafe fn newSamplerStateWithDescriptor(self, descriptor: id) -> id;

    unsafe fn newStencilDepthStateWithDescriptor(self, descriptor: id) -> id;

    unsafe fn newRenderPipleineStateWithDescriptor_completionHandler(
            self, descriptor: id, completionHandler: MTLNewRenderPipleineStateCompletionHandler);

    unsafe fn newRenderPipelineStateWithDescriptor_options_completionHandler(
            self, descriptor: id, options: MTLPipelineOption,
            completionHandler: MTLNewRenderPipelineStateWithReflectionCompletionHandler);

    unsafe fn newRenderPipelineStateWithDescriptor_error(self, descriptor: id, error: id);

    unsafe fn newRenderPipelineStateWithDescriptor_options_reflection(self, descriptor: id,
                                                                      options: MTLPipelineOption,
                                                                      reflection: id, error: id);

    unsafe fn newComputePipelineStateWithFunction_completionHandler(
            self, function: id, completionHandler: MTLNewComputePipelineStateCompletionHandler);

    unsafe fn newComputePipelineStateWithFunction_options_completionHandler(
            self, function: id, options: MTLPipelineOption,
            completionHandler: MTLNewComputePipelineStateWithReflectionCompletionHandler);

    unsafe fn newComputePipelineStateWithFunction_error(self, function: id, error: id);

    unsafe fn newComputePipelineStateWithFunction_options_reflection_error(
            self, function: id, options: MTLPipelineOption, reflection: id, error: id);

    unsafe fn newComputePipelineStateWithDescriptor_options_completionHandler(
            self, descriptor: id, options: MTLPipelineOption,
            completionHandler: MTLNewComputePipelineStateWithReflectionCompletionHandler);

    unsafe fn newComputePipelineStateWithDescriptor_options_reflection_error(
            self, descriptor: id, options: MTLPipelineOption, reflection: id, error: id);
}

impl MTLDevice for id {
    unsafe fn depth24Stencil8PixelFormatSupported(self) -> BOOL {
        msg_send![self, isDepth24Stencil8PixelFormatSupported]
    }

    unsafe fn headless(self) -> BOOL {
        msg_send![self, isHeadless]
    }

    unsafe fn lowPower(self) -> BOOL {
        msg_send![self, isLowPower]
    }

    unsafe fn maxThreadsPerGroup(self) -> MTLSize {
        msg_send![self, maxThreadsPerThreadgroup]
    }

    unsafe fn name(self) -> id {
        msg_send![self, name]
    }

    unsafe fn supportsFeatureSet(self, featureSet: MTLFeatureSet) -> BOOL {
        msg_send![self, supportsFeatureSet:featureSet]
    }

    unsafe fn supportsTextureSampleCount(self, textureSampleCount: NSUInteger) -> BOOL {
        msg_send![self, supportsTextureSampleCount:textureSampleCount]
    }

    unsafe fn newDefaultLibrary(self) -> id {
        msg_send![self, newDefaultLibrary]
    }

    unsafe fn newLibraryWithFile_error(self, filePath: id, error: *mut id) -> id {
        msg_send![self, newLibraryWithFile:filePath error:error]
    }

    unsafe fn newLibraryWithSource_options_completionHandler(
        self, source: id, options: id, completionHandler: MTLNewLibraryCompletionHandler)
        -> id {
        msg_send![self, newLibraryWithSource:source options:options
                           completionHandler:completionHandler]
    }

    #[cfg_attr(rustfmt, rustfmt_skip)] // This definition is too long to fit on one line
    unsafe fn newLibraryWithSource_options_error(self, source: id, options: id, error: *mut id)
                                                 -> id {
        msg_send![self, newLibraryWithSource:source options:options error:error]
    }

    unsafe fn newLibraryWithData_error(self, data: id, error: *mut id) -> id {
        msg_send![self, newLibraryWithData:data error:error]
    }

    unsafe fn newCommandQueue(self) -> id {
        msg_send![self, newCommandQueue]
    }

    #[cfg_attr(rustfmt, rustfmt_skip)] // This definition is too long to fit on one line
    unsafe fn newCommandQueueWithMaxCommandBufferCount(self, maxCommandBufferCount: NSUInteger)
                                                       -> id {
        msg_send![self, newCommandQueueWithMaxCommandBufferCount:maxCommandBufferCount]
    }

    unsafe fn newBufferWithLength_options(self, length: NSUInteger, options: MTLResourceOptions) -> id {
        msg_send![self, newBufferWithLength:length options:options]
    }

    unsafe fn newBufferWithBytes_length_options(self, pointer: *mut c_void, length: NSUInteger,
                                                options: MTLResourceOptions)
                                                -> id {
        msg_send![self, newBufferWithBytes:pointer length:length options:options]
    }

    unsafe fn newBufferWithBytesNoCopy_length_options_deallocator(self, pointer: *mut c_void,
                                                                  length: NSUInteger,
                                                                  options: MTLResourceOptions,
                                                                  deallocator: Block<(*mut c_void,
                                                                                NSUInteger),
                                                                                ()>) {
        msg_send![self, newBufferWithBytesNoCopy:pointer
                                          length:length
                                         options:options
                                     deallocator:deallocator]
    }

    unsafe fn newTextureWithDescriptor(self, descriptor: id) -> id {
        msg_send![self, newTextureWithDescriptor:descriptor]
    }

    unsafe fn newSamplerStateWithDescriptor(self, descriptor: id) -> id {
        msg_send![self, newSamplerStateWithDescriptor:descriptor]
    }

    unsafe fn newStencilDepthStateWithDescriptor(self, descriptor: id) -> id {
        msg_send![self, newStencilDepthStateWithDescriptor:descriptor]
    }

    unsafe fn newRenderPipleineStateWithDescriptor_completionHandler(
            self, descriptor: id,
            completionHandler: MTLNewRenderPipleineStateCompletionHandler) {
        msg_send![self, newRenderPipleineStateWithDescriptor:descriptor
                                           completionHandler:completionHandler]
    }

    unsafe fn newRenderPipelineStateWithDescriptor_options_completionHandler(
            self, descriptor: id, options: MTLPipelineOption,
            completionHandler: MTLNewRenderPipelineStateWithReflectionCompletionHandler) {
        msg_send![self, newRenderPipelineStateWithDescriptor:descriptor
                                                     options:options
                                           completionHandler:completionHandler]
    }

    unsafe fn newRenderPipelineStateWithDescriptor_error(self, descriptor: id, error: id) {
        msg_send![self, newRenderPipelineStateWithDescriptor:descriptor error:error]
    }

    unsafe fn newRenderPipelineStateWithDescriptor_options_reflection(self, descriptor: id,
                                                                      options: MTLPipelineOption,
                                                                      reflection: id, error: id) {
        msg_send![self, newRenderPipelineStateWithDescriptor:descriptor
                                                     options:options
                                                  reflection:reflection
                                                       error:error]
    }

    unsafe fn newComputePipelineStateWithFunction_completionHandler(
                  self,
                  function: id,
                  completionHandler: MTLNewComputePipelineStateCompletionHandler) {
        msg_send![self, newComputePipelineStateWithFunction:function
                                          completionHandler:completionHandler]
    }

    unsafe fn newComputePipelineStateWithFunction_options_completionHandler(
            self, function: id, options: MTLPipelineOption,
            completionHandler: MTLNewComputePipelineStateWithReflectionCompletionHandler) {
        msg_send![self, newComputePipelineStateWithFunction:function
                                                    options:options
                                          completionHandler:completionHandler]
    }

    unsafe fn newComputePipelineStateWithFunction_error(self, function: id, error: id) {
        msg_send![self, newComputePipelineStateWithFunction:function error:error]
    }

    unsafe fn newComputePipelineStateWithFunction_options_reflection_error(
            self, function: id, options: MTLPipelineOption, reflection: id, error: id) {
        msg_send![self, newComputePipelineStateWithFunction:function
                                                    options:options
                                                 reflection:reflection
                                                      error:error]
    }

    unsafe fn newComputePipelineStateWithDescriptor_options_completionHandler(
                   self,
                   descriptor: id,
                   options: MTLPipelineOption,
                   completionHandler: MTLNewComputePipelineStateWithReflectionCompletionHandler) {
        msg_send![self, newComputePipelineStateWithDescriptor:descriptor
                                                      options:options
                                            completionHandler:completionHandler]
    }
    unsafe fn newComputePipelineStateWithDescriptor_options_reflection_error(
            self, descriptor: id, options: MTLPipelineOption, reflection: id, error: id) {
        msg_send![self, newComputePipelineStateWithDescriptor:descriptor
                                                      options:options
                                                   reflection:reflection
                                                        error:error]
    }
}

pub type MTLNewLibraryCompletionHandler = Block<(id, id), ()>;
pub type MTLNewRenderPipleineStateCompletionHandler = Block<(id, id), ()>;
pub type MTLNewRenderPipelineStateWithReflectionCompletionHandler = Block<(id, id, id), ()>;
pub type MTLNewComputePipelineStateCompletionHandler = Block<(id, id), ()>;
pub type MTLNewComputePipelineStateWithReflectionCompletionHandler = Block<(id, id, id), ()>;
<|endoftext|>


<commit_before>// min-llvm-version: 12.0.0
// needs-llvm-components: aarch64 x86
// revisions:X64 A64
// assembly-output: emit-asm
// [X64] compile-flags: --target x86_64-unknown-linux-gnu -Crelocation-model=static
// [A64] compile-flags: --target aarch64-unknown-linux-gnu -Crelocation-model=static

#![feature(no_core, lang_items)]
#![no_core]
#![crate_type="rlib"]

#[lang="sized"]
trait Sized {}

#[lang="copy"]
trait Copy {}

impl Copy for u8 {}

extern "C" {
    fn chaenomeles();
}

// CHECK-LABEL: banana:
// x64: movb    chaenomeles, %{{[a,z]+}}
// A64:      adrp    [[REG:[a-z0-9]+]], chaenomeles
// A64-NEXT: ldrb    {{[a-z0-9]+}}, {{\[}}[[REG]], :lo12:chaenomeles]
#[no_mangle]
pub fn banana() -> u8 {
    unsafe {
        *(chaenomeles as *mut u8)
    }
}

// CHECK-LABEL: peach:
// x64: movb    banana, %{{[a,z]+}}
// A64:      adrp    [[REG2:[a-z0-9]+]], banana
// A64-NEXT: ldrb    {{[a-z0-9]+}}, {{\[}}[[REG2]], :lo12:banana]
#[no_mangle]
pub fn peach() -> u8 {
    unsafe {
        *(banana as *mut u8)
    }
}
<commit_msg>Fix assembly test from #83592<commit_after>// min-llvm-version: 12.0.0
// needs-llvm-components: aarch64 x86
// revisions:x64 A64
// assembly-output: emit-asm
// [x64] compile-flags: --target x86_64-unknown-linux-gnu -Crelocation-model=static
// [A64] compile-flags: --target aarch64-unknown-linux-gnu -Crelocation-model=static

#![feature(no_core, lang_items)]
#![no_core]
#![crate_type="rlib"]

#[lang="sized"]
trait Sized {}

#[lang="copy"]
trait Copy {}

impl Copy for u8 {}

extern "C" {
    fn chaenomeles();
}

// CHECK-LABEL: banana:
// x64: movb   chaenomeles{{(\(%[a-z0-9]+\))?}}, %{{[a-z0-9]+}}
// A64:      adrp    [[REG:[a-z0-9]+]], chaenomeles
// A64-NEXT: ldrb    {{[a-z0-9]+}}, {{\[}}[[REG]], :lo12:chaenomeles]
#[no_mangle]
pub fn banana() -> u8 {
    unsafe {
        *(chaenomeles as *mut u8)
    }
}

// CHECK-LABEL: peach:
// x64: movb    banana{{(\(%[a-z0-9]+\))?}}, %{{[a-z0-9]+}}
// A64:      adrp    [[REG2:[a-z0-9]+]], banana
// A64-NEXT: ldrb    {{[a-z0-9]+}}, {{\[}}[[REG2]], :lo12:banana]
#[no_mangle]
pub fn peach() -> u8 {
    unsafe {
        *(banana as *mut u8)
    }
}
<|endoftext|>