<commit_before>// memory debug window
extern crate minifb;
use minifb::*;
use std::io::Write;
use c64;
use utils;
mod font;

const DEBUG_W: usize = 640;
const DEBUG_H: usize = 416;

pub struct Debugger
{
    debug_window: minifb::Window,
    font: font::SysFont,
    window_buffer: Vec<u32>,
    mempage_offset: u32,
}

impl Debugger
{
    pub fn new() -> Debugger
    {
        Debugger {
            debug_window: Window::new("Debug window", DEBUG_W, DEBUG_H, Scale::X2).unwrap(),
            font: font::SysFont::new(DEBUG_W, DEBUG_H),
            window_buffer: vec![0; DEBUG_W * DEBUG_H],
            mempage_offset: 0,
        }
    }

    pub fn render(&mut self, cpu: &mut c64::cpu::CPUShared, memory: &mut c64::memory::MemShared)
    {
        if self.debug_window.is_key_pressed(Key::PageUp, KeyRepeat::Yes)
        {
            self.mempage_offset += 0x400;
            if self.mempage_offset > 0xFC00 { self.mempage_offset = 0; }
        }

        if self.debug_window.is_key_pressed(Key::PageDown, KeyRepeat::Yes)
        {
            if self.mempage_offset == 0x0000 { self.mempage_offset = 0x10000; }
            self.mempage_offset -= 0x400;
        }

        self.draw_border();

        // dump memory page to screen
        let mut start = 0x0000 + self.mempage_offset as u16;

        let mut title = Vec::new();
        let _ = write!(&mut title, "Memory page ${:04x}-${:04x}", start, start + 0x3FF);
        self.font.draw_text(&mut self.window_buffer, 0, 0, &String::from_utf8(title).unwrap().to_owned()[..], 0x0A);
        let mut hex_offset_x = 0;

        for y in 0..25
        {
            for x in 0..40
            {
                let byte = memory.borrow_mut().get_ram_bank(c64::memory::MemType::RAM).read(start);
                self.font.draw_char(&mut self.window_buffer, 8*x as usize, 8 + 8*y as usize, byte, 0x05);

                self.draw_hex(hex_offset_x + x as usize, 27 + y as usize, byte);
                hex_offset_x += 1;
                start += 1;
            }

            hex_offset_x = 0;
        }

        self.draw_gfx_mode(memory);
        self.draw_data(memory);
        self.draw_cpu(cpu);

        self.debug_window.update(&self.window_buffer);
    }

    fn draw_hex(&mut self, x_pos: usize, y_pos: usize, byte: u8 )
    {
        let mut hex_value = Vec::new();
        let _ = write!(&mut hex_value, "{:02X}", byte);

        let mut base_color = utils::fetch_c64_color_rgba(byte >> 4);
        if base_color == 0 { base_color = 0x00333333; }
        //self.set_saturation(&mut base_color, (byte >> 4) as f64 / 15.0);

        // all black? make it at least somewhat visible
        if byte == 0 { base_color = 0x00101010; }

        self.font.draw_text_rgb(&mut self.window_buffer, x_pos, y_pos, &String::from_utf8(hex_value).unwrap().to_owned()[..], base_color);
    }

    fn draw_data(&mut self, memory: &mut c64::memory::MemShared)
    {
        let d018 = memory.borrow_mut().get_ram_bank(c64::memory::MemType::IO).read(0xD018);
        let dd00 = memory.borrow_mut().get_ram_bank(c64::memory::MemType::IO).read(0xDD00);

        let mut vmatrix_txt = Vec::new();
        let mut char_txt = Vec::new();
        let mut bmp_txt = Vec::new();
        let mut bank_txt = Vec::new();
        let _ = write!(&mut vmatrix_txt, "${:04X}", 0x400 * ((d018 >> 4) & 0xF) as u16);
        let _ = write!(&mut char_txt, "${:04X}", 0x800 * ((d018 >> 1) & 0x07) as u16);
        let _ = write!(&mut bmp_txt, "${:04X}", 0x2000 * ((d018 >> 3) & 0x01) as u16);
        let _ = write!(&mut bank_txt, "${:04X}", 0xC000 - 0x4000 * (dd00 & 0x03) as u16);
        self.font.draw_text(&mut self.window_buffer, 43, 3, "Screen: ", 0x0F);
        self.font.draw_text(&mut self.window_buffer, 51, 3, &String::from_utf8(vmatrix_txt).unwrap().to_owned()[..], 0x0E);
        self.font.draw_text(&mut self.window_buffer, 45, 4, "Char: ", 0x0F);
        self.font.draw_text(&mut self.window_buffer, 51, 4, &String::from_utf8(char_txt).unwrap().to_owned()[..], 0x0E);
        self.font.draw_text(&mut self.window_buffer, 43, 5, "Bitmap: ", 0x0F);
        self.font.draw_text(&mut self.window_buffer, 51, 5, &String::from_utf8(bmp_txt).unwrap().to_owned()[..], 0x0E);
        self.font.draw_text(&mut self.window_buffer, 41, 6, "VIC Bank: ", 0x0F);
        self.font.draw_text(&mut self.window_buffer, 51, 6, &String::from_utf8(bank_txt).unwrap().to_owned()[..], 0x0E);
    }

    fn draw_gfx_mode(&mut self, memory: &mut c64::memory::MemShared)
    {
        let d011 = memory.borrow_mut().get_ram_bank(c64::memory::MemType::IO).read(0xD011);
        let d016 = memory.borrow_mut().get_ram_bank(c64::memory::MemType::IO).read(0xD016);
        let ecm_on = (d011 & 0x40) != 0;
        let mcm_on = (d016 & 0x10) != 0;
        let bmp_on = (d011 & 0x20) != 0;

        self.font.draw_text(&mut self.window_buffer, 52, 1, "ECM", if ecm_on { 0x0A } else { 0x0B });
        self.font.draw_text(&mut self.window_buffer, 57, 1, "CHR", if !bmp_on & !ecm_on { 0x0A } else { 0x0B });
        self.font.draw_text(&mut self.window_buffer, 62, 1, "BMP", if bmp_on { 0x0A } else { 0x0B });
        self.font.draw_text(&mut self.window_buffer, 67, 1, "MCM", if mcm_on { 0x0A } else { 0x0B });
    }

    fn draw_cpu(&mut self, cpu: &mut c64::cpu::CPUShared)
    {
        let mut pc_txt = Vec::new();
        let mut a_txt = Vec::new();
        let mut x_txt = Vec::new();
        let mut y_txt = Vec::new();
        let mut sp_txt = Vec::new();
        let mut p_txt = Vec::new();
        let _ = write!(&mut pc_txt, "${:04X}", cpu.borrow_mut().PC);
        let _ = write!(&mut a_txt, "${:02X}", cpu.borrow_mut().A);
        let _ = write!(&mut x_txt, "${:02X}", cpu.borrow_mut().X);
        let _ = write!(&mut y_txt, "${:02X}", cpu.borrow_mut().Y);
        let _ = write!(&mut sp_txt, "${:02X}", cpu.borrow_mut().SP);
        let _ = write!(&mut p_txt, "[{:08b}]", cpu.borrow_mut().P);

        self.font.draw_text(&mut self.window_buffer, 44, 23, "PC:", 0x0F);
        self.font.draw_text(&mut self.window_buffer, 47, 23, &String::from_utf8(pc_txt).unwrap().to_owned()[..], 0x0E);
        self.font.draw_text(&mut self.window_buffer, 53, 23, "A:", 0x0F);
        self.font.draw_text(&mut self.window_buffer, 55, 23, &String::from_utf8(a_txt).unwrap().to_owned()[..], 0x0E);
        self.font.draw_text(&mut self.window_buffer, 59, 23, "X:", 0x0F);
        self.font.draw_text(&mut self.window_buffer, 61, 23, &String::from_utf8(x_txt).unwrap().to_owned()[..], 0x0E);
        self.font.draw_text(&mut self.window_buffer, 65, 23, "Y:", 0x0F);
        self.font.draw_text(&mut self.window_buffer, 67, 23, &String::from_utf8(y_txt).unwrap().to_owned()[..], 0x0E);
        self.font.draw_text(&mut self.window_buffer, 71, 23, "SP:", 0x0F);
        self.font.draw_text(&mut self.window_buffer, 74, 23, &String::from_utf8(sp_txt).unwrap().to_owned()[..], 0x0E);
        self.font.draw_text(&mut self.window_buffer, 51, 24, "NV-BDIZC:", 0x0F);
        self.font.draw_text(&mut self.window_buffer, 61, 24, &String::from_utf8(p_txt).unwrap().to_owned()[..], 0x0E);
    }

    fn draw_border(&mut self)
    {
        for x in 0..80
        {
            self.font.draw_char(&mut self.window_buffer, 8*x as usize, 0, 64, 0x0B);
            self.font.draw_char(&mut self.window_buffer, 8*x as usize, 8*26, 64, 0x0B);
        }

        for y in 1..26
        {
            self.font.draw_char(&mut self.window_buffer, 8*40, 8*y as usize, 66, 0x0B);
        }

        self.font.draw_char(&mut self.window_buffer, 8*40, 0, 114, 0x0B);
        self.font.draw_char(&mut self.window_buffer, 8*40, 8*26, 113, 0x0B);
    }

   /* fn set_saturation(&self, color: &mut u32, change: f64)
    {
        let Pr = 0.299;
        let Pg = 0.587;
        let Pb = 0.114;
        let mut r = ((*color >> 16) & 0xFF) as f64;
        let mut g = ((*color >> 8) & 0xFF) as f64;
        let mut b = (*color & 0xFF) as f64;

        let P = ((r*r*Pr + g*g*Pg + b*b*Pb) as f64).sqrt();

        r = P + (r - P) * change;
        g = P + (g - P) * change;
        b = P + (b - P) * change;

        *color = (r as u32) << 16;
        *color |= (g as u32) << 8;
        *color |= b as u32;
    }*/
}
<commit_msg>[debug] added more diagnostic info<commit_after>// memory debug window
extern crate minifb;
use minifb::*;
use std::io::Write;
use c64;
use utils;
mod font;

const DEBUG_W: usize = 640;
const DEBUG_H: usize = 416;

pub struct Debugger
{
    debug_window: minifb::Window,
    font: font::SysFont,
    window_buffer: Vec<u32>,
    mempage_offset: u32, // RAM preview memory page offset
    draw_mode: u8,
}

impl Debugger
{
    pub fn new() -> Debugger
    {
        Debugger {
            debug_window: Window::new("Debug window", DEBUG_W, DEBUG_H, Scale::X2).unwrap(),
            font: font::SysFont::new(DEBUG_W, DEBUG_H),
            window_buffer: vec![0; DEBUG_W * DEBUG_H],
            mempage_offset: 0,
            draw_mode: 0,
        }
    }

    pub fn render(&mut self, cpu: &mut c64::cpu::CPUShared, memory: &mut c64::memory::MemShared)
    {
        self.draw_border();

        if self.debug_window.is_key_pressed(Key::End, KeyRepeat::No)
        {
            self.draw_mode += 1;
            if self.draw_mode > 3 { self.draw_mode = 0; }

            // clear memdump
            for y in 1..26
            {
                for x in 0..40
                {
                    self.clear_char(x, y);
                }
            }

            // clear hex region
            for y in 28..52
            {
                for x in 0..80
                {
                    self.clear_char(x, y);
                }
            }
        }

        match self.draw_mode {
            0 => self.draw_ram(memory),
            1 => self.draw_vic(memory),
            2 => self.draw_cia(memory),
            3 => self.draw_color_ram(memory),
            _ => ()
        }

        self.draw_gfx_mode(memory);
        self.draw_data(memory);
        self.draw_cpu(cpu);

        self.debug_window.update(&self.window_buffer);
    }

    fn draw_ram(&mut self, memory: &mut c64::memory::MemShared)
    {
        if self.debug_window.is_key_pressed(Key::PageUp, KeyRepeat::Yes)
        {
            self.mempage_offset += 0x400;
            if self.mempage_offset > 0xFC00 { self.mempage_offset = 0; }
        }

        if self.debug_window.is_key_pressed(Key::PageDown, KeyRepeat::Yes)
        {
            if self.mempage_offset == 0x0000 { self.mempage_offset = 0x10000; }
            self.mempage_offset -= 0x400;
        }

        // dump memory page to screen
        let mut start = 0x0000 + self.mempage_offset as u16;

        let mut title = Vec::new();
        let _ = write!(&mut title, "Memory page ${:04x}-${:04x}", start, start + 0x3FF);
        self.font.draw_text(&mut self.window_buffer, 0, 0, &String::from_utf8(title).unwrap().to_owned()[..], 0x0A);
        self.font.draw_text(&mut self.window_buffer, 34, 0, "*RAM*", 0x0E);

        let mut hex_offset_x = 0;

        for y in 0..25
        {
            for x in 0..40
            {
                let byte = memory.borrow_mut().get_ram_bank(c64::memory::MemType::RAM).read(start);
                self.font.draw_char(&mut self.window_buffer, 8*x as usize, 8 + 8*y as usize, byte, 0x05);

                self.draw_hex(hex_offset_x + x as usize, 27 + y as usize, byte);
                hex_offset_x += 1;
                start += 1;
            }

            hex_offset_x = 0;
        }
    }

    fn draw_vic(&mut self, memory: &mut c64::memory::MemShared)
    {
        let mut start = 0xD000;

        let mut title = Vec::new();
        let _ = write!(&mut title, "VIC ${:04x}-${:04x}", start, start + 0x03F);
        self.font.draw_text(&mut self.window_buffer, 0, 0, &String::from_utf8(title).unwrap().to_owned()[..], 0x0A);
        self.font.draw_text(&mut self.window_buffer, 34, 0, "*VIC*", 0x0E);

        let mut hex_offset_x = 0;

        for y in 0..25
        {
            for x in 0..40
            {
                let byte = memory.borrow_mut().get_ram_bank(c64::memory::MemType::IO).read(start);
                self.font.draw_char(&mut self.window_buffer, 8*x as usize, 8 + 8*y as usize, byte, 0x05);

                self.draw_hex(hex_offset_x + x as usize, 27 + y as usize, byte);
                hex_offset_x += 1;
                start += 1;

                if start == 0xD040 { return; }
            }

            hex_offset_x = 0;
        }
    }

    fn draw_cia(&mut self, memory: &mut c64::memory::MemShared)
    {
        let mut start = 0xDC00;

        let mut title = Vec::new();
        let _ = write!(&mut title, "CIA ${:04x}-${:04x}", start, start + 0x1FF);
        self.font.draw_text(&mut self.window_buffer, 0, 0, &String::from_utf8(title).unwrap().to_owned()[..], 0x0A);
        self.font.draw_text(&mut self.window_buffer, 34, 0, "*CIA*", 0x0E);

        let mut hex_offset_x = 0;

        for y in 0..25
        {
            for x in 0..40
            {
                let byte = memory.borrow_mut().get_ram_bank(c64::memory::MemType::IO).read(start);
                self.font.draw_char(&mut self.window_buffer, 8*x as usize, 8 + 8*y as usize, byte, 0x05);

                self.draw_hex(hex_offset_x + x as usize, 27 + y as usize, byte);
                hex_offset_x += 1;
                start += 1;

                if start == 0xDE00 { return; }
            }

            hex_offset_x = 0;
        }
    }

    fn draw_color_ram(&mut self, memory: &mut c64::memory::MemShared)
    {
        let mut start = 0xD800;

        let mut title = Vec::new();
        let _ = write!(&mut title, "COLOR ${:04x}-${:04x}", start, start + 0x3FF);
        self.font.draw_text(&mut self.window_buffer, 0, 0, &String::from_utf8(title).unwrap().to_owned()[..], 0x0A);
        self.font.draw_text(&mut self.window_buffer, 28, 0, "*COLOR RAM*", 0x0E);

        let mut hex_offset_x = 0;

        for y in 0..25
        {
            for x in 0..40
            {
                let byte = memory.borrow_mut().get_ram_bank(c64::memory::MemType::IO).read(start);
                self.font.draw_char(&mut self.window_buffer, 8*x as usize, 8 + 8*y as usize, byte, 0x05);

                self.draw_hex(hex_offset_x + x as usize, 27 + y as usize, byte);
                hex_offset_x += 1;
                start += 1;

                if start == 0xDC00 { return; }
            }

            hex_offset_x = 0;
        }
    }

    fn draw_hex(&mut self, x_pos: usize, y_pos: usize, byte: u8 )
    {
        let mut hex_value = Vec::new();
        let _ = write!(&mut hex_value, "{:02X}", byte);

        let mut base_color = utils::fetch_c64_color_rgba(byte >> 4);
        if base_color == 0 { base_color = 0x00333333; }
        //self.set_saturation(&mut base_color, (byte >> 4) as f64 / 15.0);

        // all black? make it at least somewhat visible
        if byte == 0 { base_color = 0x00101010; }

        self.font.draw_text_rgb(&mut self.window_buffer, x_pos, y_pos, &String::from_utf8(hex_value).unwrap().to_owned()[..], base_color);
    }

    fn draw_data(&mut self, memory: &mut c64::memory::MemShared)
    {
        let d018 = memory.borrow_mut().get_ram_bank(c64::memory::MemType::IO).read(0xD018);
        let dd00 = memory.borrow_mut().get_ram_bank(c64::memory::MemType::IO).read(0xDD00);

        let mut vmatrix_txt = Vec::new();
        let mut char_txt = Vec::new();
        let mut bmp_txt = Vec::new();
        let mut bank_txt = Vec::new();
        let _ = write!(&mut vmatrix_txt, "${:04X}", 0x400 * ((d018 >> 4) & 0xF) as u16);
        let _ = write!(&mut char_txt, "${:04X}", 0x800 * ((d018 >> 1) & 0x07) as u16);
        let _ = write!(&mut bmp_txt, "${:04X}", 0x2000 * ((d018 >> 3) & 0x01) as u16);
        let _ = write!(&mut bank_txt, "${:04X}", 0xC000 - 0x4000 * (dd00 & 0x03) as u16);
        self.font.draw_text(&mut self.window_buffer, 43, 3, "Screen: ", 0x0F);
        self.font.draw_text(&mut self.window_buffer, 51, 3, &String::from_utf8(vmatrix_txt).unwrap().to_owned()[..], 0x0E);
        self.font.draw_text(&mut self.window_buffer, 45, 4, "Char: ", 0x0F);
        self.font.draw_text(&mut self.window_buffer, 51, 4, &String::from_utf8(char_txt).unwrap().to_owned()[..], 0x0E);
        self.font.draw_text(&mut self.window_buffer, 43, 5, "Bitmap: ", 0x0F);
        self.font.draw_text(&mut self.window_buffer, 51, 5, &String::from_utf8(bmp_txt).unwrap().to_owned()[..], 0x0E);
        self.font.draw_text(&mut self.window_buffer, 41, 6, "VIC Bank: ", 0x0F);
        self.font.draw_text(&mut self.window_buffer, 51, 6, &String::from_utf8(bank_txt).unwrap().to_owned()[..], 0x0E);
    }

    fn draw_gfx_mode(&mut self, memory: &mut c64::memory::MemShared)
    {
        let d011 = memory.borrow_mut().get_ram_bank(c64::memory::MemType::IO).read(0xD011);
        let d016 = memory.borrow_mut().get_ram_bank(c64::memory::MemType::IO).read(0xD016);
        let ecm_on = (d011 & 0x40) != 0;
        let mcm_on = (d016 & 0x10) != 0;
        let bmp_on = (d011 & 0x20) != 0;

        self.font.draw_text(&mut self.window_buffer, 52, 1, "ECM", if ecm_on { 0x0A } else { 0x0B });
        self.font.draw_text(&mut self.window_buffer, 57, 1, "CHR", if !bmp_on & !ecm_on { 0x0A } else { 0x0B });
        self.font.draw_text(&mut self.window_buffer, 62, 1, "BMP", if bmp_on { 0x0A } else { 0x0B });
        self.font.draw_text(&mut self.window_buffer, 67, 1, "MCM", if mcm_on { 0x0A } else { 0x0B });
    }

    fn draw_cpu(&mut self, cpu: &mut c64::cpu::CPUShared)
    {
        let mut pc_txt = Vec::new();
        let mut a_txt = Vec::new();
        let mut x_txt = Vec::new();
        let mut y_txt = Vec::new();
        let mut sp_txt = Vec::new();
        let mut p_txt = Vec::new();
        let _ = write!(&mut pc_txt, "${:04X}", cpu.borrow_mut().PC);
        let _ = write!(&mut a_txt, "${:02X}", cpu.borrow_mut().A);
        let _ = write!(&mut x_txt, "${:02X}", cpu.borrow_mut().X);
        let _ = write!(&mut y_txt, "${:02X}", cpu.borrow_mut().Y);
        let _ = write!(&mut sp_txt, "${:02X}", cpu.borrow_mut().SP);
        let _ = write!(&mut p_txt, "[{:08b}]", cpu.borrow_mut().P);

        self.font.draw_text(&mut self.window_buffer, 44, 23, "PC:", 0x0F);
        self.font.draw_text(&mut self.window_buffer, 47, 23, &String::from_utf8(pc_txt).unwrap().to_owned()[..], 0x0E);
        self.font.draw_text(&mut self.window_buffer, 53, 23, "A:", 0x0F);
        self.font.draw_text(&mut self.window_buffer, 55, 23, &String::from_utf8(a_txt).unwrap().to_owned()[..], 0x0E);
        self.font.draw_text(&mut self.window_buffer, 59, 23, "X:", 0x0F);
        self.font.draw_text(&mut self.window_buffer, 61, 23, &String::from_utf8(x_txt).unwrap().to_owned()[..], 0x0E);
        self.font.draw_text(&mut self.window_buffer, 65, 23, "Y:", 0x0F);
        self.font.draw_text(&mut self.window_buffer, 67, 23, &String::from_utf8(y_txt).unwrap().to_owned()[..], 0x0E);
        self.font.draw_text(&mut self.window_buffer, 71, 23, "SP:", 0x0F);
        self.font.draw_text(&mut self.window_buffer, 74, 23, &String::from_utf8(sp_txt).unwrap().to_owned()[..], 0x0E);
        self.font.draw_text(&mut self.window_buffer, 51, 24, "NV-BDIZC:", 0x0F);
        self.font.draw_text(&mut self.window_buffer, 61, 24, &String::from_utf8(p_txt).unwrap().to_owned()[..], 0x0E);
    }

    fn draw_border(&mut self)
    {
        for x in 0..80
        {
            self.font.draw_char(&mut self.window_buffer, 8*x as usize, 0, 64, 0x0B);
            self.font.draw_char(&mut self.window_buffer, 8*x as usize, 8*26, 64, 0x0B);
        }

        for y in 1..26
        {
            self.font.draw_char(&mut self.window_buffer, 8*40, 8*y as usize, 66, 0x0B);
        }

        self.font.draw_char(&mut self.window_buffer, 8*40, 0, 114, 0x0B);
        self.font.draw_char(&mut self.window_buffer, 8*40, 8*26, 113, 0x0B);
    }

    fn clear_char(&mut self, x_pos: usize, y_pos: usize)
    {
        self.font.draw_text(&mut self.window_buffer, x_pos, y_pos, " ", 0x00);
    }

   /* fn set_saturation(&self, color: &mut u32, change: f64)
    {
        let Pr = 0.299;
        let Pg = 0.587;
        let Pb = 0.114;
        let mut r = ((*color >> 16) & 0xFF) as f64;
        let mut g = ((*color >> 8) & 0xFF) as f64;
        let mut b = (*color & 0xFF) as f64;

        let P = ((r*r*Pr + g*g*Pg + b*b*Pb) as f64).sqrt();

        r = P + (r - P) * change;
        g = P + (g - P) * change;
        b = P + (b - P) * change;

        *color = (r as u32) << 16;
        *color |= (g as u32) << 8;
        *color |= b as u32;
    }*/
}
<|endoftext|>


<commit_before>use cpu::common_defs::OpcodeExecInfo;
use cpu::CpuState;
use cpu::DecodeRegister;
use cpu::common_defs::address_mode::AddressMode;
use cpu::common_defs::opcode_class::OpcodeClass;
use memory::Memory;
use std::collections::HashMap;

pub struct CpuExecutor {
    op_table: HashMap<u8,OpcodeExecInfo>,
}

impl CpuExecutor {

	/// Construct a new CpuExecutor.
    pub fn new(opcodes: Vec<OpcodeExecInfo> ) -> CpuExecutor {
        // Construct the HashMap and copy it over to CpuExecutor's constructor.
        let mut op_table_temp: HashMap<u8, OpcodeExecInfo> = HashMap::new();
        for oc in opcodes {
            if op_table_temp.contains_key(&oc.opcode) {
                println!("Encountered duplicate opcode: {:#x}", oc.opcode);
                println!("Replacing previous opcode, which was {{ opcode: {:#x}, len: {}, cycles: {}, page_cycles: {} }}", oc.opcode, oc.len, oc.cycles, oc.page_cycles);
            }
            op_table_temp.insert(oc.opcode, oc);
        }

        CpuExecutor {
            op_table: op_table_temp,
        }
    }

	/// Reset the given cpu_state.
    pub fn reset(self: &CpuExecutor, cpu_state: &mut CpuState, mem:&mut Memory) {
        cpu_state.pc = mem.read16(0xFFFC).unwrap();
        cpu_state.sp = 0xFD;
        cpu_state.pack_flags(0x24);
    }

    /// Execute a single instruction in the given memory and cpu_state context.
    pub fn step(self: &CpuExecutor, cpu_state: &mut CpuState,mem:&mut Memory) {
        self.fetch_and_decode(cpu_state,mem);
        let new_cpu_state = self.execute(cpu_state,mem);
        // Perform logging, recording here...
        *cpu_state = new_cpu_state
    }

	/// Fetch the next instruction and perform address resolution.
    pub fn fetch_and_decode(self: &CpuExecutor, cpu_state: &mut CpuState,mem:&mut Memory) {
        cpu_state.instruction_register = mem.read8(cpu_state.pc).unwrap();
        cpu_state.decode_register = self.decode(cpu_state,mem);
        cpu_state.pc = cpu_state.pc + cpu_state.decode_register.info.len as u16;
    }

    /// Perform address resolution, returning the info in a DecodeRegister.
    fn decode(self: &CpuExecutor, cpu_state: &CpuState, mem: &Memory) -> DecodeRegister {
        let mut dr = DecodeRegister {
            info : self.op_table[&cpu_state.instruction_register].clone(),
            ..Default::default()
        };
        match dr.info.address_mode {
            // no explicit addresses for the following modes
            AddressMode::Accumulator  => { },
            AddressMode::Implied      => { },

            // explicit addresses from here on out
            AddressMode::Absolute => {
                dr.addr_final  = Some(mem.read16(cpu_state.pc+1).unwrap());
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::AbsoluteX       => {
                dr.addr_final  = Some(mem.read16(cpu_state.pc+1).unwrap() + cpu_state.x as u16);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::AbsoluteY       => {
                dr.addr_final  = Some(mem.read16(cpu_state.pc+1).unwrap() + cpu_state.y as u16);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::Immediate       => {
                dr.addr_final  = Some(cpu_state.pc+1);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::Indirect        => {
                dr.addr_intermediate = Some(mem.read16(cpu_state.pc+1).unwrap());
                dr.addr_final        = Some(mem.read16(dr.addr_intermediate.unwrap()).unwrap());
            },
            AddressMode::IndexedIndirect => {
                dr.addr_intermediate = Some( (mem.read8(cpu_state.pc+1).unwrap() + cpu_state.x) as u16);
                dr.addr_final        = Some(mem.read16(dr.addr_intermediate.unwrap()).unwrap())
            },
            AddressMode::IndirectIndexed => {
                dr.addr_intermediate = Some(mem.read16(cpu_state.pc+1).unwrap());
                dr.addr_final        = Some(dr.addr_intermediate.unwrap() + cpu_state.y as u16);
            },
            AddressMode::Relative        => {
                dr.addr_final  = Some(cpu_state.pc+1);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::ZeroPage        => {
                dr.addr_final  = Some(mem.read8(cpu_state.pc+1).unwrap() as u16);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::ZeroPageX       => {
                dr.addr_final  = Some( (mem.read8(cpu_state.pc+1).unwrap() + cpu_state.x) as u16);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::ZeroPageY       => {
                dr.addr_final  = Some( (mem.read8(cpu_state.pc+1).unwrap() + cpu_state.y) as u16);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            _ => panic!("unrecognized addressing mode while decoding instruction_register!")
        }

        return dr;
    }

    /// Perform the current instruction, returning the CpuState after execution.
    pub fn execute(self: &CpuExecutor, mut cpu_state: &CpuState, mut mem:&Memory) -> CpuState {

    	// The state of the CPU after executing the current instruction.
    	let mut new_cpu_state = cpu_state.clone();

    	// Figure out which opcode is being executed.
    	let ref decode_register = cpu_state.decode_register;
    	match decode_register.info.opcode_class {

    		// LDA (Load Accumulator)
    		OpcodeClass::LDA => {
    			new_cpu_state.a = decode_register.value_final.unwrap();
    		},

    		// LDX (Load X)
    		OpcodeClass::LDX => {
    			new_cpu_state.x = decode_register.value_final.unwrap();
    		}

    		// LDY (Load Y)
    		OpcodeClass::LDY => {
    			new_cpu_state.y = decode_register.value_final.unwrap();
    		}

    		// NOP (No Operation)
    		OpcodeClass::NOP => {}

    		// Default: not sure what this opcode is.
			_ => panic!("Unrecognised opcode class")

    	}

    	// Expression returned is the updated cpu_state.
    	new_cpu_state
    }

}

<commit_msg>Execution for shift operators<commit_after>use cpu::common_defs::OpcodeExecInfo;
use cpu::CpuState;
use cpu::DecodeRegister;
use cpu::common_defs::address_mode::AddressMode;
use cpu::common_defs::opcode_class::OpcodeClass;
use memory::Memory;
use std::collections::HashMap;

pub struct CpuExecutor {
    op_table: HashMap<u8,OpcodeExecInfo>,
}

impl CpuExecutor {

	/// Construct a new CpuExecutor.
    pub fn new(opcodes: Vec<OpcodeExecInfo> ) -> CpuExecutor {
        // Construct the HashMap and copy it over to CpuExecutor's constructor.
        let mut op_table_temp: HashMap<u8, OpcodeExecInfo> = HashMap::new();
        for oc in opcodes {
            if op_table_temp.contains_key(&oc.opcode) {
                println!("Encountered duplicate opcode: {:#x}", oc.opcode);
                println!("Replacing previous opcode, which was {{ opcode: {:#x}, len: {}, cycles: {}, page_cycles: {} }}", oc.opcode, oc.len, oc.cycles, oc.page_cycles);
            }
            op_table_temp.insert(oc.opcode, oc);
        }

        CpuExecutor {
            op_table: op_table_temp,
        }
    }

	/// Reset the given cpu_state.
    pub fn reset(self: &CpuExecutor, cpu_state: &mut CpuState, mem:&mut Memory) {
        cpu_state.pc = mem.read16(0xFFFC).unwrap();
        cpu_state.sp = 0xFD;
        cpu_state.pack_flags(0x24);
    }

    /// Execute a single instruction in the given memory and cpu_state context.
    pub fn step(self: &CpuExecutor, cpu_state: &mut CpuState,mem:&mut Memory) {
        self.fetch_and_decode(cpu_state,mem);
        let new_cpu_state = self.execute(cpu_state,mem);
        // Perform logging, recording here...
        *cpu_state = new_cpu_state
    }

	/// Fetch the next instruction and perform address resolution.
    pub fn fetch_and_decode(self: &CpuExecutor, cpu_state: &mut CpuState,mem:&mut Memory) {
        cpu_state.instruction_register = mem.read8(cpu_state.pc).unwrap();
        cpu_state.decode_register = self.decode(cpu_state,mem);
        cpu_state.pc = cpu_state.pc + cpu_state.decode_register.info.len as u16;
    }

    /// Perform address resolution, returning the info in a DecodeRegister.
    fn decode(self: &CpuExecutor, cpu_state: &CpuState, mem: &Memory) -> DecodeRegister {
        let mut dr = DecodeRegister {
            info : self.op_table[&cpu_state.instruction_register].clone(),
            ..Default::default()
        };
        match dr.info.address_mode {
            // no explicit addresses for the following modes
            AddressMode::Accumulator  => { },
            AddressMode::Implied      => { },

            // explicit addresses from here on out
            AddressMode::Absolute => {
                dr.addr_final  = Some(mem.read16(cpu_state.pc+1).unwrap());
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::AbsoluteX       => {
                dr.addr_final  = Some(mem.read16(cpu_state.pc+1).unwrap() + cpu_state.x as u16);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::AbsoluteY       => {
                dr.addr_final  = Some(mem.read16(cpu_state.pc+1).unwrap() + cpu_state.y as u16);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::Immediate       => {
                dr.addr_final  = Some(cpu_state.pc+1);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::Indirect        => {
                dr.addr_intermediate = Some(mem.read16(cpu_state.pc+1).unwrap());
                dr.addr_final        = Some(mem.read16(dr.addr_intermediate.unwrap()).unwrap());
            },
            AddressMode::IndexedIndirect => {
                dr.addr_intermediate = Some( (mem.read8(cpu_state.pc+1).unwrap() + cpu_state.x) as u16);
                dr.addr_final        = Some(mem.read16(dr.addr_intermediate.unwrap()).unwrap())
            },
            AddressMode::IndirectIndexed => {
                dr.addr_intermediate = Some(mem.read16(cpu_state.pc+1).unwrap());
                dr.addr_final        = Some(dr.addr_intermediate.unwrap() + cpu_state.y as u16);
            },
            AddressMode::Relative        => {
                dr.addr_final  = Some(cpu_state.pc+1);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::ZeroPage        => {
                dr.addr_final  = Some(mem.read8(cpu_state.pc+1).unwrap() as u16);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::ZeroPageX       => {
                dr.addr_final  = Some( (mem.read8(cpu_state.pc+1).unwrap() + cpu_state.x) as u16);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::ZeroPageY       => {
                dr.addr_final  = Some( (mem.read8(cpu_state.pc+1).unwrap() + cpu_state.y) as u16);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            _ => panic!("unrecognized addressing mode while decoding instruction_register!")
        }

        return dr;
    }

    /// Perform the current instruction, returning the CpuState after execution.
    pub fn execute(self: &CpuExecutor, mut cpu_state: &CpuState, mut mem:&Memory) -> CpuState {

    	// The state of the CPU after executing the current instruction.
    	let mut new_cpu_state = cpu_state.clone();

    	// Figure out which opcode is being executed.
    	let ref decode_register = cpu_state.decode_register;

    	match decode_register.info.opcode_class {

    		// ASL (Arithmetic Shift Left)
    		OpcodeClass::ASL => {

				// Shift accumulator to the left.
				new_cpu_state.a = cpu_state.a << 1;
				// Carry flag gets set to the most significant bit.
				new_cpu_state.C = (128 & cpu_state.a) > 0;
				// Set zero flag if result is 0.
    			if new_cpu_state.a == 0 { new_cpu_state.Z = true }

    		},

    		// LDA (Load Accumulator)
    		OpcodeClass::LDA => {
    			new_cpu_state.a = decode_register.value_final.unwrap()
    		},

    		// LDX (Load X)
    		OpcodeClass::LDX => {
    			new_cpu_state.x = decode_register.value_final.unwrap()
    		},

    		// LDY (Load Y)
    		OpcodeClass::LDY => {
    			new_cpu_state.y = decode_register.value_final.unwrap()
    		},

    		// LSR (Logical Shift Right)
    		OpcodeClass::LSR => {

    			// Shift accumulator to the right.
    			new_cpu_state.a = cpu_state.a >> 1;
    			// Carry flag gets set to the least significant bit.
    			new_cpu_state.C = 1 & cpu_state.a > 0;
    			// Set zero flag if result is 0.
    			if new_cpu_state.a == 0 { new_cpu_state.Z = true }

    		},

    		// NOP (No Operation)
    		OpcodeClass::NOP => {},

    		// Default: not sure what this opcode is.
			_ => panic!("Unrecognised opcode class: {:?}", decode_register.info.opcode_class)

    	}

    	// Expression returned is the updated cpu_state.
    	new_cpu_state
    }

}

<|endoftext|>


<commit_before>// Extracted from the scopeguard crate
use core::ops::{Deref, DerefMut};

pub struct ScopeGuard<T, F>
where
    F: FnMut(&mut T),
{
    dropfn: F,
    value: T,
}

#[cfg_attr(feature = "inline-more", inline)]
pub fn guard<T, F>(value: T, dropfn: F) -> ScopeGuard<T, F>
where
    F: FnMut(&mut T),
{
    ScopeGuard { dropfn, value }
}

impl<T, F> Deref for ScopeGuard<T, F>
where
    F: FnMut(&mut T),
{
    type Target = T;
    #[cfg_attr(feature = "inline-more", inline)]
    fn deref(&self) -> &T {
        &self.value
    }
}

impl<T, F> DerefMut for ScopeGuard<T, F>
where
    F: FnMut(&mut T),
{
    #[cfg_attr(feature = "inline-more", inline)]
    fn deref_mut(&mut self) -> &mut T {
        &mut self.value
    }
}

impl<T, F> Drop for ScopeGuard<T, F>
where
    F: FnMut(&mut T),
{
    #[cfg_attr(feature = "inline-more", inline)]
    fn drop(&mut self) {
        (self.dropfn)(&mut self.value)
    }
}
<commit_msg>Auto merge of #242 - quininer:patch-2, r=Amanieu<commit_after>// Extracted from the scopeguard crate
use core::ops::{Deref, DerefMut};

pub struct ScopeGuard<T, F>
where
    F: FnMut(&mut T),
{
    dropfn: F,
    value: T,
}

#[inline]
pub fn guard<T, F>(value: T, dropfn: F) -> ScopeGuard<T, F>
where
    F: FnMut(&mut T),
{
    ScopeGuard { dropfn, value }
}

impl<T, F> Deref for ScopeGuard<T, F>
where
    F: FnMut(&mut T),
{
    type Target = T;
    #[inline]
    fn deref(&self) -> &T {
        &self.value
    }
}

impl<T, F> DerefMut for ScopeGuard<T, F>
where
    F: FnMut(&mut T),
{
    #[inline]
    fn deref_mut(&mut self) -> &mut T {
        &mut self.value
    }
}

impl<T, F> Drop for ScopeGuard<T, F>
where
    F: FnMut(&mut T),
{
    #[inline]
    fn drop(&mut self) {
        (self.dropfn)(&mut self.value)
    }
}
<|endoftext|>


<commit_before>use self::super::{Github, Result, Iter};
use serde::Deserialize;
use std::fmt;
use url::form_urlencoded;
use std::collections::HashMap;
use super::SortDirection;
use users::User;
use url;
use labels::Label;

/// Sort directions for pull requests
#[derive(Debug, PartialEq)]
pub enum SearchIssuesSort {
    /// Sort by time created
    Created,
    /// Sort by last updated
    Updated,
    /// Sort by number of comments
    Comments,
}

impl fmt::Display for SearchIssuesSort {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "{}",
               match *self {
                   SearchIssuesSort::Comments => "comments",
                   SearchIssuesSort::Created => "created",
                   SearchIssuesSort::Updated => "updated",
               })
    }
}

// https://developer.github.com/v3/search/#search-issues
pub struct Search<'a> {
    github: &'a Github,
}

fn items<D: Deserialize>(result: SearchResult<D>) -> Vec<D> {
    result.items
}

impl<'a> Search<'a> {
    pub fn new(github: &'a Github) -> Search<'a> {
        Search { github: github }
    }

    /// return a reference to a search interface for issues
    pub fn issues(&self) -> SearchIssues {
        SearchIssues::new(&self)
    }

    fn iter<D: Deserialize>(&'a self, url: &str) -> Result<Iter<'a, SearchResult<D>, D>> {
        self.github.iter(url.to_owned(), items)
    }

    fn search<D: Deserialize>(&self, url: &str) -> Result<SearchResult<D>> {
        self.github.get::<SearchResult<D>>(url)
    }
}

// https://developer.github.com/v3/search/#search-issues
pub struct SearchIssues<'a> {
    search: &'a Search<'a>,
}

impl<'a> SearchIssues<'a> {
    pub fn new(search: &'a Search<'a>) -> SearchIssues<'a> {
        SearchIssues { search: search }
    }

    fn search_uri<Q>(q: Q, options: &SearchIssuesOptions) -> String
        where Q: Into<String>
    {
        let mut uri = vec!["/search/issues".to_string()];
        let query_options = options.serialize().unwrap_or(String::new());
        let query =
            form_urlencoded::Serializer::new(query_options).append_pair("q", &q.into()).finish();
        uri.push(query);
        uri.join("?")
    }

    /// returns an Iterator over pages of search results
    pub fn iter<Q>(&'a self,
                   q: Q,
                   options: &SearchIssuesOptions)
                   -> Result<Iter<'a, SearchResult<SearchIssuesItem>, SearchIssuesItem>>
        where Q: Into<String>
    {
        self.search.iter::<SearchIssuesItem>(&Self::search_uri(q, options))
    }

    /// returns a single page of search results
    pub fn list<Q>(&self,
                   q: Q,
                   options: &SearchIssuesOptions)
                   -> Result<SearchResult<SearchIssuesItem>>
        where Q: Into<String>
    {
        self.search.search::<SearchIssuesItem>(&Self::search_uri(q, options))
    }
}

// representations

#[derive(Default)]
pub struct SearchIssuesOptions {
    params: HashMap<&'static str, String>,
}

impl SearchIssuesOptions {
    pub fn builder() -> SearchIssuesOptionsBuilder {
        SearchIssuesOptionsBuilder::new()
    }

    /// serialize options as a string. returns None if no options are defined
    pub fn serialize(&self) -> Option<String> {
        if self.params.is_empty() {
            None
        } else {
            let encoded: String = form_urlencoded::Serializer::new(String::new())
                .extend_pairs(&self.params)
                .finish();
            Some(encoded)
        }
    }
}

/// https://developer.github.com/v3/search/#search-issues
#[derive(Default)]
pub struct SearchIssuesOptionsBuilder {
    params: HashMap<&'static str, String>,
}

impl SearchIssuesOptionsBuilder {
    pub fn new() -> SearchIssuesOptionsBuilder {
        SearchIssuesOptionsBuilder { ..Default::default() }
    }

    pub fn sort(&mut self, sort: SearchIssuesSort) -> &mut SearchIssuesOptionsBuilder {
        self.params.insert("sort", sort.to_string());
        self
    }

    pub fn order(&mut self, direction: SortDirection) -> &mut SearchIssuesOptionsBuilder {
        self.params.insert("order", direction.to_string());
        self
    }

    pub fn build(&self) -> SearchIssuesOptions {
        SearchIssuesOptions { params: self.params.clone() }
    }
}

#[derive(Debug, Deserialize)]
pub struct SearchResult<D: ::serde::Deserialize> {
    pub total_count: u64,
    pub incomplete_results: bool,
    pub items: Vec<D>,
}

#[derive(Debug, Deserialize)]
pub struct SearchIssuesItem {
    pub url: String,
    pub repository_url: String,
    pub labels_url: String,
    pub comments_url: String,
    pub events_url: String,
    pub html_url: String,
    pub id: u64,
    pub number: u64,
    pub title: String,
    pub user: User,
    pub labels: Vec<Label>,
    pub state: String,
    pub locked: bool,
    pub assignee: Option<User>,
    pub assignees: Vec<User>,
    pub comments: u64,
    pub created_at: String,
    pub updated_at: String,
    pub closed_at: Option<String>,
    pub pull_request: Option<PullRequestInfo>,
    pub body: Option<String>,
}

impl SearchIssuesItem {
    /// returns a tuple of (repo owner name, repo name) associated with this issue
    pub fn repo_tuple(&self) -> (String, String) {
        let parsed = url::Url::parse(&self.repository_url).unwrap();
        let mut path = parsed.path().split("/").collect::<Vec<_>>();
        path.reverse();
        (path[0].to_owned(), path[1].to_owned())
    }
}

#[derive(Debug, Deserialize)]
pub struct PullRequestInfo {
    pub url: String,
    pub html_url: String,
    pub diff_url: String,
    pub patch_url: String,
}
<commit_msg>simplify type names<commit_after>//! Comments interface

use self::super::{Github, Result, Iter};
use serde::Deserialize;
use std::fmt;
use url::form_urlencoded;
use std::collections::HashMap;
use super::SortDirection;
use users::User;
use url;
use labels::Label;

/// Sort directions for pull requests
#[derive(Debug, PartialEq)]
pub enum IssuesSort {
    /// Sort by time created
    Created,
    /// Sort by last updated
    Updated,
    /// Sort by number of comments
    Comments,
}

impl fmt::Display for IssuesSort {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "{}",
               match *self {
                   IssuesSort::Comments => "comments",
                   IssuesSort::Created => "created",
                   IssuesSort::Updated => "updated",
               })
    }
}

// https://developer.github.com/v3/search/#search-issues
pub struct Search<'a> {
    github: &'a Github,
}

fn items<D: Deserialize>(result: SearchResult<D>) -> Vec<D> {
    result.items
}

impl<'a> Search<'a> {
    pub fn new(github: &'a Github) -> Search<'a> {
        Search { github: github }
    }

    /// return a reference to a search interface for issues
    pub fn issues(&self) -> SearchIssues {
        SearchIssues::new(&self)
    }

    fn iter<D: Deserialize>(&'a self, url: &str) -> Result<Iter<'a, SearchResult<D>, D>> {
        self.github.iter(url.to_owned(), items)
    }

    fn search<D: Deserialize>(&self, url: &str) -> Result<SearchResult<D>> {
        self.github.get::<SearchResult<D>>(url)
    }
}

// https://developer.github.com/v3/search/#search-issues
pub struct SearchIssues<'a> {
    search: &'a Search<'a>,
}

impl<'a> SearchIssues<'a> {
    pub fn new(search: &'a Search<'a>) -> SearchIssues<'a> {
        SearchIssues { search: search }
    }

    fn search_uri<Q>(q: Q, options: &SearchIssuesOptions) -> String
        where Q: Into<String>
    {
        let mut uri = vec!["/search/issues".to_string()];
        let query_options = options.serialize().unwrap_or(String::new());
        let query =
            form_urlencoded::Serializer::new(query_options).append_pair("q", &q.into()).finish();
        uri.push(query);
        uri.join("?")
    }

    /// returns an Iterator over pages of search results
    pub fn iter<Q>(&'a self,
                   q: Q,
                   options: &SearchIssuesOptions)
                   -> Result<Iter<'a, SearchResult<IssuesItem>, IssuesItem>>
        where Q: Into<String>
    {
        self.search.iter::<IssuesItem>(&Self::search_uri(q, options))
    }

    /// returns a single page of search results
    pub fn list<Q>(&self, q: Q, options: &SearchIssuesOptions) -> Result<SearchResult<IssuesItem>>
        where Q: Into<String>
    {
        self.search.search::<IssuesItem>(&Self::search_uri(q, options))
    }
}

// representations

#[derive(Default)]
pub struct SearchIssuesOptions {
    params: HashMap<&'static str, String>,
}

impl SearchIssuesOptions {
    pub fn builder() -> SearchIssuesOptionsBuilder {
        SearchIssuesOptionsBuilder::new()
    }

    /// serialize options as a string. returns None if no options are defined
    pub fn serialize(&self) -> Option<String> {
        if self.params.is_empty() {
            None
        } else {
            let encoded: String = form_urlencoded::Serializer::new(String::new())
                .extend_pairs(&self.params)
                .finish();
            Some(encoded)
        }
    }
}

/// https://developer.github.com/v3/search/#search-issues
#[derive(Default)]
pub struct SearchIssuesOptionsBuilder {
    params: HashMap<&'static str, String>,
}

impl SearchIssuesOptionsBuilder {
    pub fn new() -> SearchIssuesOptionsBuilder {
        SearchIssuesOptionsBuilder { ..Default::default() }
    }

    pub fn sort(&mut self, sort: IssuesSort) -> &mut SearchIssuesOptionsBuilder {
        self.params.insert("sort", sort.to_string());
        self
    }

    pub fn order(&mut self, direction: SortDirection) -> &mut SearchIssuesOptionsBuilder {
        self.params.insert("order", direction.to_string());
        self
    }

    pub fn build(&self) -> SearchIssuesOptions {
        SearchIssuesOptions { params: self.params.clone() }
    }
}

#[derive(Debug, Deserialize)]
pub struct SearchResult<D: ::serde::Deserialize> {
    pub total_count: u64,
    pub incomplete_results: bool,
    pub items: Vec<D>,
}

#[derive(Debug, Deserialize)]
pub struct IssuesItem {
    pub url: String,
    pub repository_url: String,
    pub labels_url: String,
    pub comments_url: String,
    pub events_url: String,
    pub html_url: String,
    pub id: u64,
    pub number: u64,
    pub title: String,
    pub user: User,
    pub labels: Vec<Label>,
    pub state: String,
    pub locked: bool,
    pub assignee: Option<User>,
    pub assignees: Vec<User>,
    pub comments: u64,
    pub created_at: String,
    pub updated_at: String,
    pub closed_at: Option<String>,
    pub pull_request: Option<PullRequestInfo>,
    pub body: Option<String>,
}

impl IssuesItem {
    /// returns a tuple of (repo owner name, repo name) associated with this issue
    pub fn repo_tuple(&self) -> (String, String) {
        let parsed = url::Url::parse(&self.repository_url).unwrap();
        let mut path = parsed.path().split("/").collect::<Vec<_>>();
        path.reverse();
        (path[0].to_owned(), path[1].to_owned())
    }
}

#[derive(Debug, Deserialize)]
pub struct PullRequestInfo {
    pub url: String,
    pub html_url: String,
    pub diff_url: String,
    pub patch_url: String,
}
<|endoftext|>


<commit_before>use clap::{ArgMatches};
use std::path::Path;

use db;

#[derive(Debug)]
struct Person {
    id: i32,
    name: String,
    data: Option<Vec<u8>>
}

pub fn listy(direcory: &str) {
    let path = Path::new(direcory);
    for entry in path.read_dir().expect("read_dir call failed") {
        if let Ok(entry) = entry {
            println!("aaaa{:?}", entry.path());
        }
    }
}

pub fn job_files_list(direcory: &str) {
    let path = Path::new(direcory);
    for entry in path.read_dir().expect("read_dir call failed") {
        if let Ok(entry) = entry {
            let p1 = entry.path();
            let path = p1.as_path();
            println!("dddd{:?}", path);

        }
    }
}

fn elephanc() {
    let conn = db::connect();
    db::create_tables(&conn);
    db::insert_provider(&conn, "Steven".to_string());
    db::provider_list(&conn);
    db::insert_job(&conn, "Steven".to_string(), "".to_string());
    db::insert_job_provide(&conn, 1, 1);
    db::insert_job_depend(&conn, 1, 1,10);
    db::insert_job_variable_name(&conn, "Steven".to_string());
    db::insert_job_require_variable(&conn, 1, 1);
    db::insert_job_variable_pair(&conn, 1, "Steven".to_string());
    db::insert_job_require_variable_pair(&conn, 1, 1);
    conn.execute("CREATE TABLE person (
                  id              INTEGER PRIMARY KEY,
                  name            TEXT NOT NULL,
                  data            BLOB
                  )", &[]).unwrap();
    let me = Person {
        id: 0,
        name: "Steven".to_string(),
        data: None
    };
    conn.execute("INSERT INTO person (name, data)
                  VALUES (?1, ?2)",
                 &[&me.name, &me.data]).unwrap();

    let mut stmt = conn.prepare("SELECT id, name, data FROM person").unwrap();
    let person_iter = stmt.query_map(&[], |row| {
        Person {
            id: row.get(0),
            name: row.get(1),
            data: row.get(2)
        }
    }).unwrap();

    for person in person_iter {
        println!("Found person {:?}", person.unwrap());
    }
}

pub fn deligate(matches : ArgMatches) {
    if let Some(in_v) = matches.values_of("dir-scripts") {
        for in_file in in_v {
            //println!("An input dir-scripts: {}", in_file);
           //listy(&in_file);
           job_files_list(&in_file);
        }
    }

        // If we specified the multiple() setting we can get all the values
    if let Some(in_v) = matches.values_of("env") {
        for in_file in in_v {
            println!("An input file: {}", in_file);
        }
    }

    if let Some(in_v) = matches.values_of("dir-jobs") {
        for in_file in in_v {
            println!("An input file: {}", in_file);
            listy(&in_file);
        }
    }
    elephanc();
}

<commit_msg>Make use of most mthods<commit_after>use clap::{ArgMatches};
use std::path::Path;
use db;
use std::fs::File;
use std::io::Read;

use rustc_serialize::Encodable;
use rustc_serialize::json::{self, Encoder};
use rustc_serialize::json::Json;

#[derive(Debug)]
struct Person {
    id: i32,
    name: String,
    data: Option<Vec<u8>>
}

pub fn listy(direcory: &str) {
    let path = Path::new(direcory);
    for entry in path.read_dir().expect("read_dir call failed") {
        if let Ok(entry) = entry {
            println!("aaaa{:?}", entry.path());
        }
    }
}

pub fn job_files_list(direcory: &str)  {
    let path = Path::new(direcory);
    for entry in path.read_dir().expect("read_dir call failed") {
        if let Ok(entry) = entry {
            println!("job_files_list{:?}", entry.path());
        }
    }
}

pub fn listy2(direcory: &str) -> Vec<String>{
    println!("listy2{:?}", direcory);
    let mut items = Vec::<String>::new();

    let path = Path::new(direcory);
    for entry in path.read_dir().expect("read_dir call failed") {
        if let Ok(entry) = entry {
            let path = entry.path();
            if path.is_dir() {
                continue;
            }
            let pb_2 = path.as_path();
            let as_path_buf = pb_2.as_os_str();
            let path = String::new() + as_path_buf.to_str().unwrap() ;
            items.push(path);

        }
    }
    return items;
}

fn elephanc() {
    let conn = db::connect();
    db::create_tables(&conn);
    db::insert_fs_dir(&conn, "Steven".to_string());
    db::insert_fs_dir(&conn, "Steven2".to_string());
    db::insert_fs_file(&conn, 0, "Steven".to_string());
    db::insert_provider(&conn, "Steven".to_string());
    db::provider_list(&conn);
    db::insert_job(&conn, "Steven".to_string(), "".to_string());
    db::insert_job_provide(&conn, 1, 1);
    db::insert_job_depend(&conn, 1, 1,10);
    db::insert_job_variable_name(&conn, "Steven".to_string());
    db::insert_job_require_variable(&conn, 1, 1);
    db::insert_job_variable_pair(&conn, 1, "Steven".to_string());
    db::insert_job_require_variable_pair(&conn, 1, 1);
    conn.execute("CREATE TABLE person (
                  id              INTEGER PRIMARY KEY,
                  name            TEXT NOT NULL,
                  data            BLOB
                  )", &[]).unwrap();
    let me = Person {
        id: 0,
        name: "Steven".to_string(),
        data: None
    };
    conn.execute("INSERT INTO person (name, data)
                  VALUES (?1, ?2)",
                 &[&me.name, &me.data]).unwrap();

    let mut stmt = conn.prepare("SELECT id, name, data FROM person").unwrap();
    let person_iter = stmt.query_map(&[], |row| {
        Person {
            id: row.get(0),
            name: row.get(1),
            data: row.get(2)
        }
    }).unwrap();

    for person in person_iter {
        println!("Found person {:?}", person.unwrap());
    }
}

pub fn deligate(matches : ArgMatches) {

    let conn = db::connect();
    db::create_tables(&conn);

    if let Some(in_v) = matches.values_of("dir-scripts") {
        for in_file in in_v {
            //println!("An input dir-scripts: {}", in_file);
           listy(&in_file);

        }
    }

        // If we specified the multiple() setting we can get all the values
    if let Some(in_v) = matches.values_of("env") {
        for in_file in in_v {
            println!("An input file: {}", in_file);
            job_files_list(&in_file);
        }
    }

    if let Some(in_v) = matches.values_of("dir-jobs") {
        for in_file in in_v {
            db::insert_fs_dir(&conn, in_file.to_string());
        }
    }
    for directory in db::list_fs_dir(&conn) {
        let foo = directory.id;
        let foo_name = directory.name;
        let file_list = listy2(&foo_name);
        for fnccc in file_list {
            println!("An input file: {}", fnccc);
            db::insert_fs_file(&conn, foo, fnccc);
        }
    }
    for filename in db::list_fs_file(&conn) {
        println!("list_fs_file{:?}", filename);
        let name = filename.name;
        let mut f = File::open(name).expect("file not found");

        let mut contents = String::new();
        f.read_to_string(&mut contents).expect("something went wrong reading the file");

        let json = Json::from_str(&contents).unwrap();
        //println!("json={}", json);
        let found = json.find_path(&["provides"]);
        if found != None {
            for item in found {
                println!("provides={}", item);
                let as_a_str = item.to_string();
                db::insert_provider(&conn, as_a_str);
            }
        }
        let found = json.find_path(&["name"]);
        if found != None {
            for item in found {
                println!("name={}", item);
            }
        }
        let found = json.find_path(&["script"]);
        if found != None {
            for item in found {
                println!("script={}", item);
            }
        }
        let found = json.find_path(&["variables"]);
        if found != None {

            for item in found {
                println!("variables={}", item);
                let bill = item.find_path(&["require_keys"]);
                if bill != None {
                    for item2 in bill {
                        println!("variables::require_keys={}", item2);
                    }
                }
                let bill = item.find_path(&["provides_keys"]);
                if bill != None {
                    for item2 in bill {
                        println!("variables::provides_keys={}", item2);
                    }
                }
                let bill = item.find_path(&["require_values"]);
                if bill != None {
                    for item2 in bill {
                        let ben = item2.find_path(&[""]);

                        for itme3 in ben {
                            println!("variables::itme3={}", itme3);
                        }
                    }
                }
            }

        }
        let found = json.find_path(&["depends"]);
        if found != None {
            for item in found {
                println!("depends={}", item);
            }
        }

    }
    for filename in db::list_provider(&conn) {
        println!("list_provider{:?}", filename);
    }
}

<|endoftext|>


<commit_before>use std::fs::File;
use std::io::Write;
use std::path::Path;
use cpu::CpuState;
use memory::Memory;
use cpu::AddressMode;
use std::fmt::UpperHex;

use std::vec;
use cpu::OpcodeDebugInfo;

//collections::vec::Vec<cpu::common_defs::OpcodeDebugInfo>

pub struct NesTest {
    f:File,
    op_info: Vec<OpcodeDebugInfo>,
}

impl NesTest {
    pub fn new<P:AsRef<Path>>(file_path: P, opcode_info:Vec<OpcodeDebugInfo>) -> NesTest {
        NesTest {
            f : File::create(&file_path).unwrap(),
            op_info: opcode_info,
        }
    }

    pub fn log_after_fetch(self: &mut NesTest, cpu_state: &CpuState, mem: &Memory) {
        let pc = cpu_state.pc-1;
        let dr = &cpu_state.decode_register;
        let len = cpu_state.decode_register.info.len;
        let opcode = cpu_state.instruction_register;
        let info = &self.op_info[opcode as usize];

        let mut s:String = format!("{:X}  ",pc).to_owned();

        match len {
            1 => { s.push_str(&format!("{:X}           ",cpu_state.instruction_register)) },
            2 => { s.push_str(&format!("{:X} {:X}      ",cpu_state.instruction_register,mem.read8(pc+1).unwrap())) },
            3 => { s.push_str(&format!("{:X} {:X} {:X} ",cpu_state.instruction_register,mem.read8(pc+1).unwrap(),mem.read8(pc+2).unwrap())) },
            _ => panic!("instructions should have a length of 1, 2, or 3.")
        }

        match dr.info.address_mode {
            // no explicit addresses for the following modes
            AddressMode::Accumulator  => { panic!("Accumulator addressing mode is unimplemented"); },
            AddressMode::Implied      => { panic!("Implied addressing mode is unimplemented"); },

            //explicit addresses from here on out
            AddressMode::Absolute =>        {
                s.push_str(&format!("{} ${:X}",info.name,mem.read16(pc+1).unwrap()));
            },
            AddressMode::AbsoluteX       => { panic!("AbsoluteX addressing mode is unimplemented"); },
            AddressMode::AbsoluteY       => { panic!("AbsoluteY addressing mode is unimplemented"); },
            AddressMode::Immediate       => { panic!("Immediate addressing mode is unimplemented"); },
            AddressMode::Indirect        => { panic!("Indirect addressing mode is unimplemented"); },
            AddressMode::IndexedIndirect => { panic!("IndexedIndirect addressing mode is unimplemented"); },
            AddressMode::IndirectIndexed => { panic!("IndirectIndexed addressing mode is unimplemented"); },
            AddressMode::Relative        => { panic!("Relative addressing mode is unimplemented"); },
            AddressMode::ZeroPage        => { panic!("ZeroPage addressing mode is unimplemented"); },
            AddressMode::ZeroPageX       => { panic!("ZeroPageX addressing mode is unimplemented"); },
            AddressMode::ZeroPageY       => { panic!("ZeroPageY addressing mode is unimplemented"); },
            _ => panic!("unrecognized addressing mode")
        }
        let len = s.len();
        s.push_str(&format!("{output:>0$}",48-len,output="")); // spacing
        s.push_str(&format!("A:{:0>2X}",cpu_state.a));
        s.push_str(&format!(" X:{:0>2X}",cpu_state.x));
        s.push_str(&format!(" Y:{:0>2X}",cpu_state.y));
        s.push_str(&format!(" P:{:0>2X}",cpu_state.unpack_flags()));
        s.push_str(&format!(" SP:{:0>2X}",cpu_state.sp));

        self.f.write(s.as_bytes());
    }
}

<commit_msg>we now write buffer before panic'ing in logger<commit_after>use std::fs::File;
use std::io::Write;
use std::path::Path;
use cpu::CpuState;
use memory::Memory;
use cpu::AddressMode;
use std::fmt::UpperHex;

use std::vec;
use cpu::OpcodeDebugInfo;

//collections::vec::Vec<cpu::common_defs::OpcodeDebugInfo>

pub struct NesTest {
    f:File,
    op_info: Vec<OpcodeDebugInfo>,
}

impl NesTest {
    pub fn new<P:AsRef<Path>>(file_path: P, opcode_info:Vec<OpcodeDebugInfo>) -> NesTest {
        NesTest {
            f : File::create(&file_path).unwrap(),
            op_info: opcode_info,
        }
    }

    pub fn log_after_fetch(self: &mut NesTest, cpu_state: &CpuState, mem: &Memory) {
        let pc = cpu_state.pc-1;
        let dr = &cpu_state.decode_register;
        let len = cpu_state.decode_register.info.len;
        let opcode = cpu_state.instruction_register;
        let info = &self.op_info[opcode as usize];

        let mut s:String = format!("{:X}  ",pc).to_owned();

        match len {
            1 => { s.push_str(&format!("{:X}           ",cpu_state.instruction_register)) },
            2 => { s.push_str(&format!("{:X} {:X}      ",cpu_state.instruction_register,mem.read8(pc+1).unwrap())) },
            3 => { s.push_str(&format!("{:X} {:X} {:X} ",cpu_state.instruction_register,mem.read8(pc+1).unwrap(),mem.read8(pc+2).unwrap())) },
            _ => panic!("instructions should have a length of 1, 2, or 3.")
        }

        match dr.info.address_mode {
            // no explicit addresses for the following modes
            AddressMode::Accumulator  => { panic!("Accumulator addressing mode is unimplemented"); },
            AddressMode::Implied      => { panic!("Implied addressing mode is unimplemented"); },

            //explicit addresses from here on out
            AddressMode::Absolute =>        {
                s.push_str(&format!("{} ${:X}",info.name,mem.read16(pc+1).unwrap()));
            },
            AddressMode::AbsoluteX       => { self.f.write(s.as_bytes()); panic!("AbsoluteX addressing mode is unimplemented"); },
            AddressMode::AbsoluteY       => { self.f.write(s.as_bytes()); panic!("AbsoluteY addressing mode is unimplemented"); },
            AddressMode::Immediate       => { self.f.write(s.as_bytes()); panic!("Immediate addressing mode is unimplemented"); },
            AddressMode::Indirect        => { self.f.write(s.as_bytes()); panic!("Indirect addressing mode is unimplemented"); },
            AddressMode::IndexedIndirect => { self.f.write(s.as_bytes()); panic!("IndexedIndirect addressing mode is unimplemented"); },
            AddressMode::IndirectIndexed => { self.f.write(s.as_bytes()); panic!("IndirectIndexed addressing mode is unimplemented"); },
            AddressMode::Relative        => { self.f.write(s.as_bytes()); panic!("Relative addressing mode is unimplemented"); },
            AddressMode::ZeroPage        => { self.f.write(s.as_bytes()); panic!("ZeroPage addressing mode is unimplemented"); },
            AddressMode::ZeroPageX       => { self.f.write(s.as_bytes()); panic!("ZeroPageX addressing mode is unimplemented"); },
            AddressMode::ZeroPageY       => { self.f.write(s.as_bytes()); panic!("ZeroPageY addressing mode is unimplemented"); },
            _ => { self.f.write(s.as_bytes()); panic!("unrecognized addressing mode") }
        }
        let len = s.len();
        s.push_str(&format!("{output:>0$}",48-len,output="")); // spacing
        s.push_str(&format!("A:{:0>2X}",cpu_state.a));
        s.push_str(&format!(" X:{:0>2X}",cpu_state.x));
        s.push_str(&format!(" Y:{:0>2X}",cpu_state.y));
        s.push_str(&format!(" P:{:0>2X}",cpu_state.unpack_flags()));
        s.push_str(&format!(" SP:{:0>2X}\n",cpu_state.sp));

        self.f.write(s.as_bytes());
    }
}

<|endoftext|>


<commit_before>use decoder::{Decoder, MAX_COMPONENTS};
use error::{Error, Result, UnsupportedFeature};
use huffman::{fill_default_mjpeg_tables, HuffmanDecoder, HuffmanTable};
use marker::Marker;
use parser::Predictor;
use parser::{
    parse_app, parse_com, parse_dht, parse_dqt, parse_dri, parse_sof, parse_sos,
    AdobeColorTransform, AppData, CodingProcess, Component, Dimensions, EntropyCoding, FrameInfo,
    IccChunk, ScanInfo,
};
use std::io::Read;

impl<R: Read> Decoder<R> {
    /// decode_scan_lossless
    pub fn decode_scan_lossless(
        &mut self,
        frame: &FrameInfo,
        scan: &ScanInfo,
    ) -> Result<(Option<Marker>, Vec<Vec<u16>>)> {
        let ncomp = scan.component_indices.len();
        let npixel = frame.image_size.height as usize * frame.image_size.width as usize;
        assert!(ncomp <= MAX_COMPONENTS);
        let mut results = vec![Vec::with_capacity(npixel); ncomp];

        let components: Vec<Component> = scan
            .component_indices
            .iter()
            .map(|&i| frame.components[i].clone())
            .collect();

        // Verify that all required huffman tables has been set.
        if scan
            .dc_table_indices
            .iter()
            .any(|&i| self.dc_huffman_tables[i].is_none())
        {
            return Err(Error::Format(
                "scan makes use of unset dc huffman table".to_owned(),
            ));
        }

        let mut huffman = HuffmanDecoder::new();
        let reader = &mut self.reader;
        let mut mcus_left_until_restart = self.restart_interval;
        let mut expected_rst_num = 0;
        let mut ra = [0u16; MAX_COMPONENTS];
        let mut rb = [0u16; MAX_COMPONENTS];
        let mut rc = [0u16; MAX_COMPONENTS];

        for mcu_y in 0..frame.image_size.height as usize {
            for mcu_x in 0..frame.image_size.width as usize {
                if self.restart_interval > 0 {
                    if mcus_left_until_restart == 0 {
                        match huffman.take_marker(reader)? {
                            Some(Marker::RST(n)) => {
                                if n != expected_rst_num {
                                    return Err(Error::Format(format!(
                                        "found RST{} where RST{} was expected",
                                        n, expected_rst_num
                                    )));
                                }

                                huffman.reset();

                                expected_rst_num = (expected_rst_num + 1) % 8;
                                mcus_left_until_restart = self.restart_interval;
                            }
                            Some(marker) => {
                                return Err(Error::Format(format!(
                                    "found marker {:?} inside scan where RST{} was expected",
                                    marker, expected_rst_num
                                )))
                            }
                            None => {
                                return Err(Error::Format(format!(
                                    "no marker found where RST{} was expected",
                                    expected_rst_num
                                )))
                            }
                        }
                    }

                    mcus_left_until_restart -= 1;
                }

                for (i, component) in components.iter().enumerate() {
                    let dc_table = self.dc_huffman_tables[scan.dc_table_indices[i]]
                        .as_ref()
                        .unwrap();
                    let value = huffman.decode(reader, dc_table)?;
                    let diff = match value {
                        0 => 0,
                        1..=15 => huffman.receive_extend(reader, value)? as i32,
                        16 => 32768,
                        _ => {
                            // Section F.1.2.1.1
                            // Table F.1
                            return Err(Error::Format(
                                "invalid DC difference magnitude category".to_owned(),
                            ));
                        }
                    };

                    // The following lines could be further optimized, e.g. moving the checks
                    // and updates of the previous values into the prediction function or
                    // iterating such that diagonals with mcu_x + mcu_y = const are computed at
                    // the same time to exploit independent predictions in this case
                    if mcu_x > 0 {
                        ra[i] = results[i][mcu_y * frame.image_size.width as usize + mcu_x - 1];
                    }
                    if mcu_y > 0 {
                        rb[i] = results[i][(mcu_y - 1) * frame.image_size.width as usize + mcu_x];
                        if mcu_x > 0 {
                            rc[i] = results[i]
                                [(mcu_y - 1) * frame.image_size.width as usize + (mcu_x - 1)];
                        }
                    }
                    let prediction = predict(
                        ra[i] as i32,
                        rb[i] as i32,
                        rc[i] as i32,
                        scan.predictor_selection,
                        scan.point_transform,
                        frame.precision,
                        mcu_x,
                        mcu_y,
                        self.restart_interval > 0
                            && mcus_left_until_restart == self.restart_interval - 1,
                    );
                    let result = ((prediction + diff) & 0xFFFF) as u16; // modulo 2^16
                    results[i].push(result << scan.point_transform);
                }
            }
        }

        let mut marker = huffman.take_marker(&mut self.reader)?;
        while let Some(Marker::RST(_)) = marker {
            marker = self.read_marker().ok();
        }
        Ok((marker, results))
    }
}

/// H.1.2.1
fn predict(
    ra: i32,
    rb: i32,
    rc: i32,
    predictor: Predictor,
    point_transform: u8,
    input_precision: u8,
    ix: usize,
    iy: usize,
    restart: bool,
) -> i32 {
    let result = if (ix == 0 && iy == 0) || restart {
        // start of first line or restart
        1 << (input_precision - point_transform - 1)
    } else if iy == 0 {
        // rest of first line
        ra
    } else if ix == 0 {
        // start of other line
        rb
    } else {
        // use predictor Table H.1
        match predictor {
            Predictor::NoPrediction => 0,
            Predictor::Ra => ra,
            Predictor::Rb => rb,
            Predictor::Rc => rc,
            Predictor::RaRbRc1 => ra + rb - rc,
            Predictor::RaRbRc2 => ra + ((rb - rc) >> 1),
            Predictor::RaRbRc3 => rb + ((ra - rc) >> 1),
            Predictor::RaRb => (ra + rb) / 2,
        }
    };
    result
}

pub fn compute_image_lossless(
    frame: &FrameInfo,
    mut data: Vec<Vec<u16>>
) -> Result<Vec<u8>> {
    if data.is_empty() || data.iter().any(Vec::is_empty) {
        return Err(Error::Format("not all components have data".to_owned()));
    }
    let output_size = frame.output_size;
    let components = &frame.components;
    let ncomp = components.len();

    if ncomp == 1 {
        let decoded = convert_to_u8(frame, data.remove(0));
        Ok(decoded)
    } else {
        let mut decoded: Vec<u16> = vec![
            0u16;
            ncomp * output_size.width as usize * output_size.height as usize
        ];
        for (x, chunk) in decoded.chunks_mut(ncomp).enumerate() {
            for (i, (component_data, _)) in data.iter().zip(components.iter()).enumerate() {
                chunk[i] = component_data[x];
            }
        }
        let decoded = convert_to_u8(frame, decoded);
        Ok(decoded)
    }
}

fn convert_to_u8(frame: &FrameInfo, data: Vec<u16>) -> Vec<u8> {
    if frame.precision == 8 {
        data.iter().map(|x| *x as u8).collect()
    } else {
        // we use big endian to conform with PNG
        let out: Vec<[u8; 2]> = data.iter().map(|x| x.to_be_bytes()).collect();
        out.iter().flatten().map(|x| *x).collect()
    }
}
<commit_msg>native endian output for 16bit decoding<commit_after>use decoder::{Decoder, MAX_COMPONENTS};
use error::{Error, Result, UnsupportedFeature};
use huffman::{fill_default_mjpeg_tables, HuffmanDecoder, HuffmanTable};
use marker::Marker;
use parser::Predictor;
use parser::{
    parse_app, parse_com, parse_dht, parse_dqt, parse_dri, parse_sof, parse_sos,
    AdobeColorTransform, AppData, CodingProcess, Component, Dimensions, EntropyCoding, FrameInfo,
    IccChunk, ScanInfo,
};
use std::io::Read;

impl<R: Read> Decoder<R> {
    /// decode_scan_lossless
    pub fn decode_scan_lossless(
        &mut self,
        frame: &FrameInfo,
        scan: &ScanInfo,
    ) -> Result<(Option<Marker>, Vec<Vec<u16>>)> {
        let ncomp = scan.component_indices.len();
        let npixel = frame.image_size.height as usize * frame.image_size.width as usize;
        assert!(ncomp <= MAX_COMPONENTS);
        let mut results = vec![Vec::with_capacity(npixel); ncomp];

        let components: Vec<Component> = scan
            .component_indices
            .iter()
            .map(|&i| frame.components[i].clone())
            .collect();

        // Verify that all required huffman tables has been set.
        if scan
            .dc_table_indices
            .iter()
            .any(|&i| self.dc_huffman_tables[i].is_none())
        {
            return Err(Error::Format(
                "scan makes use of unset dc huffman table".to_owned(),
            ));
        }

        let mut huffman = HuffmanDecoder::new();
        let reader = &mut self.reader;
        let mut mcus_left_until_restart = self.restart_interval;
        let mut expected_rst_num = 0;
        let mut ra = [0u16; MAX_COMPONENTS];
        let mut rb = [0u16; MAX_COMPONENTS];
        let mut rc = [0u16; MAX_COMPONENTS];

        for mcu_y in 0..frame.image_size.height as usize {
            for mcu_x in 0..frame.image_size.width as usize {
                if self.restart_interval > 0 {
                    if mcus_left_until_restart == 0 {
                        match huffman.take_marker(reader)? {
                            Some(Marker::RST(n)) => {
                                if n != expected_rst_num {
                                    return Err(Error::Format(format!(
                                        "found RST{} where RST{} was expected",
                                        n, expected_rst_num
                                    )));
                                }

                                huffman.reset();

                                expected_rst_num = (expected_rst_num + 1) % 8;
                                mcus_left_until_restart = self.restart_interval;
                            }
                            Some(marker) => {
                                return Err(Error::Format(format!(
                                    "found marker {:?} inside scan where RST{} was expected",
                                    marker, expected_rst_num
                                )))
                            }
                            None => {
                                return Err(Error::Format(format!(
                                    "no marker found where RST{} was expected",
                                    expected_rst_num
                                )))
                            }
                        }
                    }

                    mcus_left_until_restart -= 1;
                }

                for (i, component) in components.iter().enumerate() {
                    let dc_table = self.dc_huffman_tables[scan.dc_table_indices[i]]
                        .as_ref()
                        .unwrap();
                    let value = huffman.decode(reader, dc_table)?;
                    let diff = match value {
                        0 => 0,
                        1..=15 => huffman.receive_extend(reader, value)? as i32,
                        16 => 32768,
                        _ => {
                            // Section F.1.2.1.1
                            // Table F.1
                            return Err(Error::Format(
                                "invalid DC difference magnitude category".to_owned(),
                            ));
                        }
                    };

                    // The following lines could be further optimized, e.g. moving the checks
                    // and updates of the previous values into the prediction function or
                    // iterating such that diagonals with mcu_x + mcu_y = const are computed at
                    // the same time to exploit independent predictions in this case
                    if mcu_x > 0 {
                        ra[i] = results[i][mcu_y * frame.image_size.width as usize + mcu_x - 1];
                    }
                    if mcu_y > 0 {
                        rb[i] = results[i][(mcu_y - 1) * frame.image_size.width as usize + mcu_x];
                        if mcu_x > 0 {
                            rc[i] = results[i]
                                [(mcu_y - 1) * frame.image_size.width as usize + (mcu_x - 1)];
                        }
                    }
                    let prediction = predict(
                        ra[i] as i32,
                        rb[i] as i32,
                        rc[i] as i32,
                        scan.predictor_selection,
                        scan.point_transform,
                        frame.precision,
                        mcu_x,
                        mcu_y,
                        self.restart_interval > 0
                            && mcus_left_until_restart == self.restart_interval - 1,
                    );
                    let result = ((prediction + diff) & 0xFFFF) as u16; // modulo 2^16
                    results[i].push(result << scan.point_transform);
                }
            }
        }

        let mut marker = huffman.take_marker(&mut self.reader)?;
        while let Some(Marker::RST(_)) = marker {
            marker = self.read_marker().ok();
        }
        Ok((marker, results))
    }
}

/// H.1.2.1
fn predict(
    ra: i32,
    rb: i32,
    rc: i32,
    predictor: Predictor,
    point_transform: u8,
    input_precision: u8,
    ix: usize,
    iy: usize,
    restart: bool,
) -> i32 {
    let result = if (ix == 0 && iy == 0) || restart {
        // start of first line or restart
        1 << (input_precision - point_transform - 1)
    } else if iy == 0 {
        // rest of first line
        ra
    } else if ix == 0 {
        // start of other line
        rb
    } else {
        // use predictor Table H.1
        match predictor {
            Predictor::NoPrediction => 0,
            Predictor::Ra => ra,
            Predictor::Rb => rb,
            Predictor::Rc => rc,
            Predictor::RaRbRc1 => ra + rb - rc,
            Predictor::RaRbRc2 => ra + ((rb - rc) >> 1),
            Predictor::RaRbRc3 => rb + ((ra - rc) >> 1),
            Predictor::RaRb => (ra + rb) / 2,
        }
    };
    result
}

pub fn compute_image_lossless(
    frame: &FrameInfo,
    mut data: Vec<Vec<u16>>
) -> Result<Vec<u8>> {
    if data.is_empty() || data.iter().any(Vec::is_empty) {
        return Err(Error::Format("not all components have data".to_owned()));
    }
    let output_size = frame.output_size;
    let components = &frame.components;
    let ncomp = components.len();

    if ncomp == 1 {
        let decoded = convert_to_u8(frame, data.remove(0));
        Ok(decoded)
    } else {
        let mut decoded: Vec<u16> = vec![
            0u16;
            ncomp * output_size.width as usize * output_size.height as usize
        ];
        for (x, chunk) in decoded.chunks_mut(ncomp).enumerate() {
            for (i, (component_data, _)) in data.iter().zip(components.iter()).enumerate() {
                chunk[i] = component_data[x];
            }
        }
        let decoded = convert_to_u8(frame, decoded);
        Ok(decoded)
    }
}

fn convert_to_u8(frame: &FrameInfo, data: Vec<u16>) -> Vec<u8> {
    if frame.precision == 8 {
        data.iter().map(|x| *x as u8).collect()
    } else {
        // we use big endian to conform with PNG
        let out: Vec<[u8; 2]> = data.iter().map(|x| x.to_ne_bytes()).collect();
        out.iter().flatten().map(|x| *x).collect()
    }
}
<|endoftext|>


<commit_before>use decoder::{Decoder, MAX_COMPONENTS};
use error::{Error, Result, UnsupportedFeature};
use huffman::{fill_default_mjpeg_tables, HuffmanDecoder, HuffmanTable};
use marker::Marker;
use parser::Predictor;
use parser::{
    parse_app, parse_com, parse_dht, parse_dqt, parse_dri, parse_sof, parse_sos,
    AdobeColorTransform, AppData, CodingProcess, Component, Dimensions, EntropyCoding, FrameInfo,
    IccChunk, ScanInfo,
};
use std::io::Read;

impl<R: Read> Decoder<R> {
    /// decode_scan_lossless
    pub fn decode_scan_lossless(
        &mut self,
        frame: &FrameInfo,
        scan: &ScanInfo,
    ) -> Result<(Option<Marker>, Option<Vec<Vec<u16>>>)> {
        assert!(scan.component_indices.len() <= MAX_COMPONENTS);
        let mut results = vec![Vec::new(); MAX_COMPONENTS];

        let components: Vec<Component> = scan
            .component_indices
            .iter()
            .map(|&i| frame.components[i].clone())
            .collect();

        // Verify that all required huffman tables has been set.
        if scan
            .dc_table_indices
            .iter()
            .any(|&i| self.dc_huffman_tables[i].is_none())
        {
            return Err(Error::Format(
                "scan makes use of unset dc huffman table".to_owned(),
            ));
        }

        let mut huffman = HuffmanDecoder::new();
        let reader = &mut self.reader;
        let mut ra = 0;
        let mut rb = 0;
        let mut rc = 0;
        for mcu_y in 0..frame.image_size.height as usize {
            for mcu_x in 0..frame.image_size.width as usize {
                for (i, component) in components.iter().enumerate() {
                    let dc_table = self.dc_huffman_tables[scan.dc_table_indices[i]]
                        .as_ref()
                        .unwrap();
                    let value = huffman.decode(reader, dc_table)?;
                    let diff = match value {
                        0 => 0,
                        1..=15 => huffman.receive_extend(reader, value)?,
                        16 => -32768,
                        _ => {
                            // Section F.1.2.1.1
                            // Table F.1
                            return Err(Error::Format(
                                "invalid DC difference magnitude category".to_owned(),
                            ));
                        }
                    };
                    if mcu_y > 0 {
                        rb = results[i][(mcu_y - 1) * frame.image_size.width as usize + mcu_x];
                        if mcu_x > 0 {
                            rc = results[i]
                                [(mcu_y - 1) * frame.image_size.width as usize + (mcu_x - 1)];
                        }
                    }
                    let prediction = reverse_predict(
                        diff,
                        ra,
                        rb,
                        rc,
                        scan.predictor_selection,
                        scan.point_transform,
                        frame.precision,
                        mcu_x,
                        mcu_y,
                        false,
                    );
                    results[i].push(prediction << scan.point_transform);
                    ra = prediction;
                }
            }
        }

        let mut marker = huffman.take_marker(&mut self.reader)?;
        while let Some(Marker::RST(_)) = marker {
            marker = self.read_marker().ok();
        }

        println!("image size : {:?}", frame.image_size);
        println!("results size : {:?}", results[0].len());
        println!("ouput size : {:?}", frame.output_size);
        println!("point transform : {:?}", scan.point_transform);
        println!("predictor : {:?}", scan.predictor_selection);
        Ok((marker, Some(results)))
    }
}

/// H.1.2.1
fn reverse_predict(
    diff: i16,
    ra: u16,
    rb: u16,
    rc: u16,
    predictor: Predictor,
    point_transform: u8,
    input_precision: u8,
    ix: usize,
    iy: usize,
    restart: bool,
) -> u16 {
    let prediction = if ix == 0 && iy == 0 {
        // start of first line
        1 << (input_precision - point_transform - 1)
    } else if restart {
        1 << (input_precision - point_transform - 1)
    } else if iy == 0 {
        // rest of first line
        ra
    } else if ix == 0 {
        // start of other line
        rb
    } else {
        // use predictor Table H.1
        match predictor {
            Predictor::NoPrediction => 0,
            Predictor::Ra => ra,
            Predictor::Rb => rb,
            Predictor::Rc => rc,
            Predictor::RaRbRc1 => ra + rb - rc,
            Predictor::RaRbRc2 => ra + (rb - rc) >> 1,
            Predictor::RaRbRc3 => ra + (rc - rb) >> 1,
            Predictor::RaRb => (ra + rb) / 2,
        }
    };
    diff.wrapping_add(prediction as i16) as u16
}
<commit_msg>full precision calculations<commit_after>use decoder::{Decoder, MAX_COMPONENTS};
use error::{Error, Result, UnsupportedFeature};
use huffman::{fill_default_mjpeg_tables, HuffmanDecoder, HuffmanTable};
use marker::Marker;
use parser::Predictor;
use parser::{
    parse_app, parse_com, parse_dht, parse_dqt, parse_dri, parse_sof, parse_sos,
    AdobeColorTransform, AppData, CodingProcess, Component, Dimensions, EntropyCoding, FrameInfo,
    IccChunk, ScanInfo,
};
use std::io::Read;

impl<R: Read> Decoder<R> {
    /// decode_scan_lossless
    pub fn decode_scan_lossless(
        &mut self,
        frame: &FrameInfo,
        scan: &ScanInfo,
    ) -> Result<(Option<Marker>, Option<Vec<Vec<u16>>>)> {
        assert!(scan.component_indices.len() <= MAX_COMPONENTS);
        let mut results = vec![Vec::new(); MAX_COMPONENTS];

        let components: Vec<Component> = scan
            .component_indices
            .iter()
            .map(|&i| frame.components[i].clone())
            .collect();

        // Verify that all required huffman tables has been set.
        if scan
            .dc_table_indices
            .iter()
            .any(|&i| self.dc_huffman_tables[i].is_none())
        {
            return Err(Error::Format(
                "scan makes use of unset dc huffman table".to_owned(),
            ));
        }

        let mut huffman = HuffmanDecoder::new();
        let reader = &mut self.reader;
        let mut ra: u16 = 0;
        let mut rb: u16 = 0;
        let mut rc: u16 = 0;
        for mcu_y in 0..frame.image_size.height as usize {
            for mcu_x in 0..frame.image_size.width as usize {
                for (i, component) in components.iter().enumerate() {
                    let dc_table = self.dc_huffman_tables[scan.dc_table_indices[i]]
                        .as_ref()
                        .unwrap();
                    let value = huffman.decode(reader, dc_table)?;
                    let diff = match value {
                        0 => 0,
                        1..=15 => huffman.receive_extend(reader, value)? as i32,
                        16 => 32768,
                        _ => {
                            // Section F.1.2.1.1
                            // Table F.1
                            return Err(Error::Format(
                                "invalid DC difference magnitude category".to_owned(),
                            ));
                        }
                    };
                    if mcu_y > 0 {
                        rb = results[i][(mcu_y - 1) * frame.image_size.width as usize + mcu_x];
                        if mcu_x > 0 {
                            rc = results[i]
                                [(mcu_y - 1) * frame.image_size.width as usize + (mcu_x - 1)];
                        }
                    }
                    let prediction = predict(
                        ra as i32,
                        rb as i32,
                        rc as i32,
                        scan.predictor_selection,
                        scan.point_transform,
                        frame.precision,
                        mcu_x,
                        mcu_y,
                        false,
                    );
                    // let result = diff.wrapping_add(prediction) as u16;
                    let result = ((prediction + diff) & 0xFFFF) as u16; // modulo 2^16
                    if mcu_x == 0 && mcu_y == 0 {
                        println!(
                            "value: {} diff: {} prediction: {} result: {}",
                            value, diff, prediction, result
                        );
                    }
                    results[i].push(result << scan.point_transform);
                    ra = result;
                }
            }
        }

        let mut marker = huffman.take_marker(&mut self.reader)?;
        while let Some(Marker::RST(_)) = marker {
            marker = self.read_marker().ok();
        }

        println!("image size : {:?}", frame.image_size);
        println!("results size : {:?}", results[0].len());
        println!("ouput size : {:?}", frame.output_size);
        println!("point transform : {:?}", scan.point_transform);
        println!("predictor : {:?}", scan.predictor_selection);
        Ok((marker, Some(results)))
    }
}

/// H.1.2.1
fn predict(
    ra: i32,
    rb: i32,
    rc: i32,
    predictor: Predictor,
    point_transform: u8,
    input_precision: u8,
    ix: usize,
    iy: usize,
    restart: bool,
) -> i32 {
    let result = if ix == 0 && iy == 0 {
        // start of first line
        1 << (input_precision - point_transform - 1)
    } else if restart {
        1 << (input_precision - point_transform - 1)
    } else if iy == 0 {
        // rest of first line
        ra
    } else if ix == 0 {
        // start of other line
        rb
    } else {
        // use predictor Table H.1
        match predictor {
            Predictor::NoPrediction => 0,
            Predictor::Ra => ra,
            Predictor::Rb => rb,
            Predictor::Rc => rc,
            Predictor::RaRbRc1 => ra + rb - rc,
            Predictor::RaRbRc2 => ra + (rb - rc) >> 1,
            Predictor::RaRbRc3 => ra + (rc - rb) >> 1,
            Predictor::RaRb => (ra + rb) / 2,
        }
    };
    result
}
<|endoftext|>