<commit_before>use gl;
use gl::types::*;
use types::{Color, Viewport, Capability, GLError};
use buffer::{ArrayBufferBinder, ElementArrayBufferBinder};
use program::{ProgramBinder, ProgramAttrib};
use framebuffer::FramebufferBinder;
use renderbuffer::RenderbufferBinder;
use texture_units::TextureUnits;

pub type Context = ContextOf<ArrayBufferBinder,
                             ElementArrayBufferBinder,
                             ProgramBinder,
                             FramebufferBinder,
                             RenderbufferBinder,
                             TextureUnits>;

pub struct ContextOf<AB, EAB, P, FB, RB, TU> {
    pub array_buffer: AB,
    pub element_array_buffer: EAB,
    pub program: P,
    pub framebuffer: FB,
    pub renderbuffer: RB,
    pub tex_units: TU
}

impl Context {
    pub unsafe fn current_context() -> Self {
        Context {
            array_buffer: ArrayBufferBinder,
            element_array_buffer: ElementArrayBufferBinder,
            program: ProgramBinder,
            framebuffer: FramebufferBinder,
            renderbuffer: RenderbufferBinder,
            tex_units: TextureUnits::current()
        }
    }

    pub fn clear_color(&mut self, color: Color) {
        unsafe {
            gl::ClearColor(color.r, color.g, color.b, color.a);
        }
    }

    pub fn enable(&mut self, cap: Capability) {
        unsafe {
            gl::Enable(cap.gl_enum());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`cap` is not a valid OpenGL capability",
                _ => "Unknown error"
            }
        }
    }

    pub fn disable(&mut self, cap: Capability) {
        unsafe {
            gl::Disable(cap.gl_enum());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`cap` is not a valid OpenGL capability",
                _ => "Unknown error"
            }
        }
    }

    pub fn enable_vertex_attrib_array(&self, attrib: ProgramAttrib) {
        unsafe {
            gl::EnableVertexAttribArray(attrib.gl_index);
            dbg_gl_error! {
                GLError::InvalidValue => "`index` is >= GL_MAX_VERTEX_ATTRIBS",
                _ => "Unknown error"
            }
        }
    }

    pub fn viewport(&self, viewport: Viewport) {
        unsafe {
            gl::Viewport(viewport.x as GLint,
                         viewport.y as GLint,
                         viewport.width as GLsizei,
                         viewport.height as GLsizei);
            dbg_gl_sanity_check! {
                GLError::InvalidValue => "`width` or `height` is negative",
                _ => "Unknown error"
            }
        }
    }

    pub fn get_error() -> Option<GLError> {
        unsafe {
            match gl::GetError() {
                gl::INVALID_ENUM =>
                    Some(GLError::InvalidEnum),
                gl::INVALID_VALUE =>
                    Some(GLError::InvalidValue),
                gl::INVALID_OPERATION =>
                    Some(GLError::InvalidOperation),
                gl::INVALID_FRAMEBUFFER_OPERATION =>
                    Some(GLError::InvalidFramebufferOperation),
                gl::OUT_OF_MEMORY =>
                    Some(GLError::OutOfMemory),
                _ =>
                    None
            }
        }
    }
}

#[macro_export]
macro_rules! bind_array_buffer {
    ($gl:expr, $buffer:expr) => {
        $gl.array_buffer.bind($buffer)
    }
}

#[macro_export]
macro_rules! bind_element_array_buffer {
    ($gl:expr, $buffer:expr) => {
        $gl.element_array_buffer.bind($buffer)
    }
}

#[macro_export]
macro_rules! use_program {
    ($gl:expr, $program:expr) => {
        $gl.program.bind($program)
    }
}

#[macro_export]
macro_rules! bind_framebuffer {
    ($gl:expr, $fbo:expr) => {
        $gl.framebuffer.bind($fbo)
    }
}

#[macro_export]
macro_rules! current_framebuffer_binding {
    ($gl:expr) => {
        $gl.framebuffer.current_binding()
    }
}

#[macro_export]
macro_rules! bind_renderbuffer {
    ($gl:expr, $renderbuffer:expr) => {
        $gl.renderbuffer.bind($renderbuffer)
    }
}

// HACK: Workaround for issue described here:
// https://www.reddit.com/r/rust/comments/339yj3/tuple_indexing_in_a_macro/cqiyv4n
#[macro_export]
macro_rules! _glitter_expr {
    ($x:expr) => ($x)
}

#[macro_export]
macro_rules! active_texture {
    ($gl:expr, $idx:tt) => {
        _glitter_expr!($gl.tex_units.$idx.active())
    }
}

#[macro_export]
macro_rules! active_texture_n {
    ($gl:expr, $idx:expr) => {
        $gl.tex_units.nth_unit($idx).active()
    }
}
<commit_msg>Add `ContextOf.split_*()` methods<commit_after>use std::borrow::{Borrow, BorrowMut};
use gl;
use gl::types::*;
use types::{Color, Viewport, Capability, GLError};
use buffer::{ArrayBufferBinder, ElementArrayBufferBinder};
use program::{ProgramBinder, ProgramAttrib};
use framebuffer::FramebufferBinder;
use renderbuffer::RenderbufferBinder;
use texture_units::TextureUnits;

pub type Context = ContextOf<ArrayBufferBinder,
                             ElementArrayBufferBinder,
                             ProgramBinder,
                             FramebufferBinder,
                             RenderbufferBinder,
                             TextureUnits>;

pub struct ContextOf<AB, EAB, P, FB, RB, TU> {
    pub array_buffer: AB,
    pub element_array_buffer: EAB,
    pub program: P,
    pub framebuffer: FB,
    pub renderbuffer: RB,
    pub tex_units: TU
}

impl<AB, EAB, P, FB, RB, TU> ContextOf<AB, EAB, P, FB, RB, TU> {
    pub unsafe fn current_context() -> Context {
        Context {
            array_buffer: ArrayBufferBinder,
            element_array_buffer: ElementArrayBufferBinder,
            program: ProgramBinder,
            framebuffer: FramebufferBinder,
            renderbuffer: RenderbufferBinder,
            tex_units: TextureUnits::current()
        }
    }

    pub fn clear_color(&mut self, color: Color) {
        unsafe {
            gl::ClearColor(color.r, color.g, color.b, color.a);
        }
    }

    pub fn enable(&mut self, cap: Capability) {
        unsafe {
            gl::Enable(cap.gl_enum());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`cap` is not a valid OpenGL capability",
                _ => "Unknown error"
            }
        }
    }

    pub fn disable(&mut self, cap: Capability) {
        unsafe {
            gl::Disable(cap.gl_enum());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`cap` is not a valid OpenGL capability",
                _ => "Unknown error"
            }
        }
    }

    pub fn enable_vertex_attrib_array(&self, attrib: ProgramAttrib) {
        unsafe {
            gl::EnableVertexAttribArray(attrib.gl_index);
            dbg_gl_error! {
                GLError::InvalidValue => "`index` is >= GL_MAX_VERTEX_ATTRIBS",
                _ => "Unknown error"
            }
        }
    }

    pub fn viewport(&self, viewport: Viewport) {
        unsafe {
            gl::Viewport(viewport.x as GLint,
                         viewport.y as GLint,
                         viewport.width as GLsizei,
                         viewport.height as GLsizei);
            dbg_gl_sanity_check! {
                GLError::InvalidValue => "`width` or `height` is negative",
                _ => "Unknown error"
            }
        }
    }

    pub fn get_error() -> Option<GLError> {
        unsafe {
            match gl::GetError() {
                gl::INVALID_ENUM =>
                    Some(GLError::InvalidEnum),
                gl::INVALID_VALUE =>
                    Some(GLError::InvalidValue),
                gl::INVALID_OPERATION =>
                    Some(GLError::InvalidOperation),
                gl::INVALID_FRAMEBUFFER_OPERATION =>
                    Some(GLError::InvalidFramebufferOperation),
                gl::OUT_OF_MEMORY =>
                    Some(GLError::OutOfMemory),
                _ =>
                    None
            }
        }
    }

    pub fn split_array_buffer<'a>(&'a self)
        -> (
            &'a ArrayBufferBinder,
            ContextOf<(), &'a EAB, &'a P, &'a FB, &'a RB, &'a TU>
        )
        where AB: Borrow<ArrayBufferBinder>
    {
        (
            self.array_buffer.borrow(),
            ContextOf {
                array_buffer: (),
                element_array_buffer: &self.element_array_buffer,
                program: &self.program,
                framebuffer: &self.framebuffer,
                renderbuffer: &self.renderbuffer,
                tex_units: &self.tex_units
            }
        )
    }

    pub fn split_array_buffer_mut<'a>(&'a mut self)
        -> (
            &'a mut ArrayBufferBinder,
            ContextOf<(),
                      &'a mut EAB,
                      &'a mut P,
                      &'a mut FB,
                      &'a mut RB,
                      &'a mut TU>
        )
        where AB: BorrowMut<ArrayBufferBinder>
    {
        (
            self.array_buffer.borrow_mut(),
            ContextOf {
                array_buffer: (),
                element_array_buffer: &mut self.element_array_buffer,
                program: &mut self.program,
                framebuffer: &mut self.framebuffer,
                renderbuffer: &mut self.renderbuffer,
                tex_units: &mut self.tex_units
            }
        )
    }

    pub fn split_element_array_buffer<'a>(&'a self)
        -> (
            &'a ElementArrayBufferBinder,
            ContextOf<&'a AB, (), &'a P, &'a FB, &'a RB, &'a TU>
        )
        where EAB: Borrow<ElementArrayBufferBinder>
    {
        (
            self.element_array_buffer.borrow(),
            ContextOf {
                array_buffer: &self.array_buffer,
                element_array_buffer: (),
                program: &self.program,
                framebuffer: &self.framebuffer,
                renderbuffer: &self.renderbuffer,
                tex_units: &self.tex_units
            }
        )
    }

    pub fn split_element_array_buffer_mut<'a>(&'a mut self)
        -> (
            &'a mut ElementArrayBufferBinder,
            ContextOf<&'a mut AB,
                      (),
                      &'a mut P,
                      &'a mut FB,
                      &'a mut RB,
                      &'a mut TU>
        )
        where EAB: BorrowMut<ElementArrayBufferBinder>
    {
        (
            self.element_array_buffer.borrow_mut(),
            ContextOf {
                array_buffer: &mut self.array_buffer,
                element_array_buffer: (),
                program: &mut self.program,
                framebuffer: &mut self.framebuffer,
                renderbuffer: &mut self.renderbuffer,
                tex_units: &mut self.tex_units
            }
        )
    }

    pub fn split_program<'a>(&'a self)
        -> (
            &'a ProgramBinder,
            ContextOf<&'a AB, &'a EAB, (), &'a FB, &'a RB, &'a TU>
        )
        where P: Borrow<ProgramBinder>
    {
        (
            self.program.borrow(),
            ContextOf {
                array_buffer: &self.array_buffer,
                element_array_buffer: &self.element_array_buffer,
                program: (),
                framebuffer: &self.framebuffer,
                renderbuffer: &self.renderbuffer,
                tex_units: &self.tex_units
            }
        )
    }

    pub fn split_program_mut<'a>(&'a mut self)
        -> (
            &'a mut ProgramBinder,
            ContextOf<&'a mut AB,
                      &'a mut EAB,
                      (),
                      &'a mut FB,
                      &'a mut RB,
                      &'a mut TU>
        )
        where P: BorrowMut<ProgramBinder>
    {
        (
            self.program.borrow_mut(),
            ContextOf {
                array_buffer: &mut self.array_buffer,
                element_array_buffer: &mut self.element_array_buffer,
                program: (),
                framebuffer: &mut self.framebuffer,
                renderbuffer: &mut self.renderbuffer,
                tex_units: &mut self.tex_units
            }
        )
    }

    pub fn split_framebuffer<'a>(&'a self)
        -> (
            &'a FramebufferBinder,
            ContextOf<&'a AB, &'a EAB, &'a P, (), &'a RB, &'a TU>
        )
        where FB: Borrow<FramebufferBinder>
    {
        (
            self.framebuffer.borrow(),
            ContextOf {
                array_buffer: &self.array_buffer,
                element_array_buffer: &self.element_array_buffer,
                program: &self.program,
                framebuffer: (),
                renderbuffer: &self.renderbuffer,
                tex_units: &self.tex_units
            }
        )
    }

    pub fn split_framebuffer_mut<'a>(&'a mut self)
        -> (
            &'a mut FramebufferBinder,
            ContextOf<&'a mut AB,
                      &'a mut EAB,
                      &'a mut P,
                      (),
                      &'a mut RB,
                      &'a mut TU>
        )
        where FB: BorrowMut<FramebufferBinder>
    {
        (
            self.framebuffer.borrow_mut(),
            ContextOf {
                array_buffer: &mut self.array_buffer,
                element_array_buffer: &mut self.element_array_buffer,
                program: &mut self.program,
                framebuffer: (),
                renderbuffer: &mut self.renderbuffer,
                tex_units: &mut self.tex_units
            }
        )
    }

    pub fn split_renderbuffer<'a>(&'a self)
        -> (
            &'a RenderbufferBinder,
            ContextOf<&'a AB, &'a EAB, &'a P, &'a FB, (), &'a TU>
        )
        where RB: Borrow<RenderbufferBinder>
    {
        (
            self.renderbuffer.borrow(),
            ContextOf {
                array_buffer: &self.array_buffer,
                element_array_buffer: &self.element_array_buffer,
                program: &self.program,
                framebuffer: &self.framebuffer,
                renderbuffer: (),
                tex_units: &self.tex_units
            }
        )
    }

    pub fn split_renderbuffer_mut<'a>(&'a mut self)
        -> (
            &'a mut RenderbufferBinder,
            ContextOf<&'a mut AB,
                      &'a mut EAB,
                      &'a mut P,
                      &'a mut FB,
                      (),
                      &'a mut TU>
        )
        where RB: BorrowMut<RenderbufferBinder>
    {
        (
            self.renderbuffer.borrow_mut(),
            ContextOf {
                array_buffer: &mut self.array_buffer,
                element_array_buffer: &mut self.element_array_buffer,
                program: &mut self.program,
                framebuffer: &mut self.framebuffer,
                renderbuffer: (),
                tex_units: &mut self.tex_units
            }
        )
    }

    pub fn split_tex_units<'a>(&'a self)
        -> (
            &'a TextureUnits,
            ContextOf<&'a AB, &'a EAB, &'a P, &'a FB, &'a RB, ()>
        )
        where TU: Borrow<TextureUnits>
    {
        (
            self.tex_units.borrow(),
            ContextOf {
                array_buffer: &self.array_buffer,
                element_array_buffer: &self.element_array_buffer,
                program: &self.program,
                framebuffer: &self.framebuffer,
                renderbuffer: &self.renderbuffer,
                tex_units: ()
            }
        )
    }

    pub fn split_tex_units_mut<'a>(&'a mut self)
        -> (
            &'a mut TextureUnits,
            ContextOf<&'a mut AB,
                      &'a mut EAB,
                      &'a mut P,
                      &'a mut FB,
                      &'a mut RB,
                      ()>
        )
        where TU: BorrowMut<TextureUnits>
    {
        (
            self.tex_units.borrow_mut(),
            ContextOf {
                array_buffer: &mut self.array_buffer,
                element_array_buffer: &mut self.element_array_buffer,
                program: &mut self.program,
                framebuffer: &mut self.framebuffer,
                renderbuffer: &mut self.renderbuffer,
                tex_units: ()
            }
        )
    }
}

#[macro_export]
macro_rules! bind_array_buffer {
    ($gl:expr, $buffer:expr) => {
        $gl.array_buffer.bind($buffer)
    }
}

#[macro_export]
macro_rules! bind_element_array_buffer {
    ($gl:expr, $buffer:expr) => {
        $gl.element_array_buffer.bind($buffer)
    }
}

#[macro_export]
macro_rules! use_program {
    ($gl:expr, $program:expr) => {
        $gl.program.bind($program)
    }
}

#[macro_export]
macro_rules! bind_framebuffer {
    ($gl:expr, $fbo:expr) => {
        $gl.framebuffer.bind($fbo)
    }
}

#[macro_export]
macro_rules! current_framebuffer_binding {
    ($gl:expr) => {
        $gl.framebuffer.current_binding()
    }
}

#[macro_export]
macro_rules! bind_renderbuffer {
    ($gl:expr, $renderbuffer:expr) => {
        $gl.renderbuffer.bind($renderbuffer)
    }
}

// HACK: Workaround for issue described here:
// https://www.reddit.com/r/rust/comments/339yj3/tuple_indexing_in_a_macro/cqiyv4n
#[macro_export]
macro_rules! _glitter_expr {
    ($x:expr) => ($x)
}

#[macro_export]
macro_rules! active_texture {
    ($gl:expr, $idx:tt) => {
        _glitter_expr!($gl.tex_units.$idx.active())
    }
}

#[macro_export]
macro_rules! active_texture_n {
    ($gl:expr, $idx:expr) => {
        $gl.tex_units.nth_unit($idx).active()
    }
}
<|endoftext|>


<commit_before>use raw::*;
use std::mem;
use std::ptr;
use std::kinds::marker::{ContravariantLifetime, NoCopy, NoSync, NoSend};
use util::{from_ptr, NativeRef};
use {AnyFunction, CompiledFunction, Type, UncompiledFunction};
/// Holds all of the functions you have built and compiled. There can be
/// multiple, but normally there is only one.
pub struct Context {
    _context: jit_context_t
}
native_ref!(Context, _context, jit_context_t);

/// A context that is in the build phase while generating IR
pub struct Builder {
    _context: jit_context_t,
    no_sync: NoSync,
    no_send: NoSend,
    no_copy: NoCopy
}
impl NativeRef for Builder {
    #[inline(always)]
    unsafe fn as_ptr(&self) -> jit_context_t {
        self._context
    }
    #[inline(always)]
    unsafe fn from_ptr(ptr:jit_context_t) -> Builder {
        Builder {
            _context: ptr,
            no_sync: NoSync,
            no_send: NoSend,
            no_copy: NoCopy
        }
    }
}

impl Context {
    unsafe fn as_builder(&mut self) -> Builder {
        from_ptr(self.as_ptr())
    }
    #[inline(always)]
    /// Create a new JIT Context
    pub fn new() -> Context {
        unsafe {
            //let handle_exception:extern fn(i32) -> *mut c_void = ::handle_exception;
            //jit_exception_set_handler(Some(handle_exception));
            from_ptr(jit_context_create())
        }
    }
    #[inline(always)]
    /// Lock the context so you can safely generate IR
    pub fn build<R, F:FnOnce(&Builder) -> R>(&mut self, cb: F) -> R {
        unsafe {
            jit_context_build_start(self.as_ptr());
            let r = cb(&self.as_builder());
            jit_context_build_end(self.as_ptr());
            r
        }
    }
    #[inline(always)]
    /// Lock the context so you can safely generate IR in a new function on the context which is
    /// compiled for you
    pub fn build_func<'a, F:FnOnce(&UncompiledFunction<'a>)>(&'a mut self, signature: Type, cb: F) -> CompiledFunction<'a> {
        unsafe {
            jit_context_build_start(self.as_ptr());
            let builder = self.as_builder();
            let func = UncompiledFunction::new(mem::copy_lifetime(self, &builder), signature.clone());
            cb(&func);
            jit_context_build_end(self.as_ptr());
            func.compile()
        }
    }
    /// Iterate through the functions contained inside this context
    pub fn functions<'a>(&'a self) -> Functions<'a> {
        unsafe {
            Functions {
                context: self.as_ptr(),
                last: ptr::null_mut(),
                lifetime: ContravariantLifetime::<'a>
            }
        }
    }
}
#[unsafe_destructor]
impl Drop for Context {
    #[inline(always)]
    fn drop(&mut self) {
        unsafe {
            jit_context_destroy(self.as_ptr());
        }
    }
}

pub struct Functions<'a> {
    context: jit_context_t,
    last: jit_function_t,
    lifetime: ContravariantLifetime<'a>
}
impl<'a> Iterator<AnyFunction<'a>> for Functions<'a> {
    fn next(&mut self) -> Option<AnyFunction<'a>> {
        unsafe {
            self.last = jit_function_next(self.context, self.last);
            from_ptr(self.last)
        }
    }
}<commit_msg>Fully remove old exception handling code<commit_after>use raw::*;
use std::mem;
use std::ptr;
use std::kinds::marker::{ContravariantLifetime, NoCopy, NoSync, NoSend};
use util::{from_ptr, NativeRef};
use {AnyFunction, CompiledFunction, Type, UncompiledFunction};
/// Holds all of the functions you have built and compiled. There can be
/// multiple, but normally there is only one.
pub struct Context {
    _context: jit_context_t
}
native_ref!(Context, _context, jit_context_t);

/// A context that is in the build phase while generating IR
pub struct Builder {
    _context: jit_context_t,
    no_sync: NoSync,
    no_send: NoSend,
    no_copy: NoCopy
}
impl NativeRef for Builder {
    #[inline(always)]
    unsafe fn as_ptr(&self) -> jit_context_t {
        self._context
    }
    #[inline(always)]
    unsafe fn from_ptr(ptr:jit_context_t) -> Builder {
        Builder {
            _context: ptr,
            no_sync: NoSync,
            no_send: NoSend,
            no_copy: NoCopy
        }
    }
}

impl Context {
    unsafe fn as_builder(&mut self) -> Builder {
        from_ptr(self.as_ptr())
    }
    #[inline(always)]
    /// Create a new JIT Context
    pub fn new() -> Context {
        unsafe {
            from_ptr(jit_context_create())
        }
    }
    #[inline(always)]
    /// Lock the context so you can safely generate IR
    pub fn build<R, F:FnOnce(&Builder) -> R>(&mut self, cb: F) -> R {
        unsafe {
            jit_context_build_start(self.as_ptr());
            let r = cb(&self.as_builder());
            jit_context_build_end(self.as_ptr());
            r
        }
    }
    #[inline(always)]
    /// Lock the context so you can safely generate IR in a new function on the context which is
    /// compiled for you
    pub fn build_func<'a, F:FnOnce(&UncompiledFunction<'a>)>(&'a mut self, signature: Type, cb: F) -> CompiledFunction<'a> {
        unsafe {
            jit_context_build_start(self.as_ptr());
            let builder = self.as_builder();
            let func = UncompiledFunction::new(mem::copy_lifetime(self, &builder), signature.clone());
            cb(&func);
            jit_context_build_end(self.as_ptr());
            func.compile()
        }
    }
    /// Iterate through the functions contained inside this context
    pub fn functions<'a>(&'a self) -> Functions<'a> {
        unsafe {
            Functions {
                context: self.as_ptr(),
                last: ptr::null_mut(),
                lifetime: ContravariantLifetime::<'a>
            }
        }
    }
}
#[unsafe_destructor]
impl Drop for Context {
    #[inline(always)]
    fn drop(&mut self) {
        unsafe {
            jit_context_destroy(self.as_ptr());
        }
    }
}

pub struct Functions<'a> {
    context: jit_context_t,
    last: jit_function_t,
    lifetime: ContravariantLifetime<'a>
}
impl<'a> Iterator<AnyFunction<'a>> for Functions<'a> {
    fn next(&mut self) -> Option<AnyFunction<'a>> {
        unsafe {
            self.last = jit_function_next(self.context, self.last);
            from_ptr(self.last)
        }
    }
}<|endoftext|>


<commit_before>use super::super::interconnect;
use super::cp0::cp0;

const NUM_GPR: usize = 32;

#[derive(Debug)]
pub struct Cpu {
    reg_gpr: [u64; NUM_GPR],
    reg_fpr: [f64; NUM_GPR],

    reg_pc: u64,

    reg_hi: u64,
    reg_lo: u64,

    reg_llbit: bool, // TODO: Enum type

    reg_fcr0: u32,
    reg_fcr31: u32,

    cp0: cp0::Cp0,

    interconnect: interconnect::Interconnect
}

impl Cpu {
    pub fn new(interconnect: interconnect::Interconnect) -> Cpu {
        Cpu {
            reg_gpr: [0; NUM_GPR],
            reg_fpr: [0.0; NUM_GPR],

            reg_pc: 0,

            reg_hi: 0,
            reg_lo: 0,

            reg_llbit: false,

            reg_fcr0: 0,
            reg_fcr31: 0,

            cp0: cp0::Cp0::default(),

            interconnect: interconnect
        }
    }

    pub fn power_on_reset(&mut self) {
        self.cp0.power_on_reset();

        self.reg_pc = 0xffff_ffff_bfc0_0000; // TODO: Move to const
    }

    // TODO: Different interface
    pub fn run(&mut self) {
        loop {
            self.run_instruction();
        }
    }

    pub fn run_instruction(&mut self) {
        let instruction = self.read_word(self.reg_pc);

        let opcode = (instruction >> 26) & 0b111111;
        let rt = (instruction >> 16) & 0b11111;

        match opcode {
            0b001111 => {
                // Lui
                let imm = instruction & 0xffff;
                // TODO: Sign extend for upper 32 bits
                self.write_reg_gpr(rt as usize, (imm << 16) as u64);
            },
            0b010000 => {
                // Mtc0
                let rd = (instruction >> 11) & 0b11111;
                let data = self.read_reg_gpr(rt as usize);
                self.cp0.write_reg(rd, data);
            },
            _ => {
                panic!("Unrecognized instruction: {:#x}",
                       instruction);
            }
        }

        self.reg_pc += 4;
    }

    fn read_word(&self, virt_addr: u64) -> u32 {
        let phys_addr = self.virt_addr_to_phys_addr(virt_addr);
        // TODO: Check endianness
        self.interconnect.read_word(phys_addr as u32)
    }

    fn virt_addr_to_phys_addr(&self, virt_addr: u64) -> u64 {
        // See Table 5-3 in the VR4300 User's Manual
        let addr_bit_values = (virt_addr >> 29) & 0b111;

        if addr_bit_values == 0b101 {
            // kseg1
            virt_addr - 0xffff_ffff_a000_0000
        } else {
            // TODO
            panic!("Unrecognized virtual address: {:#x}", virt_addr);
        }
    }

    fn write_reg_gpr(&mut self, index: usize, value: u64) {
        if index != 0 {
            self.reg_gpr[index] = value;
        }
    }

    fn read_reg_gpr(&self, index: usize) -> u64 {
        match index {
            0 => 0,
            _ => self.reg_gpr[index]
        }
    }
}
<commit_msg>Implemented ori instruction<commit_after>use super::super::interconnect;
use super::cp0::cp0;

const NUM_GPR: usize = 32;

#[derive(Debug)]
pub struct Cpu {
    reg_gpr: [u64; NUM_GPR],
    reg_fpr: [f64; NUM_GPR],

    reg_pc: u64,

    reg_hi: u64,
    reg_lo: u64,

    reg_llbit: bool, // TODO: Enum type

    reg_fcr0: u32,
    reg_fcr31: u32,

    cp0: cp0::Cp0,

    interconnect: interconnect::Interconnect
}

impl Cpu {
    pub fn new(interconnect: interconnect::Interconnect) -> Cpu {
        Cpu {
            reg_gpr: [0; NUM_GPR],
            reg_fpr: [0.0; NUM_GPR],

            reg_pc: 0,

            reg_hi: 0,
            reg_lo: 0,

            reg_llbit: false,

            reg_fcr0: 0,
            reg_fcr31: 0,

            cp0: cp0::Cp0::default(),

            interconnect: interconnect
        }
    }

    pub fn power_on_reset(&mut self) {
        self.cp0.power_on_reset();

        self.reg_pc = 0xffff_ffff_bfc0_0000; // TODO: Move to const
    }

    // TODO: Different interface
    pub fn run(&mut self) {
        loop {
            self.run_instruction();
        }
    }

    pub fn run_instruction(&mut self) {
        let instruction = self.read_word(self.reg_pc);

        let opcode = (instruction >> 26) & 0b111111;
        let rs = (instruction >> 21) & 0b11111;
        let rt = (instruction >> 16) & 0b11111;
        let imm = instruction & 0xffff;

        match opcode {
            0b001101 => {
                // Ori
                let res = self.read_reg_gpr(rs as usize) | (imm as u64);
                self.write_reg_gpr(rt as usize, res);
            },
            0b001111 => {
                // Lui
                // TODO: Sign extend for upper 32 bits
                self.write_reg_gpr(rt as usize, (imm << 16) as u64);
            },
            0b010000 => {
                // Mtc0
                let rd = (instruction >> 11) & 0b11111;
                let data = self.read_reg_gpr(rt as usize);
                self.cp0.write_reg(rd, data);
            },
            _ => {
                panic!("Unrecognized instruction: {:#x}",
                       instruction);
            }
        }

        self.reg_pc += 4;
    }

    fn read_word(&self, virt_addr: u64) -> u32 {
        let phys_addr = self.virt_addr_to_phys_addr(virt_addr);
        // TODO: Check endianness
        self.interconnect.read_word(phys_addr as u32)
    }

    fn virt_addr_to_phys_addr(&self, virt_addr: u64) -> u64 {
        // See Table 5-3 in the VR4300 User's Manual
        let addr_bit_values = (virt_addr >> 29) & 0b111;

        if addr_bit_values == 0b101 {
            // kseg1
            virt_addr - 0xffff_ffff_a000_0000
        } else {
            // TODO
            panic!("Unrecognized virtual address: {:#x}", virt_addr);
        }
    }

    fn write_reg_gpr(&mut self, index: usize, value: u64) {
        if index != 0 {
            self.reg_gpr[index] = value;
        }
    }

    fn read_reg_gpr(&self, index: usize) -> u64 {
        match index {
            0 => 0,
            _ => self.reg_gpr[index]
        }
    }
}
<|endoftext|>


<commit_before>/*!
Functionality for declaring Objective-C classes.

Classes can be declared using the `ClassDecl` struct. Instance variables and
methods can then be added before the class is ultimately registered.

# Example

The following example demonstrates declaring a class named `MyNumber` that has
one ivar, a `u32` named `_number` and a `number` method that returns it:

```
# #[macro_use] extern crate objc;
# use objc::declare::ClassDecl;
# use objc::runtime::{Class, Object, Sel};
# fn main() {
let superclass = Class::get("NSObject").unwrap();
let mut decl = ClassDecl::new(superclass, "MyNumber").unwrap();

// Add an instance variable
decl.add_ivar::<u32>("_number");

// Add an ObjC method for getting the number
extern fn my_number_get(this: &Object, _cmd: Sel) -> u32 {
    unsafe { *this.get_ivar("_number") }
}
unsafe {
    decl.add_method(sel!(number),
        my_number_get as extern fn(&Object, Sel) -> u32);
}

decl.register();
# }
```
*/

use std::error::Error;
use std::ffi::CString;
use std::fmt;
use std::mem;
use libc::size_t;

use {Encode, Encoding, Message};
use runtime::{Class, Imp, NO, Object, Sel, self};

/// An error returned from `MethodImplementation::imp_for` to indicate that a
/// selector and function accept unequal numbers of arguments.
#[derive(Clone, PartialEq, Debug)]
pub struct UnequalArgsError {
    sel_args: usize,
    fn_args: usize,
}

impl fmt::Display for UnequalArgsError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Selector accepts {} arguments, but function accepts {}",
            self.sel_args, self.fn_args)
    }
}

impl Error for UnequalArgsError {
    fn description(&self) -> &str {
        "Selector and function accept unequal numbers of arguments"
    }
}

/// Types that can be used as the implementation of an Objective-C method.
pub trait MethodImplementation {
    /// The callee type of the method.
    type Callee: Message;
    /// The return type of the method.
    type Ret: Encode;

    /// Returns the type encodings of Self's arguments.
    fn argument_encodings() -> Box<[Encoding]>;

    /// Returns self as an `Imp` of a method for the given selector.
    ///
    /// Returns an error if self and the selector do not accept the same number
    /// of arguments.
    fn imp_for(self, sel: Sel) -> Result<Imp, UnequalArgsError>;
}

macro_rules! count_idents {
    () => (0);
    ($a:ident) => (1);
    ($a:ident, $($b:ident),+) => (1 + count_idents!($($b),*));
}

macro_rules! method_decl_impl {
    (-$s:ident, $sp:ty, $($t:ident),*) => (
        impl<$s, R $(, $t)*> MethodImplementation for extern fn($sp, Sel $(, $t)*) -> R
                where $s: Message, R: Encode $(, $t: Encode)* {
            type Callee = $s;
            type Ret = R;

            fn argument_encodings() -> Box<[Encoding]> {
                Box::new([
                    <*mut Object>::encode(),
                    Sel::encode(),
                    $($t::encode()),*
                ])
            }

            fn imp_for(self, sel: Sel) -> Result<Imp, UnequalArgsError> {
                // Add 2 to the arguments for self and _cmd
                let fn_args = 2 + count_idents!($($t),*);
                let sel_args = 2 + sel.name().chars().filter(|&c| c == ':').count();
                if sel_args == fn_args {
                    unsafe { Ok(mem::transmute(self)) }
                } else {
                    Err(UnequalArgsError { sel_args: sel_args, fn_args: fn_args })
                }
            }
        }
    );
    ($($t:ident),*) => (
        method_decl_impl!(-T, &T, $($t),*);
        method_decl_impl!(-T, &mut T, $($t),*);
    );
}

method_decl_impl!();
method_decl_impl!(A);
method_decl_impl!(A, B);
method_decl_impl!(A, B, C);
method_decl_impl!(A, B, C, D);
method_decl_impl!(A, B, C, D, E);
method_decl_impl!(A, B, C, D, E, F);
method_decl_impl!(A, B, C, D, E, F, G);
method_decl_impl!(A, B, C, D, E, F, G, H);
method_decl_impl!(A, B, C, D, E, F, G, H, I);
method_decl_impl!(A, B, C, D, E, F, G, H, I, J);
method_decl_impl!(A, B, C, D, E, F, G, H, I, J, K);
method_decl_impl!(A, B, C, D, E, F, G, H, I, J, K, L);

fn method_type_encoding<F>() -> CString where F: MethodImplementation {
    let mut types = F::Ret::encode().as_str().to_string();
    types.extend(F::argument_encodings().iter().map(|e| e.as_str()));
    CString::new(types).unwrap()
}

/// A type for declaring a new class and adding new methods and ivars to it
/// before registering it.
pub struct ClassDecl {
    cls: *mut Class,
}

impl ClassDecl {
    /// Constructs a `ClassDecl` with the given superclass and name.
    /// Returns `None` if the class couldn't be allocated.
    pub fn new(superclass: &Class, name: &str) -> Option<ClassDecl> {
        let name = CString::new(name).unwrap();
        let cls = unsafe {
            runtime::objc_allocateClassPair(superclass, name.as_ptr(), 0)
        };
        if cls.is_null() {
            None
        } else {
            Some(ClassDecl { cls: cls })
        }
    }

    /// Adds a method with the given name and implementation to self.
    /// Panics if the method wasn't sucessfully added
    /// or if the selector and function take different numbers of arguments.
    /// Unsafe because the caller must ensure that the types match those that
    /// are expected when the method is invoked from Objective-C.
    pub unsafe fn add_method<F>(&mut self, sel: Sel, func: F)
            where F: MethodImplementation<Callee=Object> {
        let types = method_type_encoding::<F>();
        let imp = match func.imp_for(sel) {
            Ok(imp) => imp,
            Err(err) => panic!("{}", err),
        };

        let success = runtime::class_addMethod(self.cls, sel, imp,
            types.as_ptr());
        assert!(success != NO, "Failed to add method {:?}", sel);
    }

    /// Adds a class method with the given name and implementation to self.
    /// Panics if the method wasn't sucessfully added
    /// or if the selector and function take different numbers of arguments.
    /// Unsafe because the caller must ensure that the types match those that
    /// are expected when the method is invoked from Objective-C.
    pub unsafe fn add_class_method<F>(&mut self, sel: Sel, func: F)
            where F: MethodImplementation<Callee=Class> {
        let types = method_type_encoding::<F>();
        let imp = match func.imp_for(sel) {
            Ok(imp) => imp,
            Err(err) => panic!("{}", err),
        };

        let cls_obj = self.cls as *const Object;
        let metaclass = runtime::object_getClass(cls_obj) as *mut Class;
        let success = runtime::class_addMethod(metaclass, sel, imp,
            types.as_ptr());
        assert!(success != NO, "Failed to add class method {:?}", sel);
    }

    /// Adds an ivar with type `T` and the provided name to self.
    /// Panics if the ivar wasn't successfully added.
    pub fn add_ivar<T>(&mut self, name: &str) where T: Encode {
        let c_name = CString::new(name).unwrap();
        let encoding = CString::new(T::encode().as_str()).unwrap();
        let size = mem::size_of::<T>() as size_t;
        let align = mem::align_of::<T>() as u8;
        let success = unsafe {
            runtime::class_addIvar(self.cls, c_name.as_ptr(), size, align,
                encoding.as_ptr())
        };
        assert!(success != NO, "Failed to add ivar {}", name);
    }

    /// Registers self, consuming it and returning a reference to the
    /// newly registered `Class`.
    pub fn register(self) -> &'static Class {
        unsafe {
            let cls = self.cls;
            runtime::objc_registerClassPair(cls);
            // Forget self otherwise the class will be disposed in drop
            mem::forget(self);
            &*cls
        }
    }
}

impl Drop for ClassDecl {
    fn drop(&mut self) {
        unsafe {
            runtime::objc_disposeClassPair(self.cls);
        }
    }
}

#[cfg(test)]
mod tests {
    use runtime::{Object, Sel};
    use test_utils;
    use super::MethodImplementation;

    #[test]
    fn test_custom_class() {
        // Registering the custom class is in test_utils
        let obj = test_utils::custom_object();
        unsafe {
            let _: () = msg_send![obj, setFoo:13u32];
            let result: u32 = msg_send![obj, foo];
            assert!(result == 13);
        }
    }

    #[test]
    fn test_class_method() {
        let cls = test_utils::custom_class();
        unsafe {
            let result: u32 = msg_send![cls, classFoo];
            assert!(result == 7);
        }
    }

    #[test]
    fn test_mismatched_args() {
        extern fn wrong_num_args_method(_obj: &Object, _cmd: Sel, _a: i32) { }

        let sel = sel!(doSomethingWithFoo:bar:);
        let f: extern fn(&Object, Sel, i32) = wrong_num_args_method;
        let imp = f.imp_for(sel);
        assert!(imp.is_err());
    }
}
<commit_msg>Pass the type into the method_decl_impl! macro.<commit_after>/*!
Functionality for declaring Objective-C classes.

Classes can be declared using the `ClassDecl` struct. Instance variables and
methods can then be added before the class is ultimately registered.

# Example

The following example demonstrates declaring a class named `MyNumber` that has
one ivar, a `u32` named `_number` and a `number` method that returns it:

```
# #[macro_use] extern crate objc;
# use objc::declare::ClassDecl;
# use objc::runtime::{Class, Object, Sel};
# fn main() {
let superclass = Class::get("NSObject").unwrap();
let mut decl = ClassDecl::new(superclass, "MyNumber").unwrap();

// Add an instance variable
decl.add_ivar::<u32>("_number");

// Add an ObjC method for getting the number
extern fn my_number_get(this: &Object, _cmd: Sel) -> u32 {
    unsafe { *this.get_ivar("_number") }
}
unsafe {
    decl.add_method(sel!(number),
        my_number_get as extern fn(&Object, Sel) -> u32);
}

decl.register();
# }
```
*/

use std::error::Error;
use std::ffi::CString;
use std::fmt;
use std::mem;
use libc::size_t;

use {Encode, Encoding, Message};
use runtime::{Class, Imp, NO, Object, Sel, self};

/// An error returned from `MethodImplementation::imp_for` to indicate that a
/// selector and function accept unequal numbers of arguments.
#[derive(Clone, PartialEq, Debug)]
pub struct UnequalArgsError {
    sel_args: usize,
    fn_args: usize,
}

impl fmt::Display for UnequalArgsError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Selector accepts {} arguments, but function accepts {}",
            self.sel_args, self.fn_args)
    }
}

impl Error for UnequalArgsError {
    fn description(&self) -> &str {
        "Selector and function accept unequal numbers of arguments"
    }
}

/// Types that can be used as the implementation of an Objective-C method.
pub trait MethodImplementation {
    /// The callee type of the method.
    type Callee: Message;
    /// The return type of the method.
    type Ret: Encode;

    /// Returns the type encodings of Self's arguments.
    fn argument_encodings() -> Box<[Encoding]>;

    /// Returns self as an `Imp` of a method for the given selector.
    ///
    /// Returns an error if self and the selector do not accept the same number
    /// of arguments.
    fn imp_for(self, sel: Sel) -> Result<Imp, UnequalArgsError>;
}

macro_rules! count_idents {
    () => (0);
    ($a:ident) => (1);
    ($a:ident, $($b:ident),+) => (1 + count_idents!($($b),*));
}

macro_rules! method_decl_impl {
    (-$s:ident, $r:ident, $f:ty, $($t:ident),*) => (
        impl<$s, $r $(, $t)*> MethodImplementation for $f
                where $s: Message, $r: Encode $(, $t: Encode)* {
            type Callee = $s;
            type Ret = $r;

            fn argument_encodings() -> Box<[Encoding]> {
                Box::new([
                    <*mut Object>::encode(),
                    Sel::encode(),
                    $($t::encode()),*
                ])
            }

            fn imp_for(self, sel: Sel) -> Result<Imp, UnequalArgsError> {
                // Add 2 to the arguments for self and _cmd
                let fn_args = 2 + count_idents!($($t),*);
                let sel_args = 2 + sel.name().chars().filter(|&c| c == ':').count();
                if sel_args == fn_args {
                    unsafe { Ok(mem::transmute(self)) }
                } else {
                    Err(UnequalArgsError { sel_args: sel_args, fn_args: fn_args })
                }
            }
        }
    );
    ($($t:ident),*) => (
        method_decl_impl!(-T, R, extern fn(&T, Sel $(, $t)*) -> R, $($t),*);
        method_decl_impl!(-T, R, extern fn(&mut T, Sel $(, $t)*) -> R, $($t),*);
    );
}

method_decl_impl!();
method_decl_impl!(A);
method_decl_impl!(A, B);
method_decl_impl!(A, B, C);
method_decl_impl!(A, B, C, D);
method_decl_impl!(A, B, C, D, E);
method_decl_impl!(A, B, C, D, E, F);
method_decl_impl!(A, B, C, D, E, F, G);
method_decl_impl!(A, B, C, D, E, F, G, H);
method_decl_impl!(A, B, C, D, E, F, G, H, I);
method_decl_impl!(A, B, C, D, E, F, G, H, I, J);
method_decl_impl!(A, B, C, D, E, F, G, H, I, J, K);
method_decl_impl!(A, B, C, D, E, F, G, H, I, J, K, L);

fn method_type_encoding<F>() -> CString where F: MethodImplementation {
    let mut types = F::Ret::encode().as_str().to_string();
    types.extend(F::argument_encodings().iter().map(|e| e.as_str()));
    CString::new(types).unwrap()
}

/// A type for declaring a new class and adding new methods and ivars to it
/// before registering it.
pub struct ClassDecl {
    cls: *mut Class,
}

impl ClassDecl {
    /// Constructs a `ClassDecl` with the given superclass and name.
    /// Returns `None` if the class couldn't be allocated.
    pub fn new(superclass: &Class, name: &str) -> Option<ClassDecl> {
        let name = CString::new(name).unwrap();
        let cls = unsafe {
            runtime::objc_allocateClassPair(superclass, name.as_ptr(), 0)
        };
        if cls.is_null() {
            None
        } else {
            Some(ClassDecl { cls: cls })
        }
    }

    /// Adds a method with the given name and implementation to self.
    /// Panics if the method wasn't sucessfully added
    /// or if the selector and function take different numbers of arguments.
    /// Unsafe because the caller must ensure that the types match those that
    /// are expected when the method is invoked from Objective-C.
    pub unsafe fn add_method<F>(&mut self, sel: Sel, func: F)
            where F: MethodImplementation<Callee=Object> {
        let types = method_type_encoding::<F>();
        let imp = match func.imp_for(sel) {
            Ok(imp) => imp,
            Err(err) => panic!("{}", err),
        };

        let success = runtime::class_addMethod(self.cls, sel, imp,
            types.as_ptr());
        assert!(success != NO, "Failed to add method {:?}", sel);
    }

    /// Adds a class method with the given name and implementation to self.
    /// Panics if the method wasn't sucessfully added
    /// or if the selector and function take different numbers of arguments.
    /// Unsafe because the caller must ensure that the types match those that
    /// are expected when the method is invoked from Objective-C.
    pub unsafe fn add_class_method<F>(&mut self, sel: Sel, func: F)
            where F: MethodImplementation<Callee=Class> {
        let types = method_type_encoding::<F>();
        let imp = match func.imp_for(sel) {
            Ok(imp) => imp,
            Err(err) => panic!("{}", err),
        };

        let cls_obj = self.cls as *const Object;
        let metaclass = runtime::object_getClass(cls_obj) as *mut Class;
        let success = runtime::class_addMethod(metaclass, sel, imp,
            types.as_ptr());
        assert!(success != NO, "Failed to add class method {:?}", sel);
    }

    /// Adds an ivar with type `T` and the provided name to self.
    /// Panics if the ivar wasn't successfully added.
    pub fn add_ivar<T>(&mut self, name: &str) where T: Encode {
        let c_name = CString::new(name).unwrap();
        let encoding = CString::new(T::encode().as_str()).unwrap();
        let size = mem::size_of::<T>() as size_t;
        let align = mem::align_of::<T>() as u8;
        let success = unsafe {
            runtime::class_addIvar(self.cls, c_name.as_ptr(), size, align,
                encoding.as_ptr())
        };
        assert!(success != NO, "Failed to add ivar {}", name);
    }

    /// Registers self, consuming it and returning a reference to the
    /// newly registered `Class`.
    pub fn register(self) -> &'static Class {
        unsafe {
            let cls = self.cls;
            runtime::objc_registerClassPair(cls);
            // Forget self otherwise the class will be disposed in drop
            mem::forget(self);
            &*cls
        }
    }
}

impl Drop for ClassDecl {
    fn drop(&mut self) {
        unsafe {
            runtime::objc_disposeClassPair(self.cls);
        }
    }
}

#[cfg(test)]
mod tests {
    use runtime::{Object, Sel};
    use test_utils;
    use super::MethodImplementation;

    #[test]
    fn test_custom_class() {
        // Registering the custom class is in test_utils
        let obj = test_utils::custom_object();
        unsafe {
            let _: () = msg_send![obj, setFoo:13u32];
            let result: u32 = msg_send![obj, foo];
            assert!(result == 13);
        }
    }

    #[test]
    fn test_class_method() {
        let cls = test_utils::custom_class();
        unsafe {
            let result: u32 = msg_send![cls, classFoo];
            assert!(result == 7);
        }
    }

    #[test]
    fn test_mismatched_args() {
        extern fn wrong_num_args_method(_obj: &Object, _cmd: Sel, _a: i32) { }

        let sel = sel!(doSomethingWithFoo:bar:);
        let f: extern fn(&Object, Sel, i32) = wrong_num_args_method;
        let imp = f.imp_for(sel);
        assert!(imp.is_err());
    }
}
<|endoftext|>


<commit_before>use crate::utils::{match_def_path, paths, span_lint, trait_ref_of_method, walk_ptrs_ty};
use rustc::declare_lint_pass;
use rustc::hir;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::ty::{Adt, Dynamic, Opaque, Param, RawPtr, Ref, Ty, TypeAndMut};
use rustc_session::declare_tool_lint;
use syntax::source_map::Span;

declare_clippy_lint! {
    /// **What it does:** Checks for sets/maps with mutable key types.
    ///
    /// **Why is this bad?** All of `HashMap`, `HashSet`, `BTreeMap` and
    /// `BtreeSet` rely on either the hash or the order of keys be unchanging,
    /// so having types with interior mutability is a bad idea.
    ///
    /// **Known problems:** We don't currently account for `Rc` or `Arc`, so
    /// this may yield false positives.
    ///
    /// **Example:**
    /// ```rust
    /// use std::cmp::{PartialEq, Eq};
    /// use std::collections::HashSet;
    /// use std::hash::{Hash, Hasher};
    /// use std::sync::atomic::AtomicUsize;
    ///# #[allow(unused)]
    ///
    /// struct Bad(AtomicUsize);
    /// impl PartialEq for Bad {
    ///     fn eq(&self, rhs: &Self) -> bool {
    ///          ..
    /// ; unimplemented!();
    ///     }
    /// }
    ///
    /// impl Eq for Bad {}
    ///
    /// impl Hash for Bad {
    ///     fn hash<H: Hasher>(&self, h: &mut H) {
    ///         ..
    /// ; unimplemented!();
    ///     }
    /// }
    ///
    /// fn main() {
    ///     let _: HashSet<Bad> = HashSet::new();
    /// }
    /// ```
    pub MUTABLE_KEY_TYPE,
    correctness,
    "Check for mutable Map/Set key type"
}

declare_lint_pass!(MutableKeyType => [ MUTABLE_KEY_TYPE ]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableKeyType {
    fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item<'tcx>) {
        if let hir::ItemKind::Fn(ref sig, ..) = item.kind {
            check_sig(cx, item.hir_id, &sig.decl);
        }
    }

    fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::ImplItem<'tcx>) {
        if let hir::ImplItemKind::Method(ref sig, ..) = item.kind {
            if trait_ref_of_method(cx, item.hir_id).is_none() {
                check_sig(cx, item.hir_id, &sig.decl);
            }
        }
    }

    fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::TraitItem<'tcx>) {
        if let hir::TraitItemKind::Method(ref sig, ..) = item.kind {
            check_sig(cx, item.hir_id, &sig.decl);
        }
    }

    fn check_local(&mut self, cx: &LateContext<'_, '_>, local: &hir::Local<'_>) {
        if let hir::PatKind::Wild = local.pat.kind {
            return;
        }
        check_ty(cx, local.span, cx.tables.pat_ty(&*local.pat));
    }
}

fn check_sig<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item_hir_id: hir::HirId, decl: &hir::FnDecl) {
    let fn_def_id = cx.tcx.hir().local_def_id(item_hir_id);
    let fn_sig = cx.tcx.fn_sig(fn_def_id);
    for (hir_ty, ty) in decl.inputs.iter().zip(fn_sig.inputs().skip_binder().iter()) {
        check_ty(cx, hir_ty.span, ty);
    }
    check_ty(
        cx,
        decl.output.span(),
        cx.tcx.erase_late_bound_regions(&fn_sig.output()),
    );
}

// We want to lint 1. sets or maps with 2. not immutable key types and 3. no unerased
// generics (because the compiler cannot ensure immutability for unknown types).
fn check_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, ty: Ty<'tcx>) {
    let ty = walk_ptrs_ty(ty);
    if let Adt(def, substs) = ty.kind {
        if [&paths::HASHMAP, &paths::BTREEMAP, &paths::HASHSET, &paths::BTREESET]
            .iter()
            .any(|path| match_def_path(cx, def.did, &**path))
        {
            let key_type = substs.type_at(0);
            if is_concrete_type(key_type) && !key_type.is_freeze(cx.tcx, cx.param_env, span) {
                span_lint(cx, MUTABLE_KEY_TYPE, span, "mutable key type");
            }
        }
    }
}

fn is_concrete_type(ty: Ty<'_>) -> bool {
    match ty.kind {
        RawPtr(TypeAndMut { ty: inner_ty, .. }) | Ref(_, inner_ty, _) => is_concrete_type(inner_ty),
        Dynamic(..) | Opaque(..) | Param(..) => false,
        _ => true,
    }
}
<commit_msg>Possibly fix an ICE on test<commit_after>use crate::utils::{match_def_path, paths, span_lint, trait_ref_of_method, walk_ptrs_ty};
use rustc::declare_lint_pass;
use rustc::hir;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::ty::{Adt, Dynamic, Opaque, Param, RawPtr, Ref, Ty, TypeAndMut};
use rustc_session::declare_tool_lint;
use syntax::source_map::Span;

declare_clippy_lint! {
    /// **What it does:** Checks for sets/maps with mutable key types.
    ///
    /// **Why is this bad?** All of `HashMap`, `HashSet`, `BTreeMap` and
    /// `BtreeSet` rely on either the hash or the order of keys be unchanging,
    /// so having types with interior mutability is a bad idea.
    ///
    /// **Known problems:** We don't currently account for `Rc` or `Arc`, so
    /// this may yield false positives.
    ///
    /// **Example:**
    /// ```rust
    /// use std::cmp::{PartialEq, Eq};
    /// use std::collections::HashSet;
    /// use std::hash::{Hash, Hasher};
    /// use std::sync::atomic::AtomicUsize;
    ///# #[allow(unused)]
    ///
    /// struct Bad(AtomicUsize);
    /// impl PartialEq for Bad {
    ///     fn eq(&self, rhs: &Self) -> bool {
    ///          ..
    /// ; unimplemented!();
    ///     }
    /// }
    ///
    /// impl Eq for Bad {}
    ///
    /// impl Hash for Bad {
    ///     fn hash<H: Hasher>(&self, h: &mut H) {
    ///         ..
    /// ; unimplemented!();
    ///     }
    /// }
    ///
    /// fn main() {
    ///     let _: HashSet<Bad> = HashSet::new();
    /// }
    /// ```
    pub MUTABLE_KEY_TYPE,
    correctness,
    "Check for mutable Map/Set key type"
}

declare_lint_pass!(MutableKeyType => [ MUTABLE_KEY_TYPE ]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableKeyType {
    fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item<'tcx>) {
        if let hir::ItemKind::Fn(ref sig, ..) = item.kind {
            check_sig(cx, item.hir_id, &sig.decl);
        }
    }

    fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::ImplItem<'tcx>) {
        if let hir::ImplItemKind::Method(ref sig, ..) = item.kind {
            if trait_ref_of_method(cx, item.hir_id).is_none() {
                check_sig(cx, item.hir_id, &sig.decl);
            }
        }
    }

    fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::TraitItem<'tcx>) {
        if let hir::TraitItemKind::Method(ref sig, ..) = item.kind {
            check_sig(cx, item.hir_id, &sig.decl);
        }
    }

    fn check_local(&mut self, cx: &LateContext<'_, '_>, local: &hir::Local<'_>) {
        if let hir::PatKind::Wild = local.pat.kind {
            return;
        }
        check_ty(cx, local.span, cx.tables.pat_ty(&*local.pat));
    }
}

fn check_sig<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item_hir_id: hir::HirId, decl: &hir::FnDecl) {
    let fn_def_id = cx.tcx.hir().local_def_id(item_hir_id);
    let fn_sig = cx.tcx.fn_sig(fn_def_id);
    for (hir_ty, ty) in decl.inputs.iter().zip(fn_sig.inputs().skip_binder().iter()) {
        check_ty(cx, hir_ty.span, ty);
    }
    check_ty(
        cx,
        decl.output.span(),
        cx.tcx.erase_late_bound_regions(&fn_sig.output()),
    );
}

// We want to lint 1. sets or maps with 2. not immutable key types and 3. no unerased
// generics (because the compiler cannot ensure immutability for unknown types).
fn check_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, ty: Ty<'tcx>) {
    let ty = walk_ptrs_ty(ty);
    if let Adt(def, substs) = ty.kind {
        if [&paths::HASHMAP, &paths::BTREEMAP, &paths::HASHSET, &paths::BTREESET]
            .iter()
            .any(|path| match_def_path(cx, def.did, &**path))
        {
            let key_type = concrete_type(Some(substs.type_at(0)));
            if let Some(key_type) = key_type {
                if !key_type.is_freeze(cx.tcx, cx.param_env, span) {
                    span_lint(cx, MUTABLE_KEY_TYPE, span, "mutable key type");
                }
            }
        }
    }
}

fn concrete_type(ty: Option<Ty<'_>>) -> Option<Ty<'_>> {
    if let Some(ty) = ty {
        match ty.kind {
            RawPtr(TypeAndMut { ty: inner_ty, .. }) | Ref(_, inner_ty, _) => return concrete_type(Some(inner_ty)),
            Dynamic(..) | Opaque(..) | Param(..) => return None,
            _ => return Some(ty),
        }
    }
    None
}
<|endoftext|>


<commit_before>use crate::utils::{match_def_path, paths, span_lint, trait_ref_of_method, walk_ptrs_ty};
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{Adt, Array, RawPtr, Ref, Slice, Tuple, Ty, TypeAndMut};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;

declare_clippy_lint! {
    /// **What it does:** Checks for sets/maps with mutable key types.
    ///
    /// **Why is this bad?** All of `HashMap`, `HashSet`, `BTreeMap` and
    /// `BtreeSet` rely on either the hash or the order of keys be unchanging,
    /// so having types with interior mutability is a bad idea.
    ///
    /// **Known problems:** We don't currently account for `Rc` or `Arc`, so
    /// this may yield false positives.
    ///
    /// **Example:**
    /// ```rust
    /// use std::cmp::{PartialEq, Eq};
    /// use std::collections::HashSet;
    /// use std::hash::{Hash, Hasher};
    /// use std::sync::atomic::AtomicUsize;
    ///# #[allow(unused)]
    ///
    /// struct Bad(AtomicUsize);
    /// impl PartialEq for Bad {
    ///     fn eq(&self, rhs: &Self) -> bool {
    ///          ..
    /// ; unimplemented!();
    ///     }
    /// }
    ///
    /// impl Eq for Bad {}
    ///
    /// impl Hash for Bad {
    ///     fn hash<H: Hasher>(&self, h: &mut H) {
    ///         ..
    /// ; unimplemented!();
    ///     }
    /// }
    ///
    /// fn main() {
    ///     let _: HashSet<Bad> = HashSet::new();
    /// }
    /// ```
    pub MUTABLE_KEY_TYPE,
    correctness,
    "Check for mutable `Map`/`Set` key type"
}

declare_lint_pass!(MutableKeyType => [ MUTABLE_KEY_TYPE ]);

impl<'tcx> LateLintPass<'tcx> for MutableKeyType {
    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
        if let hir::ItemKind::Fn(ref sig, ..) = item.kind {
            check_sig(cx, item.hir_id, &sig.decl);
        }
    }

    fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'tcx>) {
        if let hir::ImplItemKind::Fn(ref sig, ..) = item.kind {
            if trait_ref_of_method(cx, item.hir_id).is_none() {
                check_sig(cx, item.hir_id, &sig.decl);
            }
        }
    }

    fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'tcx>) {
        if let hir::TraitItemKind::Fn(ref sig, ..) = item.kind {
            check_sig(cx, item.hir_id, &sig.decl);
        }
    }

    fn check_local(&mut self, cx: &LateContext<'_>, local: &hir::Local<'_>) {
        if let hir::PatKind::Wild = local.pat.kind {
            return;
        }
        check_ty(cx, local.span, cx.typeck_results().pat_ty(&*local.pat));
    }
}

fn check_sig<'tcx>(cx: &LateContext<'tcx>, item_hir_id: hir::HirId, decl: &hir::FnDecl<'_>) {
    let fn_def_id = cx.tcx.hir().local_def_id(item_hir_id);
    let fn_sig = cx.tcx.fn_sig(fn_def_id);
    for (hir_ty, ty) in decl.inputs.iter().zip(fn_sig.inputs().skip_binder().iter()) {
        check_ty(cx, hir_ty.span, ty);
    }
    check_ty(
        cx,
        decl.output.span(),
        cx.tcx.erase_late_bound_regions(&fn_sig.output()),
    );
}

// We want to lint 1. sets or maps with 2. not immutable key types and 3. no unerased
// generics (because the compiler cannot ensure immutability for unknown types).
fn check_ty<'tcx>(cx: &LateContext<'tcx>, span: Span, ty: Ty<'tcx>) {
    let ty = walk_ptrs_ty(ty);
    if let Adt(def, substs) = ty.kind() {
        if [&paths::HASHMAP, &paths::BTREEMAP, &paths::HASHSET, &paths::BTREESET]
            .iter()
            .any(|path| match_def_path(cx, def.did, &**path))
            && is_mutable_type(cx, substs.type_at(0), span)
        {
            span_lint(cx, MUTABLE_KEY_TYPE, span, "mutable key type");
        }
    }
}

fn is_mutable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span) -> bool {
    match *ty.kind() {
        RawPtr(TypeAndMut { ty: inner_ty, mutbl }) | Ref(_, inner_ty, mutbl) => {
            mutbl == hir::Mutability::Mut || is_mutable_type(cx, inner_ty, span)
        },
        Slice(inner_ty) => is_mutable_type(cx, inner_ty, span),
        Array(inner_ty, size) => {
            size.try_eval_usize(cx.tcx, cx.param_env).map_or(true, |u| u != 0) && is_mutable_type(cx, inner_ty, span)
        },
        Tuple(..) => ty.tuple_fields().any(|ty| is_mutable_type(cx, ty, span)),
        Adt(..) => cx.tcx.layout_of(cx.param_env.and(ty)).is_ok() && !ty.is_freeze(cx.tcx.at(span), cx.param_env),
        _ => false,
    }
}
<commit_msg>Improve "known problems" of `interior_mutable_key`<commit_after>use crate::utils::{match_def_path, paths, span_lint, trait_ref_of_method, walk_ptrs_ty};
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{Adt, Array, RawPtr, Ref, Slice, Tuple, Ty, TypeAndMut};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;

declare_clippy_lint! {
    /// **What it does:** Checks for sets/maps with mutable key types.
    ///
    /// **Why is this bad?** All of `HashMap`, `HashSet`, `BTreeMap` and
    /// `BtreeSet` rely on either the hash or the order of keys be unchanging,
    /// so having types with interior mutability is a bad idea.
    ///
    /// **Known problems:** It's correct to use a struct, that contains interior mutability,
    /// as a key; when its `Hash` implementation doesn't access any these interior mutable types.
    /// However, this lint is unable to recognise it so cause a false positive.
    /// `bytes` ctate is a great example of this.
    ///
    /// **Example:**
    /// ```rust
    /// use std::cmp::{PartialEq, Eq};
    /// use std::collections::HashSet;
    /// use std::hash::{Hash, Hasher};
    /// use std::sync::atomic::AtomicUsize;
    ///# #[allow(unused)]
    ///
    /// struct Bad(AtomicUsize);
    /// impl PartialEq for Bad {
    ///     fn eq(&self, rhs: &Self) -> bool {
    ///          ..
    /// ; unimplemented!();
    ///     }
    /// }
    ///
    /// impl Eq for Bad {}
    ///
    /// impl Hash for Bad {
    ///     fn hash<H: Hasher>(&self, h: &mut H) {
    ///         ..
    /// ; unimplemented!();
    ///     }
    /// }
    ///
    /// fn main() {
    ///     let _: HashSet<Bad> = HashSet::new();
    /// }
    /// ```
    pub MUTABLE_KEY_TYPE,
    correctness,
    "Check for mutable `Map`/`Set` key type"
}

declare_lint_pass!(MutableKeyType => [ MUTABLE_KEY_TYPE ]);

impl<'tcx> LateLintPass<'tcx> for MutableKeyType {
    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
        if let hir::ItemKind::Fn(ref sig, ..) = item.kind {
            check_sig(cx, item.hir_id, &sig.decl);
        }
    }

    fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'tcx>) {
        if let hir::ImplItemKind::Fn(ref sig, ..) = item.kind {
            if trait_ref_of_method(cx, item.hir_id).is_none() {
                check_sig(cx, item.hir_id, &sig.decl);
            }
        }
    }

    fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'tcx>) {
        if let hir::TraitItemKind::Fn(ref sig, ..) = item.kind {
            check_sig(cx, item.hir_id, &sig.decl);
        }
    }

    fn check_local(&mut self, cx: &LateContext<'_>, local: &hir::Local<'_>) {
        if let hir::PatKind::Wild = local.pat.kind {
            return;
        }
        check_ty(cx, local.span, cx.typeck_results().pat_ty(&*local.pat));
    }
}

fn check_sig<'tcx>(cx: &LateContext<'tcx>, item_hir_id: hir::HirId, decl: &hir::FnDecl<'_>) {
    let fn_def_id = cx.tcx.hir().local_def_id(item_hir_id);
    let fn_sig = cx.tcx.fn_sig(fn_def_id);
    for (hir_ty, ty) in decl.inputs.iter().zip(fn_sig.inputs().skip_binder().iter()) {
        check_ty(cx, hir_ty.span, ty);
    }
    check_ty(
        cx,
        decl.output.span(),
        cx.tcx.erase_late_bound_regions(&fn_sig.output()),
    );
}

// We want to lint 1. sets or maps with 2. not immutable key types and 3. no unerased
// generics (because the compiler cannot ensure immutability for unknown types).
fn check_ty<'tcx>(cx: &LateContext<'tcx>, span: Span, ty: Ty<'tcx>) {
    let ty = walk_ptrs_ty(ty);
    if let Adt(def, substs) = ty.kind() {
        if [&paths::HASHMAP, &paths::BTREEMAP, &paths::HASHSET, &paths::BTREESET]
            .iter()
            .any(|path| match_def_path(cx, def.did, &**path))
            && is_mutable_type(cx, substs.type_at(0), span)
        {
            span_lint(cx, MUTABLE_KEY_TYPE, span, "mutable key type");
        }
    }
}

fn is_mutable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span) -> bool {
    match *ty.kind() {
        RawPtr(TypeAndMut { ty: inner_ty, mutbl }) | Ref(_, inner_ty, mutbl) => {
            mutbl == hir::Mutability::Mut || is_mutable_type(cx, inner_ty, span)
        },
        Slice(inner_ty) => is_mutable_type(cx, inner_ty, span),
        Array(inner_ty, size) => {
            size.try_eval_usize(cx.tcx, cx.param_env).map_or(true, |u| u != 0) && is_mutable_type(cx, inner_ty, span)
        },
        Tuple(..) => ty.tuple_fields().any(|ty| is_mutable_type(cx, ty, span)),
        Adt(..) => cx.tcx.layout_of(cx.param_env.and(ty)).is_ok() && !ty.is_freeze(cx.tcx.at(span), cx.param_env),
        _ => false,
    }
}
<|endoftext|>


<commit_before>use std;
use std::convert::From;
use std::io;

use std::net::SocketAddr;

use mioco::udp::UdpSocket;
use trust_dns_proto::error::ProtoError;
use trust_dns_proto::op::{Message, MessageType, Query};
use trust_dns_proto::rr::{Name, Record, RecordType};
use trust_dns_proto::serialize::binary::BinDecodable;

use crate::query::ErrorKind as QueryErrorKind;
use crate::resolver::ErrorKind as ResolverErrorKind;

pub mod as_disp;
pub mod future;
pub mod ipset;
pub mod jsonrpc;
pub mod with_timeout;
pub use self::as_disp::AsDisplay;
pub use self::future::Future;
pub use self::ipset::IpSet;
pub use self::jsonrpc::{JsonRpcRequest, JsonRpcResponse};
pub use self::with_timeout::WithTimeout;

lazy_static! {
    pub static ref ROOT_NAME: Name = Name::root();
}

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        Io(err: io::Error) {
            from()
            from(kind: io::ErrorKind) -> (io::Error::new(kind, "Io"))
            description(err.description())
            display("{}", err)
        }
        Proto(err: ProtoError) {
            from()
            description(err.description())
            display("{}", err)
        }
        ChannelRecv(err: std::sync::mpsc::RecvError) {
            from()
            description(err.description())
        }
        Resolver(kind: ResolverErrorKind) {
            from()
        }
        Query(kind: QueryErrorKind) {
            from()
        }
        Other(msg: &'static str, extra: Option<String>) {
            description(msg)
            display("{}: {}", msg, extra.as_ref().unwrap_or(&String::new()))
        }
    }
}

pub type Result<T> = std::result::Result<T, Error>;

pub trait MessageExt {
    fn from_udp(sock: &mut UdpSocket) -> Result<(Message, SocketAddr)>;
    fn strip_dnssec_records(&self) -> Message;
    fn new_resp(&self) -> Message;
    fn clone_resp(&self) -> Message;
    fn clone_resp_for(&self, q: &Query) -> Message;
    fn copy_resp_from(&mut self, other: &Message);
    fn copy_resp_with<F>(&mut self, other: &Message, f: F)
    where
        F: FnMut(&Record) -> Record;
    fn without_rr(&self) -> Message;
    fn is_resp_for(&self, other: &Message) -> bool;
}
impl MessageExt for Message {
    fn from_udp(sock: &mut UdpSocket) -> Result<(Message, SocketAddr)> {
        let mut buf = [0u8; 1024 * 16];
        let (l, addr) = (sock.recv(&mut buf))?;
        let msg = (Message::from_bytes(&buf[0..l]))?;
        Ok((msg, addr))
    }
    fn strip_dnssec_records(&self) -> Message {
        let mut filtered = self.without_rr();
        const REMOVED_TYPES: [RecordType; 1] = [RecordType::OPT];
        let query_type = self.queries()[0].query_type();
        let f = |r: &&Record| -> bool {
            let t = r.rr_type();
            if t == query_type {
                return true;
            }
            if let RecordType::DNSSEC(_) = t {
                return false;
            }
            !REMOVED_TYPES.contains(&t)
        };
        self.answers().iter().filter(&f).for_each(|r| {
            filtered.add_answer(r.clone());
        });
        self.name_servers().iter().filter(&f).for_each(|r| {
            filtered.add_name_server(r.clone());
        });
        self.additionals().iter().filter(&f).for_each(|r| {
            filtered.add_additional(r.clone());
        });
        filtered
    }
    fn new_resp(&self) -> Message {
        let mut ret: Message = Message::new();
        ret.set_message_type(MessageType::Response);
        ret.set_id(self.id());
        ret.set_op_code(self.op_code());
        ret.set_recursion_desired(self.recursion_desired());
        for q in self.queries() {
            ret.add_query(q.clone());
        }
        ret
    }
    fn clone_resp(&self) -> Message {
        let mut ret = Message::new();
        ret.copy_resp_from(self);
        ret
    }
    fn clone_resp_for(&self, q: &Query) -> Message {
        let mut ret = self.clone_resp();
        ret.add_query(q.clone());
        ret
    }
    fn without_rr(&self) -> Message {
        // Simpler way to clear all answers
        let mut new_msg = self.truncate();
        assert!(new_msg.queries().is_empty());
        assert!(new_msg.answers().is_empty());
        assert!(new_msg.name_servers().is_empty());
        assert!(new_msg.additionals().is_empty());
        new_msg.set_truncated(false);
        new_msg.set_checking_disabled(self.checking_disabled());
        new_msg.set_authentic_data(self.authentic_data());
        self.queries().iter().for_each(|q| {
            new_msg.add_query(q.clone());
        });
        new_msg
    }
    fn copy_resp_from(&mut self, other: &Message) {
        self.copy_resp_with(other, Record::clone)
    }
    fn copy_resp_with<F>(&mut self, other: &Message, mut f: F)
    where
        F: FnMut(&Record) -> Record,
    {
        self.set_response_code(other.response_code());
        self.set_message_type(other.message_type());
        other.answers().iter().map(|x| f(x)).for_each(|x| {
            self.add_answer(x);
        });
        other.name_servers().iter().map(|x| f(x)).for_each(|x| {
            self.add_name_server(x);
        });

        // RFC 2671 4.1: OPT should never be cached nor forwarded
        other
            .additionals()
            .iter()
            .filter(|x| x.rr_type() != RecordType::OPT)
            .map(|x| f(x))
            .for_each(|x| {
                self.add_additional(x);
            });
    }
    fn is_resp_for(&self, other: &Message) -> bool {
        assert_eq!(other.message_type(), MessageType::Query);
        if self.message_type() != MessageType::Response {
            return false;
        }
        if other.id() != self.id() {
            return false;
        }
        if other.op_code() != self.op_code() {
            return false;
        }
        assert_eq!(other.queries().len(), 1);
        if self.queries().len() != 1 {
            return false;
        }
        if other.queries()[0] != self.queries()[0] {
            return false;
        }
        true
    }
}
<commit_msg>Why aren't name servers removed?<commit_after>use std;
use std::convert::From;
use std::io;

use std::net::SocketAddr;

use mioco::udp::UdpSocket;
use trust_dns_proto::error::ProtoError;
use trust_dns_proto::op::{Message, MessageType, Query};
use trust_dns_proto::rr::{Name, Record, RecordType};
use trust_dns_proto::serialize::binary::BinDecodable;

use crate::query::ErrorKind as QueryErrorKind;
use crate::resolver::ErrorKind as ResolverErrorKind;

pub mod as_disp;
pub mod future;
pub mod ipset;
pub mod jsonrpc;
pub mod with_timeout;
pub use self::as_disp::AsDisplay;
pub use self::future::Future;
pub use self::ipset::IpSet;
pub use self::jsonrpc::{JsonRpcRequest, JsonRpcResponse};
pub use self::with_timeout::WithTimeout;

lazy_static! {
    pub static ref ROOT_NAME: Name = Name::root();
}

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        Io(err: io::Error) {
            from()
            from(kind: io::ErrorKind) -> (io::Error::new(kind, "Io"))
            description(err.description())
            display("{}", err)
        }
        Proto(err: ProtoError) {
            from()
            description(err.description())
            display("{}", err)
        }
        ChannelRecv(err: std::sync::mpsc::RecvError) {
            from()
            description(err.description())
        }
        Resolver(kind: ResolverErrorKind) {
            from()
        }
        Query(kind: QueryErrorKind) {
            from()
        }
        Other(msg: &'static str, extra: Option<String>) {
            description(msg)
            display("{}: {}", msg, extra.as_ref().unwrap_or(&String::new()))
        }
    }
}

pub type Result<T> = std::result::Result<T, Error>;

pub trait MessageExt {
    fn from_udp(sock: &mut UdpSocket) -> Result<(Message, SocketAddr)>;
    fn strip_dnssec_records(&self) -> Message;
    fn new_resp(&self) -> Message;
    fn clone_resp(&self) -> Message;
    fn clone_resp_for(&self, q: &Query) -> Message;
    fn copy_resp_from(&mut self, other: &Message);
    fn copy_resp_with<F>(&mut self, other: &Message, f: F)
    where
        F: FnMut(&Record) -> Record;
    fn without_rr(&self) -> Message;
    fn is_resp_for(&self, other: &Message) -> bool;
}
impl MessageExt for Message {
    fn from_udp(sock: &mut UdpSocket) -> Result<(Message, SocketAddr)> {
        let mut buf = [0u8; 1024 * 16];
        let (l, addr) = (sock.recv(&mut buf))?;
        let msg = (Message::from_bytes(&buf[0..l]))?;
        Ok((msg, addr))
    }
    fn strip_dnssec_records(&self) -> Message {
        let mut filtered = self.without_rr();
        const REMOVED_TYPES: [RecordType; 1] = [RecordType::OPT];
        let query_type = self.queries()[0].query_type();
        let f = |r: &&Record| -> bool {
            let t = r.rr_type();
            if t == query_type {
                return true;
            }
            if let RecordType::DNSSEC(_) = t {
                return false;
            }
            !REMOVED_TYPES.contains(&t)
        };
        self.answers().iter().filter(&f).for_each(|r| {
            filtered.add_answer(r.clone());
        });
        self.name_servers().iter().filter(&f).for_each(|r| {
            filtered.add_name_server(r.clone());
        });
        self.additionals().iter().filter(&f).for_each(|r| {
            filtered.add_additional(r.clone());
        });
        filtered
    }
    fn new_resp(&self) -> Message {
        let mut ret: Message = Message::new();
        ret.set_message_type(MessageType::Response);
        ret.set_id(self.id());
        ret.set_op_code(self.op_code());
        ret.set_recursion_desired(self.recursion_desired());
        for q in self.queries() {
            ret.add_query(q.clone());
        }
        ret
    }
    fn clone_resp(&self) -> Message {
        let mut ret = Message::new();
        ret.copy_resp_from(self);
        ret
    }
    fn clone_resp_for(&self, q: &Query) -> Message {
        let mut ret = self.clone_resp();
        ret.add_query(q.clone());
        ret
    }
    fn without_rr(&self) -> Message {
        // Simpler way to clear all answers
        let mut new_msg = self.truncate();
        assert!(new_msg.queries().is_empty());
        assert!(new_msg.answers().is_empty());
        assert!(new_msg.additionals().is_empty());
        new_msg.take_name_servers();
        new_msg.set_truncated(false);
        new_msg.set_checking_disabled(self.checking_disabled());
        new_msg.set_authentic_data(self.authentic_data());
        self.queries().iter().for_each(|q| {
            new_msg.add_query(q.clone());
        });
        new_msg
    }
    fn copy_resp_from(&mut self, other: &Message) {
        self.copy_resp_with(other, Record::clone)
    }
    fn copy_resp_with<F>(&mut self, other: &Message, mut f: F)
    where
        F: FnMut(&Record) -> Record,
    {
        self.set_response_code(other.response_code());
        self.set_message_type(other.message_type());
        other.answers().iter().map(|x| f(x)).for_each(|x| {
            self.add_answer(x);
        });
        other.name_servers().iter().map(|x| f(x)).for_each(|x| {
            self.add_name_server(x);
        });

        // RFC 2671 4.1: OPT should never be cached nor forwarded
        other
            .additionals()
            .iter()
            .filter(|x| x.rr_type() != RecordType::OPT)
            .map(|x| f(x))
            .for_each(|x| {
                self.add_additional(x);
            });
    }
    fn is_resp_for(&self, other: &Message) -> bool {
        assert_eq!(other.message_type(), MessageType::Query);
        if self.message_type() != MessageType::Response {
            return false;
        }
        if other.id() != self.id() {
            return false;
        }
        if other.op_code() != self.op_code() {
            return false;
        }
        assert_eq!(other.queries().len(), 1);
        if self.queries().len() != 1 {
            return false;
        }
        if other.queries()[0] != self.queries()[0] {
            return false;
        }
        true
    }
}
<|endoftext|>


<commit_before>/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Joseph Crail <jbcrail@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

// Based on the pattern using by Cargo, I created a shim over the
// standard PathExt trait, so that the unstable path methods could
// be backported to stable (<= 1.1). This will likely be dropped
// when the path trait stabilizes.

use ::libc;
use std::env;
use std::fs;
use std::io::{Error, ErrorKind, Result};
use std::path::{Component, Path, PathBuf};

pub trait UUPathExt {
    fn uu_exists(&self) -> bool;
    fn uu_is_file(&self) -> bool;
    fn uu_is_dir(&self) -> bool;
    fn uu_metadata(&self) -> Result<fs::Metadata>;
}

impl UUPathExt for Path {
    fn uu_exists(&self) -> bool {
        fs::metadata(self).is_ok()
    }

    fn uu_is_file(&self) -> bool {
        fs::metadata(self).map(|m| m.is_file()).unwrap_or(false)
    }

    fn uu_is_dir(&self) -> bool {
        fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false)
    }

    fn uu_metadata(&self) -> Result<fs::Metadata> {
        fs::metadata(self)
    }
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum CanonicalizeMode {
    None,
    Normal,
    Existing,
    Missing,
}

fn resolve<P: AsRef<Path>>(original: P) -> Result<PathBuf> {
    const MAX_LINKS_FOLLOWED: u32 = 255;
    let mut followed = 0;
    let mut result = original.as_ref().to_path_buf();
    loop {
        if followed == MAX_LINKS_FOLLOWED {
            return Err(Error::new(ErrorKind::InvalidInput, "maximum links followed"));
        }

        match fs::metadata(&result) {
            Err(e) => return Err(e),
            Ok(ref m) if !m.file_type().is_symlink() => break,
            Ok(..) => {
                followed += 1;
                match fs::read_link(&result) {
                    Ok(path) => {
                        result.pop();
                        result.push(path);
                    },
                    Err(e) => {
                        return Err(e);
                    }
                }
            }
        }
    }
    Ok(result)
}

pub fn canonicalize<P: AsRef<Path>>(original: P, can_mode: CanonicalizeMode) -> Result<PathBuf> {
    // Create an absolute path
    let original = original.as_ref();
    let original = if original.is_absolute() {
        original.to_path_buf()
    } else {
        env::current_dir().unwrap().join(original)
    };

    let mut result = PathBuf::new();
    let mut parts = vec!();

    // Split path by directory separator; add prefix (Windows-only) and root
    // directory to final path buffer; add remaining parts to temporary
    // vector for canonicalization.
    for part in original.components() {
        match part {
            Component::Prefix(_) | Component::RootDir => {
                result.push(part.as_os_str());
            },
            Component::CurDir => {},
            Component::ParentDir => {
                parts.pop();
            },
            Component::Normal(_) => {
                parts.push(part.as_os_str());
            }
        }
    }

    // Resolve the symlinks where possible
    if parts.len() > 0 {
        for part in parts[..parts.len()-1].iter() {
            result.push(part);

            if can_mode == CanonicalizeMode::None {
                continue;
            }

            match resolve(&result) {
                Err(e) => match can_mode {
                    CanonicalizeMode::Missing => continue,
                    _ => return Err(e)
                },
                Ok(path) => {
                    result.pop();
                    result.push(path);
                }
            }
        }

        result.push(parts.last().unwrap());

        match resolve(&result) {
            Err(e) => { if can_mode == CanonicalizeMode::Existing { return Err(e); } },
            Ok(path) => {
                result.pop();
                result.push(path);
            }
        }
    }
    Ok(result)
}

#[cfg(unix)]
pub fn is_stdin_interactive() -> bool {
    unsafe { libc::isatty(libc::STDIN_FILENO) == 1 }
}

#[cfg(windows)]
pub fn is_stdin_interactive() -> bool {
    0
}

#[cfg(unix)]
pub fn is_stdout_interactive() -> bool {
    unsafe { libc::isatty(libc::STDOUT_FILENO) == 1 }
}

#[cfg(windows)]
pub fn is_stdout_interactive() -> bool {
    0
}

#[cfg(unix)]
pub fn is_stderr_interactive() -> bool {
    unsafe { libc::isatty(libc::STDERR_FILENO) == 1 }
}

#[cfg(windows)]
pub fn is_stderr_interactive() -> bool {
    0
}
<commit_msg>Fix errors with bools represented as ints.<commit_after>/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Joseph Crail <jbcrail@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

// Based on the pattern using by Cargo, I created a shim over the
// standard PathExt trait, so that the unstable path methods could
// be backported to stable (<= 1.1). This will likely be dropped
// when the path trait stabilizes.

use ::libc;
use std::env;
use std::fs;
use std::io::{Error, ErrorKind, Result};
use std::path::{Component, Path, PathBuf};

pub trait UUPathExt {
    fn uu_exists(&self) -> bool;
    fn uu_is_file(&self) -> bool;
    fn uu_is_dir(&self) -> bool;
    fn uu_metadata(&self) -> Result<fs::Metadata>;
}

impl UUPathExt for Path {
    fn uu_exists(&self) -> bool {
        fs::metadata(self).is_ok()
    }

    fn uu_is_file(&self) -> bool {
        fs::metadata(self).map(|m| m.is_file()).unwrap_or(false)
    }

    fn uu_is_dir(&self) -> bool {
        fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false)
    }

    fn uu_metadata(&self) -> Result<fs::Metadata> {
        fs::metadata(self)
    }
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum CanonicalizeMode {
    None,
    Normal,
    Existing,
    Missing,
}

fn resolve<P: AsRef<Path>>(original: P) -> Result<PathBuf> {
    const MAX_LINKS_FOLLOWED: u32 = 255;
    let mut followed = 0;
    let mut result = original.as_ref().to_path_buf();
    loop {
        if followed == MAX_LINKS_FOLLOWED {
            return Err(Error::new(ErrorKind::InvalidInput, "maximum links followed"));
        }

        match fs::metadata(&result) {
            Err(e) => return Err(e),
            Ok(ref m) if !m.file_type().is_symlink() => break,
            Ok(..) => {
                followed += 1;
                match fs::read_link(&result) {
                    Ok(path) => {
                        result.pop();
                        result.push(path);
                    },
                    Err(e) => {
                        return Err(e);
                    }
                }
            }
        }
    }
    Ok(result)
}

pub fn canonicalize<P: AsRef<Path>>(original: P, can_mode: CanonicalizeMode) -> Result<PathBuf> {
    // Create an absolute path
    let original = original.as_ref();
    let original = if original.is_absolute() {
        original.to_path_buf()
    } else {
        env::current_dir().unwrap().join(original)
    };

    let mut result = PathBuf::new();
    let mut parts = vec!();

    // Split path by directory separator; add prefix (Windows-only) and root
    // directory to final path buffer; add remaining parts to temporary
    // vector for canonicalization.
    for part in original.components() {
        match part {
            Component::Prefix(_) | Component::RootDir => {
                result.push(part.as_os_str());
            },
            Component::CurDir => {},
            Component::ParentDir => {
                parts.pop();
            },
            Component::Normal(_) => {
                parts.push(part.as_os_str());
            }
        }
    }

    // Resolve the symlinks where possible
    if parts.len() > 0 {
        for part in parts[..parts.len()-1].iter() {
            result.push(part);

            if can_mode == CanonicalizeMode::None {
                continue;
            }

            match resolve(&result) {
                Err(e) => match can_mode {
                    CanonicalizeMode::Missing => continue,
                    _ => return Err(e)
                },
                Ok(path) => {
                    result.pop();
                    result.push(path);
                }
            }
        }

        result.push(parts.last().unwrap());

        match resolve(&result) {
            Err(e) => { if can_mode == CanonicalizeMode::Existing { return Err(e); } },
            Ok(path) => {
                result.pop();
                result.push(path);
            }
        }
    }
    Ok(result)
}

#[cfg(unix)]
pub fn is_stdin_interactive() -> bool {
    unsafe { libc::isatty(libc::STDIN_FILENO) == 1 }
}

#[cfg(windows)]
pub fn is_stdin_interactive() -> bool {
    false
}

#[cfg(unix)]
pub fn is_stdout_interactive() -> bool {
    unsafe { libc::isatty(libc::STDOUT_FILENO) == 1 }
}

#[cfg(windows)]
pub fn is_stdout_interactive() -> bool {
    false
}

#[cfg(unix)]
pub fn is_stderr_interactive() -> bool {
    unsafe { libc::isatty(libc::STDERR_FILENO) == 1 }
}

#[cfg(windows)]
pub fn is_stderr_interactive() -> bool {
    false
}
<|endoftext|>


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

/* Unimplemented! */

<commit_msg>Removed v2::export<commit_after><|endoftext|>


<commit_before>// run-pass
// ignore-windows - this is a unix-specific test
// ignore-cloudabi
// ignore-emscripten
// ignore-sgx
// ignore-musl - returns dummy result for _SC_NGROUPS_MAX

#![feature(rustc_private)]
#![feature(setgroups)]

extern crate libc;
use std::process::Command;
use std::os::unix::process::CommandExt;

fn main() {
    #[cfg(unix)]
    run()
}

#[cfg(unix)]
fn run() {
    let max_ngroups = unsafe { libc::sysconf(libc::_SC_NGROUPS_MAX) };
    let max_ngroups = max_ngroups as u32 + 1;
    let vec: Vec<u32> = (0..max_ngroups).collect();
    let p = Command::new("/bin/id").groups(&vec[..]).spawn();
    assert!(p.is_err());
}
<commit_msg>Remove unnecessary `ignore-cloudabi` flag<commit_after>// run-pass
// ignore-windows - this is a unix-specific test
// ignore-emscripten
// ignore-sgx
// ignore-musl - returns dummy result for _SC_NGROUPS_MAX

#![feature(rustc_private)]
#![feature(setgroups)]

extern crate libc;
use std::process::Command;
use std::os::unix::process::CommandExt;

fn main() {
    #[cfg(unix)]
    run()
}

#[cfg(unix)]
fn run() {
    let max_ngroups = unsafe { libc::sysconf(libc::_SC_NGROUPS_MAX) };
    let max_ngroups = max_ngroups as u32 + 1;
    let vec: Vec<u32> = (0..max_ngroups).collect();
    let p = Command::new("/bin/id").groups(&vec[..]).spawn();
    assert!(p.is_err());
}
<|endoftext|>