<commit_before>
use byteorder::{ByteOrder, LittleEndian};

use std;

use gameboy;
use gameboy::{Interconnect, Interrupt, Irq, Memory};
use gameboy::frame::{Color, Frame};

const VRAM_SIZE: usize = 0x4000;
const SPRITE_DATA_SIZE: usize = 0xA0;

pub struct GpuStat {
    pub coincidence_interrupt_enabled: bool,
    pub OAM_interrupt_enabled: bool,
    pub VBlank_interrupt_enabled: bool,
    pub HBlank_interrupt_enabled: bool,
}

impl GpuStat {
    pub fn new() -> GpuStat {
        GpuStat {
            coincidence_interrupt_enabled: false,
            OAM_interrupt_enabled: false,
            VBlank_interrupt_enabled: false,
            HBlank_interrupt_enabled: false,
        }
    }

    pub fn from_u8(b: u8) -> GpuStat {
        GpuStat {
            coincidence_interrupt_enabled: b & 0x40 == 0x40,
            OAM_interrupt_enabled: b & 0x20 == 0x20,
            VBlank_interrupt_enabled: b & 0x10 == 0x10,
            HBlank_interrupt_enabled: b & 0x08 == 0x08,
        }
    }

    pub fn to_u8(&self, gpu: &Gpu) -> u8 {
        (if self.coincidence_interrupt_enabled {
            0x40
        } else {
            0
        }) | (if self.OAM_interrupt_enabled { 0x20 } else { 0 }) |
        (if self.VBlank_interrupt_enabled {
            0x10
        } else {
            0
        }) |
        (if self.HBlank_interrupt_enabled {
            0x08
        } else {
            0
        }) | (if gpu.ly == gpu.lyc { 0x04 } else { 0 }) | gpu.mode.to_u8()
    }
}

#[derive(Eq, PartialEq, Clone)]
pub enum GpuMode {
    HBlank,
    VBlank,
    SearchingRam,
    TransferringData,
}

impl GpuMode {
    fn to_u8(&self) -> u8 {
        match *self {
            GpuMode::HBlank => 0x00,
            GpuMode::VBlank => 0x01,
            GpuMode::SearchingRam => 0x02,
            GpuMode::TransferringData => 0x03,
        }
    }
}

pub enum SpriteShape {
    Square,
    Rectangle,
}

pub struct Gpu {
    pub enabled: bool,
    pub ram: Memory,
    pub sprite_data: Memory,
    control_register: u8,
    stat: GpuStat,
    scroll_y: u8,
    scroll_x: u8,
    window_y: u8,
    window_x: u8,
    pub ly: u8,
    lyc: u8,
    bg_palette: u8,
    palette0: u8,
    palette1: u8,

    cycles: isize,

    pub frame: Frame,
    pub backbuffer: Frame,
    mode: GpuMode,

    counter: u8,
    tile_base: usize,
    background_base: usize,
    sprite_shape: SpriteShape,
}

impl Gpu {
    pub fn new() -> Gpu {
        Gpu {
            enabled: true,
            ram: Memory::new(VRAM_SIZE),
            sprite_data: Memory::new(SPRITE_DATA_SIZE),
            control_register: 0x00,
            stat: GpuStat::new(),
            scroll_y: 0x00,
            scroll_x: 0x00,
            window_y: 0x00,
            window_x: 0x00,
            ly: 0x00,
            lyc: 0x00,
            bg_palette: 0x00,
            palette0: 0x00,
            palette1: 0x00,
            cycles: 0x00,
            frame: Frame::new(),
            backbuffer: Frame::new(),
            mode: GpuMode::HBlank,
            counter: 0,
            tile_base: 0x00,
            background_base: 0xC00,
            sprite_shape: SpriteShape::Square,
        }
    }

    pub fn reset(&mut self) {
        *self = Gpu::new();
    }

    fn set_status(&mut self, irq: &mut Irq) {
        if !self.enabled {
            self.cycles = 0x1C8;
            self.ly = 0x00;
            self.stat = GpuStat::from_u8(0xFD);
        }

        let current_mode = self.mode.clone();

        if self.ly >= 0x90 {
            self.mode = GpuMode::VBlank;
        } else {
            if self.cycles >= 0x178 {
                self.mode = GpuMode::SearchingRam;
            } else if self.cycles >= 0xCC {
                self.mode = GpuMode::TransferringData;
            } else {
                self.mode = GpuMode::HBlank;
            }
        }

        if self.mode != current_mode {
            irq.request(Interrupt::Lcd);
        }

        self.check_coincidence(irq);
    }

    pub fn step(&mut self, irq: &mut Irq, cycles: usize) -> Result<(), String> {
        self.set_status(irq);

        let cycles = cycles as isize;
        if self.enabled {
            self.cycles -= cycles;
        } else {
            return Ok(());
        }

        if self.cycles <= 0 {
            self.ly += 0x01;

            self.cycles = 0x1C8;

            if self.ly == 0x90 {
                irq.request(Interrupt::Vblank);
            } else if self.ly > 0x99 {
                self.ly = 0x00;
            } else if self.ly < 0x90 {
                self.render_scanline();
            }
        }

        Ok(())
    }

    fn render_scanline(&mut self) {
        let line = self.ly.wrapping_add(self.scroll_y) as usize;
        // self.clear_scanline(line);
        self.render_background(line);
        self.render_sprites(line);
        self.frame = self.backbuffer.clone();
    }

    fn clear_scanline(&mut self, line: usize) {
        for i in 0..160 {
            self.backbuffer.pixels[line * 160 + i] = Color::new(0xFF, 0xFF, 0xFF, 0xFF);
        }
    }

    fn render_background(&mut self, line: usize) {
        let bg_base = self.background_base;
        let tile_base = self.tile_base;
        let bg_map_row = (line / 0x08) as usize;
        for i in 0..gameboy::SCREEN_WIDTH {
            let x = (i as u8).wrapping_add(self.scroll_x);
            let bg_map_col = (x / 8) as usize;
            let raw_tile_number = self.ram[bg_base + (bg_map_row * 0x20 + bg_map_col)] as usize;

            let line_offset = (line % 0x08) << 0x01;

            let tile_data_start = tile_base +
                                  (if tile_base == 0x00 {
                raw_tile_number
            } else {
                (raw_tile_number as i8 as i16 + 0x80) as usize
            }) * 0x10 + line_offset;

            let x_shift = (x % 8).wrapping_sub(0x07).wrapping_mul(0xFF);
            let tile_data1 = (self.ram[tile_data_start] >> x_shift) & 0x01;
            let tile_data2 = (self.ram[tile_data_start + 0x01] >> x_shift) & 0x01;
            let total_row_data = (tile_data2 << 1) | tile_data1;
            let color_value = total_row_data;
            let c = self.get_background_color_for_byte(color_value as u8);
            self.backbuffer.pixels[self.ly as usize * 160 + i as usize] = c;
        }
    }

    fn render_sprites(&mut self, line: usize) {
        for i in 0..40 {
            let sprite_table_entry_base = i * 0x04;
            let s_y = self.sprite_data[sprite_table_entry_base] as i16 - 0x10;
            let s_x = self.sprite_data[sprite_table_entry_base + 0x01] as i16 - 0x08;
            let sprite_height = if let SpriteShape::Rectangle = self.sprite_shape {
                0x10
            } else {
                0x08
            };

            // Ignore this scanline if the sprite doesn't sit within it
            // Should we be casting to usize here? If the number is negative the sign bit
            // will be throwing this calculation off entirely - perhaps this is why Kirby
            // disappears when sprite Y position is negative?
            if s_y as usize <= line && (s_y as usize + sprite_height) > line {
                let tile_number = self.sprite_data[sprite_table_entry_base + 0x02] as i16;
                let attributes = self.sprite_data[sprite_table_entry_base + 0x03];
                let above_background = attributes & 0x80 == 0x00;
                let flip_y = attributes & 0x40 == 0x40;
                let flip_x = attributes & 0x20 == 0x20;

                let sprite_y = (line as i16 - s_y) << 0x01;
                let tile_data_start = (tile_number * 0x10) + sprite_y;
                for x in 0..8 {
                    if s_x + x < 0 || s_x + x >= 160 {
                        continue;
                    }
                    let shift = if flip_x { x } else { 0x07 - x };
                    let tile_data1 = (self.ram[tile_data_start as usize] >> shift) & 0x01;
                    let tile_data2 = (self.ram[tile_data_start as usize + 0x01] >> shift) & 0x01;
                    let total_row_data = (tile_data2 << 1) | tile_data1;
                    let color_value = total_row_data;
                    if color_value == 0x00 {
                        continue;
                    }
                    let c = self.get_sprite_color_for_byte(color_value as u8,
                                                           ((attributes & 0x10) >> 0x04) as u8);
                    self.backbuffer.pixels[line as usize * 160 + (s_x as usize + x as usize)] = c;
                }
            }
        }
    }

    fn get_background_color_for_byte(&self, b: u8) -> Color {
        let palette_index = match b {
            0x00 => self.bg_palette & 0x0003,
            0x01 => (self.bg_palette & 0x000C) >> 0x02,
            0x02 => (self.bg_palette & 0x0030) >> 0x04,
            0x03 => (self.bg_palette & 0x00C0) >> 0x06,
            _ => panic!("err: invalid pixel color value found"),
        };

        Color::from_dmg_byte(palette_index as u8)
    }

    fn get_sprite_color_for_byte(&self, b: u8, palette_entry: u8) -> Color {
        let palette = if palette_entry == 0x00 {
            self.palette0
        } else {
            self.palette1
        };

        let palette_index = match b {
            0x00 => palette & 0x0003,
            0x01 => (palette & 0x000C) >> 0x02,
            0x02 => (palette & 0x0030) >> 0x04,
            0x03 => (palette & 0x00C0) >> 0x06,
            _ => panic!("err: invalid pixel color value found"),
        };

        Color::from_dmg_byte(palette_index as u8)
    }

    pub fn read_u8(&self, addr: u16) -> u8 {
        match addr {
            0x40 => self.control_register,
            0x41 => self.stat.to_u8(self),
            0x42 => self.scroll_y,
            0x43 => self.scroll_x,
            0x4A => self.window_y,
            0x4B => self.window_x,
            0x44 => self.ly,
            0x45 => self.lyc,
            0x47 => self.bg_palette,
            0x48 => self.palette0,
            0x49 => self.palette1,
            _ => panic!("tried to read GPU memory that is not mapped"),
        }
    }

    pub fn write_u8(&mut self, addr: u16, val: u8) {
        match addr {
            0x40 => {
                self.control_register = val;
                self.enabled = self.control_register & 0x80 == 0x80;
                self.tile_base = if self.control_register & 0x10 == 0x10 {
                    0x00
                } else {
                    0x800
                };
                self.background_base = if self.control_register & 0x08 == 0x08 {
                    0x1C00
                } else {
                    0x1800
                };
                self.sprite_shape = if self.control_register & 0x04 == 0x04 {
                    SpriteShape::Rectangle
                } else {
                    SpriteShape::Square
                };
            }
            0x41 => self.stat = GpuStat::from_u8(val),
            0x42 => self.scroll_y = val,
            0x43 => self.scroll_x = val,
            0x44 => (),
            0x45 => {
                self.lyc = val;
            }
            0x47 => self.bg_palette = val,
            0x48 => self.palette0 = val,
            0x49 => self.palette1 = val,
            0x4A => self.window_y = val,
            0x4B => self.window_x = val,
            _ => panic!("tried to write GPU memory that is not mapped: {:04}", addr),
        }
    }

    pub fn write_u16(&mut self, addr: u16, val: u16) {
        let addr = addr as usize;
        LittleEndian::write_u16(&mut self.ram[addr..], val)
    }

    fn check_coincidence(&mut self, irq: &mut Irq) {
        // If LY == LYC then set the coincidence flag
        if self.lyc == self.ly && self.stat.coincidence_interrupt_enabled {
            irq.request(Interrupt::Lcd);
        }
    }
}
<commit_msg>Fix kirby issues<commit_after>
use byteorder::{ByteOrder, LittleEndian};

use std;

use gameboy;
use gameboy::{Interconnect, Interrupt, Irq, Memory};
use gameboy::frame::{Color, Frame};

const VRAM_SIZE: usize = 0x4000;
const SPRITE_DATA_SIZE: usize = 0xA0;

pub struct GpuStat {
    pub coincidence_interrupt_enabled: bool,
    pub OAM_interrupt_enabled: bool,
    pub VBlank_interrupt_enabled: bool,
    pub HBlank_interrupt_enabled: bool,
}

impl GpuStat {
    pub fn new() -> GpuStat {
        GpuStat {
            coincidence_interrupt_enabled: false,
            OAM_interrupt_enabled: false,
            VBlank_interrupt_enabled: false,
            HBlank_interrupt_enabled: false,
        }
    }

    pub fn from_u8(b: u8) -> GpuStat {
        GpuStat {
            coincidence_interrupt_enabled: b & 0x40 == 0x40,
            OAM_interrupt_enabled: b & 0x20 == 0x20,
            VBlank_interrupt_enabled: b & 0x10 == 0x10,
            HBlank_interrupt_enabled: b & 0x08 == 0x08,
        }
    }

    pub fn to_u8(&self, gpu: &Gpu) -> u8 {
        (if self.coincidence_interrupt_enabled {
            0x40
        } else {
            0
        }) | (if self.OAM_interrupt_enabled { 0x20 } else { 0 }) |
        (if self.VBlank_interrupt_enabled {
            0x10
        } else {
            0
        }) |
        (if self.HBlank_interrupt_enabled {
            0x08
        } else {
            0
        }) | (if gpu.ly == gpu.lyc { 0x04 } else { 0 }) | gpu.mode.to_u8()
    }
}

#[derive(Eq, PartialEq, Clone)]
pub enum GpuMode {
    HBlank,
    VBlank,
    SearchingRam,
    TransferringData,
}

impl GpuMode {
    fn to_u8(&self) -> u8 {
        match *self {
            GpuMode::HBlank => 0x00,
            GpuMode::VBlank => 0x01,
            GpuMode::SearchingRam => 0x02,
            GpuMode::TransferringData => 0x03,
        }
    }
}

pub enum SpriteShape {
    Square,
    Rectangle,
}

pub struct Gpu {
    pub enabled: bool,
    pub ram: Memory,
    pub sprite_data: Memory,
    control_register: u8,
    stat: GpuStat,
    scroll_y: u8,
    scroll_x: u8,
    window_y: u8,
    window_x: u8,
    pub ly: u8,
    lyc: u8,
    bg_palette: u8,
    palette0: u8,
    palette1: u8,

    cycles: isize,

    pub frame: Frame,
    pub backbuffer: Frame,
    mode: GpuMode,

    counter: u8,
    tile_base: usize,
    background_base: usize,
    sprite_shape: SpriteShape,
}

impl Gpu {
    pub fn new() -> Gpu {
        Gpu {
            enabled: true,
            ram: Memory::new(VRAM_SIZE),
            sprite_data: Memory::new(SPRITE_DATA_SIZE),
            control_register: 0x00,
            stat: GpuStat::new(),
            scroll_y: 0x00,
            scroll_x: 0x00,
            window_y: 0x00,
            window_x: 0x00,
            ly: 0x00,
            lyc: 0x00,
            bg_palette: 0x00,
            palette0: 0x00,
            palette1: 0x00,
            cycles: 0x00,
            frame: Frame::new(),
            backbuffer: Frame::new(),
            mode: GpuMode::HBlank,
            counter: 0,
            tile_base: 0x00,
            background_base: 0xC00,
            sprite_shape: SpriteShape::Square,
        }
    }

    pub fn reset(&mut self) {
        *self = Gpu::new();
    }

    fn set_status(&mut self, irq: &mut Irq) {
        if !self.enabled {
            self.cycles = 0x1C8;
            self.ly = 0x00;
            self.stat = GpuStat::from_u8(0xFD);
        }

        let current_mode = self.mode.clone();

        if self.ly >= 0x90 {
            self.mode = GpuMode::VBlank;
        } else {
            if self.cycles >= 0x178 {
                self.mode = GpuMode::SearchingRam;
            } else if self.cycles >= 0xCC {
                self.mode = GpuMode::TransferringData;
            } else {
                self.mode = GpuMode::HBlank;
            }
        }

        if self.mode != current_mode {
            irq.request(Interrupt::Lcd);
        }

        self.check_coincidence(irq);
    }

    pub fn step(&mut self, irq: &mut Irq, cycles: usize) -> Result<(), String> {
        self.set_status(irq);

        let cycles = cycles as isize;
        if self.enabled {
            self.cycles -= cycles;
        } else {
            return Ok(());
        }

        if self.cycles <= 0 {
            self.ly += 0x01;

            self.cycles = 0x1C8;

            if self.ly == 0x90 {
                irq.request(Interrupt::Vblank);
            } else if self.ly > 0x99 {
                self.ly = 0x00;
            } else if self.ly < 0x90 {
                self.render_scanline();
            }
        }

        Ok(())
    }

    fn render_scanline(&mut self) {
        let line = self.ly.wrapping_add(self.scroll_y) as usize;
        // self.clear_scanline(line);
        self.render_background(line);
        self.render_sprites(line);
        self.frame = self.backbuffer.clone();
    }

    fn clear_scanline(&mut self, line: usize) {
        for i in 0..160 {
            self.backbuffer.pixels[line * 160 + i] = Color::new(0xFF, 0xFF, 0xFF, 0xFF);
        }
    }

    fn render_background(&mut self, line: usize) {
        let bg_base = self.background_base;
        let tile_base = self.tile_base;
        let bg_map_row = (line / 0x08) as usize;
        for i in 0..gameboy::SCREEN_WIDTH {
            let x = (i as u8).wrapping_add(self.scroll_x);
            let bg_map_col = (x / 8) as usize;
            let raw_tile_number = self.ram[bg_base + (bg_map_row * 0x20 + bg_map_col)] as usize;

            let line_offset = (line % 0x08) << 0x01;

            let tile_data_start = tile_base +
                                  (if tile_base == 0x00 {
                raw_tile_number
            } else {
                (raw_tile_number as i8 as i16 + 0x80) as usize
            }) * 0x10 + line_offset;

            let x_shift = (x % 8).wrapping_sub(0x07).wrapping_mul(0xFF);
            let tile_data1 = (self.ram[tile_data_start] >> x_shift) & 0x01;
            let tile_data2 = (self.ram[tile_data_start + 0x01] >> x_shift) & 0x01;
            let total_row_data = (tile_data2 << 1) | tile_data1;
            let color_value = total_row_data;
            let c = self.get_background_color_for_byte(color_value as u8);
            self.backbuffer.pixels[self.ly as usize * 160 + i as usize] = c;
        }
    }

    fn render_sprites(&mut self, line: usize) {
        for i in 0..40 {
            let sprite_table_entry_base = i * 0x04;
            let s_y = self.sprite_data[sprite_table_entry_base] as i16 - 0x10;
            let s_x = self.sprite_data[sprite_table_entry_base + 0x01] as i16 - 0x08;
            let sprite_height = if let SpriteShape::Rectangle = self.sprite_shape {
                0x10
            } else {
                0x08
            };

            if s_y <= line as i16 && (s_y + sprite_height as i16) > line as i16 {
                let tile_number = self.sprite_data[sprite_table_entry_base + 0x02] as i16;
                let attributes = self.sprite_data[sprite_table_entry_base + 0x03];
                let above_background = attributes & 0x80 == 0x00;
                let flip_y = attributes & 0x40 == 0x40;
                let flip_x = attributes & 0x20 == 0x20;

                let sprite_y = (line as i16 - s_y) << 0x01;
                let tile_data_start = (tile_number * 0x10) + sprite_y;
                for x in 0..8 {
                    if s_x + x < 0 || s_x + x >= 160 {
                        continue;
                    }
                    let shift = if flip_x { x } else { 0x07 - x };
                    let tile_data1 = (self.ram[tile_data_start as usize] >> shift) & 0x01;
                    let tile_data2 = (self.ram[tile_data_start as usize + 0x01] >> shift) & 0x01;
                    let total_row_data = (tile_data2 << 1) | tile_data1;
                    let color_value = total_row_data;
                    if color_value == 0x00 {
                        continue;
                    }
                    let c = self.get_sprite_color_for_byte(color_value as u8,
                                                           ((attributes & 0x10) >> 0x04) as u8);
                    self.backbuffer.pixels[line as usize * 160 + (s_x as usize + x as usize)] = c;
                }
            }
        }
    }

    fn get_background_color_for_byte(&self, b: u8) -> Color {
        let palette_index = match b {
            0x00 => self.bg_palette & 0x0003,
            0x01 => (self.bg_palette & 0x000C) >> 0x02,
            0x02 => (self.bg_palette & 0x0030) >> 0x04,
            0x03 => (self.bg_palette & 0x00C0) >> 0x06,
            _ => panic!("err: invalid pixel color value found"),
        };

        Color::from_dmg_byte(palette_index as u8)
    }

    fn get_sprite_color_for_byte(&self, b: u8, palette_entry: u8) -> Color {
        let palette = if palette_entry == 0x00 {
            self.palette0
        } else {
            self.palette1
        };

        let palette_index = match b {
            0x00 => palette & 0x0003,
            0x01 => (palette & 0x000C) >> 0x02,
            0x02 => (palette & 0x0030) >> 0x04,
            0x03 => (palette & 0x00C0) >> 0x06,
            _ => panic!("err: invalid pixel color value found"),
        };

        Color::from_dmg_byte(palette_index as u8)
    }

    pub fn read_u8(&self, addr: u16) -> u8 {
        match addr {
            0x40 => self.control_register,
            0x41 => self.stat.to_u8(self),
            0x42 => self.scroll_y,
            0x43 => self.scroll_x,
            0x4A => self.window_y,
            0x4B => self.window_x,
            0x44 => self.ly,
            0x45 => self.lyc,
            0x47 => self.bg_palette,
            0x48 => self.palette0,
            0x49 => self.palette1,
            _ => panic!("tried to read GPU memory that is not mapped"),
        }
    }

    pub fn write_u8(&mut self, addr: u16, val: u8) {
        match addr {
            0x40 => {
                self.control_register = val;
                self.enabled = self.control_register & 0x80 == 0x80;
                self.tile_base = if self.control_register & 0x10 == 0x10 {
                    0x00
                } else {
                    0x800
                };
                self.background_base = if self.control_register & 0x08 == 0x08 {
                    0x1C00
                } else {
                    0x1800
                };
                self.sprite_shape = if self.control_register & 0x04 == 0x04 {
                    SpriteShape::Rectangle
                } else {
                    SpriteShape::Square
                };
            }
            0x41 => self.stat = GpuStat::from_u8(val),
            0x42 => self.scroll_y = val,
            0x43 => self.scroll_x = val,
            0x44 => (),
            0x45 => {
                self.lyc = val;
            }
            0x47 => self.bg_palette = val,
            0x48 => self.palette0 = val,
            0x49 => self.palette1 = val,
            0x4A => self.window_y = val,
            0x4B => self.window_x = val,
            _ => panic!("tried to write GPU memory that is not mapped: {:04}", addr),
        }
    }

    pub fn write_u16(&mut self, addr: u16, val: u16) {
        let addr = addr as usize;
        LittleEndian::write_u16(&mut self.ram[addr..], val)
    }

    fn check_coincidence(&mut self, irq: &mut Irq) {
        // If LY == LYC then set the coincidence flag
        if self.lyc == self.ly && self.stat.coincidence_interrupt_enabled {
            irq.request(Interrupt::Lcd);
        }
    }
}
<|endoftext|>


<commit_before>extern crate rand;
use self::rand::Rng;

use core::renderer::RGB;

use core::world::dungeon::filter::Filter;

use core::world::dungeon::map::construct::{Corr, Rect};
use core::world::dungeon::map::{Grid, Pos, tile, Tile};

///
/// Simple dungeon builder
///
/// This builder places a number of small rooms (respective to map size)
/// all connected by corridors.
///
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Simple {

  pub w: usize,
  pub h: usize,

  // Private vector to hold rooms
  rooms: Vec<Rect>,

  // Private vector to hold floor type
  floor: Tile

}

impl Simple {

  ///
  /// Add rooms to the `rooms` vec and build them on the `grid`
  ///
  fn add_rooms(&mut self, grid: &mut Grid<Tile>) {

    // Clear rooms
    self.rooms = Vec::<Rect>::new();

    let mut rng = rand::thread_rng();

    // Number of rooms correspond to map size
    let n = (self.w + self.h) / 10;

    for _ in 0..n {

      let x: isize = rng.gen_range(1, self.w as isize - 2);
      let y: isize = rng.gen_range(1, self.h as isize - 2);
      let l: isize = rng.gen_range(5, 20);
      let w: isize = rng.gen_range(5, 20);

      // Check bounds
      if w + x >= self.w as isize|| l + y >= self.h as isize {
        continue;
      } else {
        let r = Rect::new(x, y, l, w);
        self.build_rect(&r, grid);
        self.rooms.push(r);
      }

    }

  }

  ///
  /// Build a corridor to the grid
  ///
  /// Start by moving along the x-axis, then the y-axis
  ///
  fn build_corr(&mut self, c: &Corr, grid: &mut Grid<Tile>) {

    let mut mover = c.start;

    while mover.x != c.end.x {

      if mover.x < c.end.x {
        mover.x += 1;
      } else if mover.x > c.end.x {
        mover.x -= 1;
      }

      grid[mover] = self.floor.clone();

    }

    while mover.y != c.end.y {

      if mover.y < c.end.y {
        mover.y += 1;
      } else if mover.y > c.end.y {
        mover.y -= 1;
      }

      grid[mover] = self.floor.clone();

    }

  }

  ///
  /// Build a rectangle to the grid
  ///
  fn build_rect(&mut self, r: &Rect, grid: &mut Grid<Tile>) {
    for w in 0..r.w {
      for l in 0..r.l {
        grid[(w + r.x) as usize][(l + r.y) as usize] = self.floor.clone();
      }
    }
  }

  ///
  /// Connect rooms by making `Corr`s then build them.
  ///
  /// Essentially we connect each room in `rooms` to the next room in the
  /// vector, once we run out we wrap it back around, this in theory
  /// creates a cyclical dungeon with no deadends, but it doesn't happen
  /// consistently due to the way corridors are built (which is a good thing).
  ///
  fn connect_rooms(&mut self, grid: &mut Grid<Tile>) {

    for r in 0..self.rooms.len() - 1 {

      let c1 : Pos;
      let c2 : Pos;

      // Wrap around
      if r == self.rooms.len() - 1 {

        c1 = self.rooms[r].center().clone();
        c2 = self.rooms[0].center().clone();

      } else {

        c1 = self.rooms[r].center().clone();
        c2 = self.rooms[r + 1].center().clone();

      }

      self.build_corr(&Corr::new(c1, c2), grid);

    }

  }

  ///
  /// Return a new `Simple`
  ///
  pub fn new(grid: &Grid<Tile>) -> Self {

    // Make a new dungeon with our fresh grid of size `w` by `h`
    let s = Simple {
      rooms: Vec::<Rect>::new(),
      w: grid.len(),
      h: grid[0].len(),
      // Floor type. Doesn't need to be changed right now, after all this is the 'simple' dungeon builder
      floor: Tile::new("Floor", ' ', RGB(7, 7, 7),  RGB(0, 0, 0), tile::Type::Floor(tile::Floor::Normal))
    };

    return s;

  }

}

impl Filter for Simple {

  type Output = Tile;

  fn apply(&mut self, grid: &mut Grid<Self::Output>) {

    // Generate the dungeon
    self.add_rooms(grid);
    self.connect_rooms(grid);

  }

}<commit_msg>Add super in simple<commit_after>extern crate rand;
use self::rand::Rng;

use core::renderer::RGB;

use super::Filter;

use super::map::construct::{Corr, Rect};
use super::map::{Grid, Pos, tile, Tile};

///
/// Simple dungeon builder
///
/// This builder places a number of small rooms (respective to map size)
/// all connected by corridors.
///
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Simple {

  pub w: usize,
  pub h: usize,

  // Private vector to hold rooms
  rooms: Vec<Rect>,

  // Private vector to hold floor type
  floor: Tile

}

impl Simple {

  ///
  /// Add rooms to the `rooms` vec and build them on the `grid`
  ///
  fn add_rooms(&mut self, grid: &mut Grid<Tile>) {

    // Clear rooms
    self.rooms = Vec::<Rect>::new();

    let mut rng = rand::thread_rng();

    // Number of rooms correspond to map size
    let n = (self.w + self.h) / 10;

    for _ in 0..n {

      let x: isize = rng.gen_range(1, self.w as isize - 2);
      let y: isize = rng.gen_range(1, self.h as isize - 2);
      let l: isize = rng.gen_range(5, 20);
      let w: isize = rng.gen_range(5, 20);

      // Check bounds
      if w + x >= self.w as isize|| l + y >= self.h as isize {
        continue;
      } else {
        let r = Rect::new(x, y, l, w);
        self.build_rect(&r, grid);
        self.rooms.push(r);
      }

    }

  }

  ///
  /// Build a corridor to the grid
  ///
  /// Start by moving along the x-axis, then the y-axis
  ///
  fn build_corr(&mut self, c: &Corr, grid: &mut Grid<Tile>) {

    let mut mover = c.start;

    while mover.x != c.end.x {

      if mover.x < c.end.x {
        mover.x += 1;
      } else if mover.x > c.end.x {
        mover.x -= 1;
      }

      grid[mover] = self.floor.clone();

    }

    while mover.y != c.end.y {

      if mover.y < c.end.y {
        mover.y += 1;
      } else if mover.y > c.end.y {
        mover.y -= 1;
      }

      grid[mover] = self.floor.clone();

    }

  }

  ///
  /// Build a rectangle to the grid
  ///
  fn build_rect(&mut self, r: &Rect, grid: &mut Grid<Tile>) {
    for w in 0..r.w {
      for l in 0..r.l {
        grid[(w + r.x) as usize][(l + r.y) as usize] = self.floor.clone();
      }
    }
  }

  ///
  /// Connect rooms by making `Corr`s then build them.
  ///
  /// Essentially we connect each room in `rooms` to the next room in the
  /// vector, once we run out we wrap it back around, this in theory
  /// creates a cyclical dungeon with no deadends, but it doesn't happen
  /// consistently due to the way corridors are built (which is a good thing).
  ///
  fn connect_rooms(&mut self, grid: &mut Grid<Tile>) {

    for r in 0..self.rooms.len() - 1 {

      let c1 : Pos;
      let c2 : Pos;

      // Wrap around
      if r == self.rooms.len() - 1 {

        c1 = self.rooms[r].center().clone();
        c2 = self.rooms[0].center().clone();

      } else {

        c1 = self.rooms[r].center().clone();
        c2 = self.rooms[r + 1].center().clone();

      }

      self.build_corr(&Corr::new(c1, c2), grid);

    }

  }

  ///
  /// Return a new `Simple`
  ///
  pub fn new(grid: &Grid<Tile>) -> Self {

    // Make a new dungeon with our fresh grid of size `w` by `h`
    let s = Simple {
      rooms: Vec::<Rect>::new(),
      w: grid.len(),
      h: grid[0].len(),
      // Floor type. Doesn't need to be changed right now, after all this is the 'simple' dungeon builder
      floor: Tile::new("Floor", ' ', RGB(7, 7, 7),  RGB(0, 0, 0), tile::Type::Floor(tile::Floor::Normal))
    };

    return s;

  }

}

impl Filter for Simple {

  type Output = Tile;

  fn apply(&mut self, grid: &mut Grid<Self::Output>) {

    // Generate the dungeon
    self.add_rooms(grid);
    self.connect_rooms(grid);

  }

}<|endoftext|>


<commit_before>use crate::gen::{CfgEvaluator, CfgResult};
use once_cell::sync::OnceCell;
use std::borrow::Borrow;
use std::cmp::Ordering;
use std::collections::{BTreeMap as Map, BTreeSet as Set};
use std::env;

static ENV: OnceCell<CargoEnv> = OnceCell::new();

struct CargoEnv {
    features: Set<Name>,
    cfgs: Map<Name, String>,
}

pub(super) struct CargoEnvCfgEvaluator;

impl CfgEvaluator for CargoEnvCfgEvaluator {
    fn eval(&self, name: &str, query_value: Option<&str>) -> CfgResult {
        let env = ENV.get_or_init(CargoEnv::load);
        if name == "feature" {
            if let Some(query_value) = query_value {
                CfgResult::from(env.features.contains(Lookup::new(query_value)))
            } else {
                let msg = "expected `feature = \"...\"`".to_owned();
                CfgResult::Undetermined { msg }
            }
        } else if name == "test" && query_value.is_none() {
            let msg = "cfg(test) is not supported because Cargo runs your build script only once across the lib and test build of the same crate".to_owned();
            CfgResult::Undetermined { msg }
        } else {
            match env.cfgs.get(Lookup::new(name)) {
                Some(cargo_value) => {
                    if let Some(query_value) = query_value {
                        CfgResult::from(cargo_value.split(',').any(|value| value == query_value))
                    } else {
                        CfgResult::True
                    }
                }
                None => CfgResult::False,
            }
        }
    }
}

impl CargoEnv {
    fn load() -> Self {
        const CARGO_FEATURE_PREFIX: &str = "CARGO_FEATURE_";
        const CARGO_CFG_PREFIX: &str = "CARGO_CFG_";

        let mut features = Set::new();
        let mut cfgs = Map::new();
        for (k, v) in env::vars_os() {
            let k = match k.to_str() {
                Some(k) => k,
                None => continue,
            };
            let v = match v.into_string() {
                Ok(v) => v,
                Err(_) => continue,
            };
            if let Some(feature_name) = k.strip_prefix(CARGO_FEATURE_PREFIX) {
                let feature_name = Name(feature_name.to_owned());
                features.insert(feature_name);
            } else if let Some(cfg_name) = k.strip_prefix(CARGO_CFG_PREFIX) {
                let cfg_name = Name(cfg_name.to_owned());
                cfgs.insert(cfg_name, v);
            }
        }
        CargoEnv { features, cfgs }
    }
}

struct Name(String);

impl Ord for Name {
    fn cmp(&self, rhs: &Self) -> Ordering {
        Lookup::new(&self.0).cmp(Lookup::new(&rhs.0))
    }
}

impl PartialOrd for Name {
    fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
        Some(self.cmp(rhs))
    }
}

impl Eq for Name {}

impl PartialEq for Name {
    fn eq(&self, rhs: &Self) -> bool {
        Lookup::new(&self.0).eq(Lookup::new(&rhs.0))
    }
}

#[repr(transparent)]
struct Lookup(str);

impl Lookup {
    fn new(name: &str) -> &Self {
        unsafe { &*(name as *const str as *const Self) }
    }
}

impl Borrow<Lookup> for Name {
    fn borrow(&self) -> &Lookup {
        Lookup::new(&self.0)
    }
}

impl Ord for Lookup {
    fn cmp(&self, rhs: &Self) -> Ordering {
        self.0
            .bytes()
            .map(CaseAgnosticByte)
            .cmp(rhs.0.bytes().map(CaseAgnosticByte))
    }
}

impl PartialOrd for Lookup {
    fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
        Some(self.cmp(rhs))
    }
}

impl Eq for Lookup {}

impl PartialEq for Lookup {
    fn eq(&self, rhs: &Self) -> bool {
        self.0
            .bytes()
            .map(CaseAgnosticByte)
            .eq(rhs.0.bytes().map(CaseAgnosticByte))
    }
}

struct CaseAgnosticByte(u8);

impl Ord for CaseAgnosticByte {
    fn cmp(&self, rhs: &Self) -> Ordering {
        self.0.to_ascii_lowercase().cmp(&rhs.0.to_ascii_lowercase())
    }
}

impl PartialOrd for CaseAgnosticByte {
    fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
        Some(self.cmp(rhs))
    }
}

impl Eq for CaseAgnosticByte {}

impl PartialEq for CaseAgnosticByte {
    fn eq(&self, rhs: &Self) -> bool {
        self.cmp(rhs) == Ordering::Equal
    }
}
<commit_msg>Reduce indentation in CargoEnvCfgEvaluator<commit_after>use crate::gen::{CfgEvaluator, CfgResult};
use once_cell::sync::OnceCell;
use std::borrow::Borrow;
use std::cmp::Ordering;
use std::collections::{BTreeMap as Map, BTreeSet as Set};
use std::env;

static ENV: OnceCell<CargoEnv> = OnceCell::new();

struct CargoEnv {
    features: Set<Name>,
    cfgs: Map<Name, String>,
}

pub(super) struct CargoEnvCfgEvaluator;

impl CfgEvaluator for CargoEnvCfgEvaluator {
    fn eval(&self, name: &str, query_value: Option<&str>) -> CfgResult {
        let env = ENV.get_or_init(CargoEnv::load);
        if name == "feature" {
            return if let Some(query_value) = query_value {
                CfgResult::from(env.features.contains(Lookup::new(query_value)))
            } else {
                let msg = "expected `feature = \"...\"`".to_owned();
                CfgResult::Undetermined { msg }
            };
        }
        if name == "test" && query_value.is_none() {
            let msg = "cfg(test) is not supported because Cargo runs your build script only once across the lib and test build of the same crate".to_owned();
            return CfgResult::Undetermined { msg };
        }
        if let Some(cargo_value) = env.cfgs.get(Lookup::new(name)) {
            return if let Some(query_value) = query_value {
                CfgResult::from(cargo_value.split(',').any(|value| value == query_value))
            } else {
                CfgResult::True
            };
        }
        CfgResult::False
    }
}

impl CargoEnv {
    fn load() -> Self {
        const CARGO_FEATURE_PREFIX: &str = "CARGO_FEATURE_";
        const CARGO_CFG_PREFIX: &str = "CARGO_CFG_";

        let mut features = Set::new();
        let mut cfgs = Map::new();
        for (k, v) in env::vars_os() {
            let k = match k.to_str() {
                Some(k) => k,
                None => continue,
            };
            let v = match v.into_string() {
                Ok(v) => v,
                Err(_) => continue,
            };
            if let Some(feature_name) = k.strip_prefix(CARGO_FEATURE_PREFIX) {
                let feature_name = Name(feature_name.to_owned());
                features.insert(feature_name);
            } else if let Some(cfg_name) = k.strip_prefix(CARGO_CFG_PREFIX) {
                let cfg_name = Name(cfg_name.to_owned());
                cfgs.insert(cfg_name, v);
            }
        }
        CargoEnv { features, cfgs }
    }
}

struct Name(String);

impl Ord for Name {
    fn cmp(&self, rhs: &Self) -> Ordering {
        Lookup::new(&self.0).cmp(Lookup::new(&rhs.0))
    }
}

impl PartialOrd for Name {
    fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
        Some(self.cmp(rhs))
    }
}

impl Eq for Name {}

impl PartialEq for Name {
    fn eq(&self, rhs: &Self) -> bool {
        Lookup::new(&self.0).eq(Lookup::new(&rhs.0))
    }
}

#[repr(transparent)]
struct Lookup(str);

impl Lookup {
    fn new(name: &str) -> &Self {
        unsafe { &*(name as *const str as *const Self) }
    }
}

impl Borrow<Lookup> for Name {
    fn borrow(&self) -> &Lookup {
        Lookup::new(&self.0)
    }
}

impl Ord for Lookup {
    fn cmp(&self, rhs: &Self) -> Ordering {
        self.0
            .bytes()
            .map(CaseAgnosticByte)
            .cmp(rhs.0.bytes().map(CaseAgnosticByte))
    }
}

impl PartialOrd for Lookup {
    fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
        Some(self.cmp(rhs))
    }
}

impl Eq for Lookup {}

impl PartialEq for Lookup {
    fn eq(&self, rhs: &Self) -> bool {
        self.0
            .bytes()
            .map(CaseAgnosticByte)
            .eq(rhs.0.bytes().map(CaseAgnosticByte))
    }
}

struct CaseAgnosticByte(u8);

impl Ord for CaseAgnosticByte {
    fn cmp(&self, rhs: &Self) -> Ordering {
        self.0.to_ascii_lowercase().cmp(&rhs.0.to_ascii_lowercase())
    }
}

impl PartialOrd for CaseAgnosticByte {
    fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
        Some(self.cmp(rhs))
    }
}

impl Eq for CaseAgnosticByte {}

impl PartialEq for CaseAgnosticByte {
    fn eq(&self, rhs: &Self) -> bool {
        self.cmp(rhs) == Ordering::Equal
    }
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use config::config::RoleType;
use config_builder::swarm_config::SwarmConfigBuilder;
use std::convert::TryInto;
use std::path::PathBuf;
use structopt::StructOpt;

#[derive(Debug, StructOpt)]
#[structopt(about = "Tool to manage and create Libra Configs")]
struct Args {
    #[structopt(short = "b", long, parse(from_os_str))]
    /// Base config to use
    base: PathBuf,
    #[structopt(short = "n", long, default_value = "1")]
    /// Specify the number of nodes to configure
    nodes: usize,
    #[structopt(short = "o", long, parse(from_os_str))]
    /// The output directory
    output_dir: Option<PathBuf>,
    #[structopt(short = "d", long)]
    /// Generate peer config with one peer only (to force discovery)
    discovery: bool,
    #[structopt(short = "s", long)]
    /// Use the provided seed for generating keys for each of the validators
    key_seed: Option<String>,
    #[structopt(short = "m", long)]
    /// File location from which to load faucet account generated via generate_keypair tool
    faucet_account_file: String,
    #[structopt(short = "r", long, default_value = "Validator")]
    /// Role for the nodes: one of {"validator", "full_node"}
    role: String,
    #[structopt(short = "u", long)]
    /// Config directory for upstream node. This field is needed if role is "full_node"
    upstream_config_dir: Option<String>,
}

fn main() {
    let args = Args::from_args();
    let output_dir = if let Some(output_dir) = args.output_dir.as_ref() {
        output_dir.clone()
    } else {
        ::std::env::current_dir().expect("Failed to access current directory.")
    };
    let (faucet_account_keypair, _faucet_key_file_path, _temp_dir) =
        generate_keypair::load_faucet_key_or_create_default(Some(args.faucet_account_file.clone()));
    let role: RoleType = args.role.clone().into();

    let mut config_builder = SwarmConfigBuilder::new();
    config_builder
        .with_num_nodes(args.nodes)
        .with_role(role)
        .with_base(&args.base)
        .with_output_dir(output_dir)
        .with_faucet_keypair(faucet_account_keypair)
        .with_upstream_config_dir(args.upstream_config_dir.clone());

    if args.discovery {
        config_builder.force_discovery();
    }
    if let Some(key_seed) = args.key_seed.as_ref() {
        let seed = hex::decode(key_seed).expect("Invalid hex in seed.");
        config_builder.with_key_seed(
            seed[..32]
                .try_into()
                .expect("Seed should be 32 bytes long."),
        );
    }
    config_builder.build().expect("Unable to generate configs");
}
<commit_msg>[config] Fix libra-config -r default<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use config::config::RoleType;
use config_builder::swarm_config::SwarmConfigBuilder;
use std::convert::TryInto;
use std::path::PathBuf;
use structopt::StructOpt;

#[derive(Debug, StructOpt)]
#[structopt(about = "Tool to manage and create Libra Configs")]
struct Args {
    #[structopt(short = "b", long, parse(from_os_str))]
    /// Base config to use
    base: PathBuf,
    #[structopt(short = "n", long, default_value = "1")]
    /// Specify the number of nodes to configure
    nodes: usize,
    #[structopt(short = "o", long, parse(from_os_str))]
    /// The output directory
    output_dir: Option<PathBuf>,
    #[structopt(short = "d", long)]
    /// Generate peer config with one peer only (to force discovery)
    discovery: bool,
    #[structopt(short = "s", long)]
    /// Use the provided seed for generating keys for each of the validators
    key_seed: Option<String>,
    #[structopt(short = "m", long)]
    /// File location from which to load faucet account generated via generate_keypair tool
    faucet_account_file: String,
    #[structopt(short = "r", long, default_value = "validator")]
    /// Role for the nodes: one of {"validator", "full_node"}
    role: String,
    #[structopt(short = "u", long)]
    /// Config directory for upstream node. This field is needed if role is "full_node"
    upstream_config_dir: Option<String>,
}

fn main() {
    let args = Args::from_args();
    let output_dir = if let Some(output_dir) = args.output_dir.as_ref() {
        output_dir.clone()
    } else {
        ::std::env::current_dir().expect("Failed to access current directory.")
    };
    let (faucet_account_keypair, _faucet_key_file_path, _temp_dir) =
        generate_keypair::load_faucet_key_or_create_default(Some(args.faucet_account_file.clone()));
    let role: RoleType = args.role.clone().into();

    let mut config_builder = SwarmConfigBuilder::new();
    config_builder
        .with_num_nodes(args.nodes)
        .with_role(role)
        .with_base(&args.base)
        .with_output_dir(output_dir)
        .with_faucet_keypair(faucet_account_keypair)
        .with_upstream_config_dir(args.upstream_config_dir.clone());

    if args.discovery {
        config_builder.force_discovery();
    }
    if let Some(key_seed) = args.key_seed.as_ref() {
        let seed = hex::decode(key_seed).expect("Invalid hex in seed.");
        config_builder.with_key_seed(
            seed[..32]
                .try_into()
                .expect("Seed should be 32 bytes long."),
        );
    }
    config_builder.build().expect("Unable to generate configs");
}
<|endoftext|>


<commit_before>//! Checks that the expression do not contain any invalid recursive bindings.
use std::fmt;
use std::mem;

use base::{
    ast::{self, Expr, Pattern, SpannedExpr, SpannedIdent, SpannedPattern, TypedIdent, Visitor},
    error::Errors,
    fnv::FnvMap,
    pos::{self, BytePos, Span, Spanned},
    symbol::Symbol,
};

#[derive(Debug, PartialEq)]
pub enum Error {
    InvalidRecursion { symbol: Symbol },
    LastExprMustBeConstructor,
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::InvalidRecursion { symbol } => write!(
                f,
                "`{}` may not be used recursively here",
                symbol.declared_name()
            ),
            Error::LastExprMustBeConstructor => write!(
                f,
                "The last expression a recursive binding must construct a record, a tuple, a variant or a lambda"
            ),
        }
    }
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
enum Context {
    Lazy,
    Top(usize),
}

impl Context {
    fn replace(&mut self, new_context: Context) -> Context {
        let old = *self;
        *self = new_context;
        old
    }
}

#[derive(Debug)]
struct Checker {
    /// Symbols that are uninitialized at this point in the program
    uninitialized_values: FnvMap<Symbol, usize>,
    level: usize,
    /// Uninitialized symbols that are used in the current expression
    uninitialized_free_variables: Vec<Spanned<Symbol, BytePos>>,
    /// Initialized symbols that are used in the current expression (as long as the function that
    /// contains them do not get called before the symbols are initialized).
    free_variables: Vec<Spanned<Symbol, BytePos>>,
    context: Context,
    errors: RecursionErrors,
}

pub type RecursionErrors = Errors<Spanned<Error, BytePos>>;

pub fn check_expr(expr: &SpannedExpr<Symbol>) -> Result<(), RecursionErrors> {
    let mut checker = Checker {
        uninitialized_values: FnvMap::default(),
        level: 0,
        uninitialized_free_variables: Vec::new(),
        free_variables: Vec::new(),
        context: Context::Top(0),
        errors: Errors::new(),
    };
    checker.visit_expr(expr);
    if checker.errors.has_errors() {
        Err(checker.errors)
    } else {
        Ok(())
    }
}

fn is_constructor_expr(expr: &SpannedExpr<Symbol>) -> bool {
    match expr.value {
        Expr::App { ref func, .. } => is_constructor_ident(func),
        _ => false,
    }
}

fn is_constructor_ident(expr: &SpannedExpr<Symbol>) -> bool {
    match expr.value {
        Expr::Ident(ref id) => id.name.declared_name().starts_with(char::is_uppercase),
        _ => false,
    }
}

impl Checker {
    fn check_ident(&mut self, span: Span<BytePos>, id: &Symbol) {
        let uninitialized_status = self.uninitialized_values.get(id);
        if uninitialized_status.is_some() {
            self.uninitialized_free_variables
                .push(pos::spanned(span, id.clone()));
        } else {
            self.free_variables.push(pos::spanned(span, id.clone()));
        }
    }

    // A recursive bindings is only allowed if it ends in constructing a value, if it doesn't it is
    // not possible to pre-allocate storage for the value and compile the binding.
    fn check_tail(&mut self, expr: &SpannedExpr<Symbol>) {
        match expr.value {
            Expr::Block(ref bs) => self.check_tail(bs.last().unwrap()),
            Expr::LetBindings(_, ref e) | Expr::TypeBindings(_, ref e) => {
                self.check_tail(e);
            }
            Expr::IfElse(_, ref if_true, ref if_false) => {
                self.check_tail(if_true);
                self.check_tail(if_false);
            }
            Expr::Match(_, ref alts) => for alt in alts {
                self.check_tail(&alt.expr);
            },
            Expr::Record { .. } | Expr::Tuple { .. } | Expr::Lambda { .. } => (),
            Expr::App { ref func, .. } => if !is_constructor_ident(func) {
                self.errors
                    .push(pos::spanned(expr.span, Error::LastExprMustBeConstructor))
            },
            _ => self
                .errors
                .push(pos::spanned(expr.span, Error::LastExprMustBeConstructor)),
        }
    }

    fn taint_pattern(&mut self, pattern: &SpannedPattern<Symbol>) {
        struct TaintPattern<'a>(&'a mut Checker);
        impl<'a, 'b> Visitor<'a> for TaintPattern<'b> {
            type Ident = Symbol;
            fn visit_ident(&mut self, id: &TypedIdent<Symbol>) {
                self.0
                    .uninitialized_values
                    .insert(id.name.clone(), self.0.level);
            }
            fn visit_spanned_ident(&mut self, id: &Spanned<Symbol, BytePos>) {
                self.0
                    .uninitialized_values
                    .insert(id.value.clone(), self.0.level);
            }
        }

        TaintPattern(self).visit_pattern(pattern)
    }

    fn visit_function_body(&mut self, body: &SpannedExpr<Symbol>) {
        let uninitialized_values = mem::replace(&mut self.uninitialized_values, Default::default());
        self.visit_expr(body);
        let context = self.replace(Context::Lazy);

        self.uninitialized_free_variables.extend(
            self.free_variables
                .drain(..)
                .filter(|id| uninitialized_values.contains_key(&id.value)),
        );
        self.uninitialized_values = uninitialized_values;
        self.context = context;
    }
}

impl<'a> Visitor<'a> for Checker {
    type Ident = Symbol;

    fn visit_spanned_typed_ident(&mut self, id: &SpannedIdent<Symbol>) {
        self.check_ident(id.span, &id.value.name);
    }

    fn visit_spanned_ident(&mut self, id: &Spanned<Symbol, BytePos>) {
        self.check_ident(id.span, &id.value);
    }

    fn visit_expr(&mut self, expr: &SpannedExpr<Symbol>) {
        match expr.value {
            Expr::Ident(ref id) => self.check_ident(expr.span, &id.name),

            Expr::LetBindings(ref bindings, ref expr) => {
                self.level += 1;
                let context = self.context.replace(Context::Top(self.level));

                let level = self.level;
                self.uninitialized_values.extend(
                    bindings
                        .iter()
                        .filter(|bind| bind.args.is_empty())
                        .filter_map(|bind| match bind.name.value {
                            Pattern::Ident(ref id) => Some((id.name.clone(), level)),
                            _ => None,
                        }),
                );

                for bind in bindings {
                    let start = self.uninitialized_free_variables.len();
                    let context = if !bind.args.is_empty() {
                        self.context.replace(Context::Lazy)
                    } else {
                        self.context
                    };

                    if bind.args.is_empty() {
                        self.visit_expr(&bind.expr);
                    } else {
                        self.visit_function_body(&bind.expr);
                    }

                    self.context = context;

                    if !self.uninitialized_free_variables[start..].is_empty() {
                        match bind.name.value {
                            Pattern::Ident(ref id) => if self.uninitialized_free_variables[start..]
                                .iter()
                                .any(|used| used.value == id.name)
                            {
                                // Since the binding itself appeared in this binding we must must
                                // make sure that the binding can be recursively initialized. This
                                // is only true if the vm can allocate the binding immediately and
                                // fill in the values later.
                                self.check_tail(&bind.expr);
                            },
                            _ => (),
                        }

                        self.taint_pattern(&bind.name);
                    }
                    if let Pattern::Ident(ref id) = bind.name.value {
                        if self.uninitialized_free_variables[start..]
                            .iter()
                            .all(|var| var.value == id.name)
                        {
                            // The binding is now initialized
                            self.uninitialized_values.remove(&id.name);
                        }
                    }
                }

                self.context = context;
                self.level -= 1;

                self.visit_expr(expr);
            }

            Expr::TypeBindings(_, ref expr) => self.visit_expr(expr),

            Expr::Lambda(ref lambda) => self.visit_function_body(&lambda.body),

            Expr::App { .. } | Expr::Infix { .. } => {
                let start = self.uninitialized_free_variables.len();

                ast::walk_expr(self, expr);

                // Functions may do arbitrary things so don't allow function calls that refer to
                // uninitialized variables
                if !is_constructor_expr(expr) {
                    let used_uninitialized_variables = &self.uninitialized_free_variables[start..];
                    self.errors
                        .extend(used_uninitialized_variables.iter().map(|id| Spanned {
                            value: Error::InvalidRecursion {
                                symbol: id.value.clone(),
                            },
                            span: id.span,
                        }));
                }
            }

            Expr::Match(ref expr, ref alts) => {
                let start = self.uninitialized_free_variables.len();
                self.visit_expr(expr);

                // Match expressions may not be done on uninitialized values as they could then
                // view the uninitialized contents
                {
                    let used_uninitialized_variables = &self.uninitialized_free_variables[start..];
                    self.errors
                        .extend(used_uninitialized_variables.iter().map(|id| Spanned {
                            value: Error::InvalidRecursion {
                                symbol: id.value.clone(),
                            },
                            span: id.span,
                        }));
                }

                for alt in alts {
                    self.visit_expr(&alt.expr);
                }
            }
            _ => ast::walk_expr(self, expr),
        }
    }
}
<commit_msg>Avoid deep stacks in the recursion checker<commit_after>//! Checks that the expression do not contain any invalid recursive bindings.
use std::fmt;
use std::mem;

use base::{
    ast::{self, Expr, Pattern, SpannedExpr, SpannedIdent, SpannedPattern, TypedIdent, Visitor},
    error::Errors,
    fnv::FnvMap,
    pos::{self, BytePos, Span, Spanned},
    symbol::Symbol,
};

#[derive(Debug, PartialEq)]
pub enum Error {
    InvalidRecursion { symbol: Symbol },
    LastExprMustBeConstructor,
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::InvalidRecursion { symbol } => write!(
                f,
                "`{}` may not be used recursively here",
                symbol.declared_name()
            ),
            Error::LastExprMustBeConstructor => write!(
                f,
                "The last expression a recursive binding must construct a record, a tuple, a variant or a lambda"
            ),
        }
    }
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
enum Context {
    Lazy,
    Top(usize),
}

impl Context {
    fn replace(&mut self, new_context: Context) -> Context {
        let old = *self;
        *self = new_context;
        old
    }
}

#[derive(Debug)]
struct Checker {
    /// Symbols that are uninitialized at this point in the program
    uninitialized_values: FnvMap<Symbol, usize>,
    level: usize,
    /// Uninitialized symbols that are used in the current expression
    uninitialized_free_variables: Vec<Spanned<Symbol, BytePos>>,
    /// Initialized symbols that are used in the current expression (as long as the function that
    /// contains them do not get called before the symbols are initialized).
    free_variables: Vec<Spanned<Symbol, BytePos>>,
    context: Context,
    errors: RecursionErrors,
}

pub type RecursionErrors = Errors<Spanned<Error, BytePos>>;

pub fn check_expr(expr: &SpannedExpr<Symbol>) -> Result<(), RecursionErrors> {
    let mut checker = Checker {
        uninitialized_values: FnvMap::default(),
        level: 0,
        uninitialized_free_variables: Vec::new(),
        free_variables: Vec::new(),
        context: Context::Top(0),
        errors: Errors::new(),
    };
    checker.visit_expr(expr);
    if checker.errors.has_errors() {
        Err(checker.errors)
    } else {
        Ok(())
    }
}

fn is_constructor_expr(expr: &SpannedExpr<Symbol>) -> bool {
    match expr.value {
        Expr::App { ref func, .. } => is_constructor_ident(func),
        _ => false,
    }
}

fn is_constructor_ident(expr: &SpannedExpr<Symbol>) -> bool {
    match expr.value {
        Expr::Ident(ref id) => id.name.declared_name().starts_with(char::is_uppercase),
        _ => false,
    }
}

impl Checker {
    fn check_ident(&mut self, span: Span<BytePos>, id: &Symbol) {
        let uninitialized_status = self.uninitialized_values.get(id);
        if uninitialized_status.is_some() {
            self.uninitialized_free_variables
                .push(pos::spanned(span, id.clone()));
        } else {
            self.free_variables.push(pos::spanned(span, id.clone()));
        }
    }

    // A recursive bindings is only allowed if it ends in constructing a value, if it doesn't it is
    // not possible to pre-allocate storage for the value and compile the binding.
    fn check_tail(&mut self, expr: &SpannedExpr<Symbol>) {
        match expr.value {
            Expr::Block(ref bs) => self.check_tail(bs.last().unwrap()),
            Expr::LetBindings(_, ref e) | Expr::TypeBindings(_, ref e) => {
                self.check_tail(e);
            }
            Expr::IfElse(_, ref if_true, ref if_false) => {
                self.check_tail(if_true);
                self.check_tail(if_false);
            }
            Expr::Match(_, ref alts) => for alt in alts {
                self.check_tail(&alt.expr);
            },
            Expr::Record { .. } | Expr::Tuple { .. } | Expr::Lambda { .. } => (),
            Expr::App { ref func, .. } => if !is_constructor_ident(func) {
                self.errors
                    .push(pos::spanned(expr.span, Error::LastExprMustBeConstructor))
            },
            _ => self
                .errors
                .push(pos::spanned(expr.span, Error::LastExprMustBeConstructor)),
        }
    }

    fn taint_pattern(&mut self, pattern: &SpannedPattern<Symbol>) {
        struct TaintPattern<'a>(&'a mut Checker);
        impl<'a, 'b> Visitor<'a> for TaintPattern<'b> {
            type Ident = Symbol;
            fn visit_ident(&mut self, id: &TypedIdent<Symbol>) {
                self.0
                    .uninitialized_values
                    .insert(id.name.clone(), self.0.level);
            }
            fn visit_spanned_ident(&mut self, id: &Spanned<Symbol, BytePos>) {
                self.0
                    .uninitialized_values
                    .insert(id.value.clone(), self.0.level);
            }
        }

        TaintPattern(self).visit_pattern(pattern)
    }

    fn visit_function_body(&mut self, body: &SpannedExpr<Symbol>) {
        let uninitialized_values = mem::replace(&mut self.uninitialized_values, Default::default());
        self.visit_expr(body);
        let context = self.replace(Context::Lazy);

        self.uninitialized_free_variables.extend(
            self.free_variables
                .drain(..)
                .filter(|id| uninitialized_values.contains_key(&id.value)),
        );
        self.uninitialized_values = uninitialized_values;
        self.context = context;
    }

    fn check_expr<'a>(&mut self, expr: &'a SpannedExpr<Symbol>) -> Option<&'a SpannedExpr<Symbol>> {
        match expr.value {
            Expr::Ident(ref id) => self.check_ident(expr.span, &id.name),

            Expr::LetBindings(ref bindings, ref expr) => {
                self.level += 1;
                let context = self.context.replace(Context::Top(self.level));

                let level = self.level;
                self.uninitialized_values.extend(
                    bindings
                        .iter()
                        .filter(|bind| bind.args.is_empty())
                        .filter_map(|bind| match bind.name.value {
                            Pattern::Ident(ref id) => Some((id.name.clone(), level)),
                            _ => None,
                        }),
                );

                for bind in bindings {
                    let start = self.uninitialized_free_variables.len();
                    let context = if !bind.args.is_empty() {
                        self.context.replace(Context::Lazy)
                    } else {
                        self.context
                    };

                    if bind.args.is_empty() {
                        self.visit_expr(&bind.expr);
                    } else {
                        self.visit_function_body(&bind.expr);
                    }

                    self.context = context;

                    if !self.uninitialized_free_variables[start..].is_empty() {
                        match bind.name.value {
                            Pattern::Ident(ref id) => if self.uninitialized_free_variables[start..]
                                .iter()
                                .any(|used| used.value == id.name)
                            {
                                // Since the binding itself appeared in this binding we must must
                                // make sure that the binding can be recursively initialized. This
                                // is only true if the vm can allocate the binding immediately and
                                // fill in the values later.
                                self.check_tail(&bind.expr);
                            },
                            _ => (),
                        }

                        self.taint_pattern(&bind.name);
                    }
                    if let Pattern::Ident(ref id) = bind.name.value {
                        if self.uninitialized_free_variables[start..]
                            .iter()
                            .all(|var| var.value == id.name)
                        {
                            // The binding is now initialized
                            self.uninitialized_values.remove(&id.name);
                        }
                    }
                }

                self.context = context;
                self.level -= 1;
                return Some(expr);
            }

            Expr::TypeBindings(_, ref expr) => return Some(expr),

            Expr::Lambda(ref lambda) => self.visit_function_body(&lambda.body),

            Expr::App { .. } | Expr::Infix { .. } => {
                let start = self.uninitialized_free_variables.len();

                ast::walk_expr(self, expr);

                // Functions may do arbitrary things so don't allow function calls that refer to
                // uninitialized variables
                if !is_constructor_expr(expr) {
                    let used_uninitialized_variables = &self.uninitialized_free_variables[start..];
                    self.errors
                        .extend(used_uninitialized_variables.iter().map(|id| Spanned {
                            value: Error::InvalidRecursion {
                                symbol: id.value.clone(),
                            },
                            span: id.span,
                        }));
                }
            }

            Expr::Match(ref expr, ref alts) => {
                let start = self.uninitialized_free_variables.len();
                self.visit_expr(expr);

                // Match expressions may not be done on uninitialized values as they could then
                // view the uninitialized contents
                {
                    let used_uninitialized_variables = &self.uninitialized_free_variables[start..];
                    self.errors
                        .extend(used_uninitialized_variables.iter().map(|id| Spanned {
                            value: Error::InvalidRecursion {
                                symbol: id.value.clone(),
                            },
                            span: id.span,
                        }));
                }

                for alt in alts {
                    self.visit_expr(&alt.expr);
                }
            }
            _ => ast::walk_expr(self, expr),
        }
        None
    }
}

impl<'a> Visitor<'a> for Checker {
    type Ident = Symbol;

    fn visit_spanned_typed_ident(&mut self, id: &SpannedIdent<Symbol>) {
        self.check_ident(id.span, &id.value.name);
    }

    fn visit_spanned_ident(&mut self, id: &Spanned<Symbol, BytePos>) {
        self.check_ident(id.span, &id.value);
    }

    fn visit_expr(&mut self, mut expr: &SpannedExpr<Symbol>) {
        while let Some(next) = self.check_expr(expr) {
            expr = next;
        }
    }
}
<|endoftext|>


<commit_before>extern crate server;
extern crate bincode;
extern crate log;

use server::storage::*;
use bincode::rustc_serialize::{encode_into};
use bincode::SizeLimit;
use server::logger;
use server::parse::ast::DataSrc;
use std::io::Cursor;
//use server::storage::engine::flatfile::FlatFile;

fn main() {

    logger::with_loglevel(::log::LogLevelFilter::Trace)
        .with_logfile(std::path::Path::new("log.txt"))
        .enable().unwrap();

    let ty = SqlType::Int;
    let mut v = Vec::new();
    let _ = encode_into(&ty, &mut v, SizeLimit::Infinite);

    //let db = Database::create("storage_team").unwrap();
    let db = Database::load("storage_team").unwrap();

    let mut cols = Vec::new();
    cols.push(Column {
        name: "Heiner".into(),
        sql_type: SqlType::Int,
        allow_null: false,
        description: "Heiner".to_string(),
        is_primary_key: true,
    });
    cols.push(Column {
        name: "Mathias".into(),
        sql_type: SqlType::Bool,
        allow_null: false,
        description: "Mathias".to_string(),
        is_primary_key: false,
    });
    cols.push(Column {
        name: "Dennis".into(),
        sql_type: SqlType::Char(6),
        allow_null: false,
        description: "Dennis".to_string(),
        is_primary_key: false,
    });

    let mut my_data: Vec<Option<DataSrc>> = Vec::new();
    my_data.push(Some(DataSrc::Int(10)));
    my_data.push(Some(DataSrc::Bool(1)));
    my_data.push(Some(DataSrc::String("sechs".to_string())));

   //let _storage_team = db.create_table("storage_team", cols, 1).unwrap();

   let _storage_team = db.load_table("storage_team").unwrap();

    //RRROOOOWWWWSSS
    let v = Vec::<u8>::new();
    let c = Cursor::new(v);
    let data = vec![1, 2, 3, 4, 1, 0x48, 0x41, 0x4C, 0x4C, 0x4F, 0x00];

    let mut rows = Rows::new(c, &_storage_team.columns());
    rows.add_row(&data).unwrap();
    rows.reset_pos().unwrap();

    let mut d = Vec::<u8>::new();

    rows.next_row(&mut d).unwrap();
    println!{"{:?}", d}

    let h = rows.get_value(&d, 2);
    println!{"{:?}", h}

    rows.delete_row().unwrap();

    rows.reset_pos().unwrap();

    d.clear();

    flat_file_test();

}

fn flat_file_test() {
    println!("start flat file test");

    let data = Database::load("storage_team").unwrap();

    {
        let t = data.load_table("storage_team").unwrap();
        let mut engine = FlatFile::new(t);
        engine.create_table().unwrap();
        let mut rnd_data = vec![0, 0, 0, 1, 0, 0x48, 0x41, 0x4C, 0x4C, 0x4F, 0x00];

        engine.insert_row(&rnd_data).unwrap();
        rnd_data = vec![0, 0, 0, 2, 0, 0x48, 0x41, 0x4C, 0x4C, 0x4F, 0x00];
        engine.insert_row(&rnd_data).unwrap();

        rnd_data = vec![0, 0, 0, 3, 0, 0x48, 0x41, 0x4C, 0x4D, 0x4F, 0x00];
        engine.insert_row(&rnd_data).unwrap();

        rnd_data = vec![0, 0, 0, 4, 1, 0x48, 0x41, 0x4C, 0x4D, 0x4F, 0x00];
        engine.insert_row(&rnd_data).unwrap();
    }

    let t = data.load_table("storage_team").unwrap();
    let mut engine = FlatFile::new(t);

    // delete with bool
    let my_bool: [u8; 1] = [0x01];
    engine.delete(1, &my_bool[..], CompType::Equ).unwrap();

    // delete with char
    // let my_char: [u8; 6] = [0x48, 0x41, 0x4C, 0x4D, 0x4F, 0x00];
    // println!("{:?}", my_char);
    // engine.delete(2,&my_char[0..6],CompType::Equ).unwrap();

    println!("///////////////////////////////////////////////////////////////");
    println!("/////////////////////// Lookup ////////////////////////////////");
    println!("///////////////////////////////////////////////////////////////");

    let my_int: [u8; 4] = [0, 0, 0, 1];
    let mut rows = engine.lookup(0,&my_int[0..4],CompType::Equ).unwrap();
    rows.reset_pos().unwrap();

    println!("engine.lookup rows: {:?}", rows);

    println!("///////////////////////////////////////////////////////////////");
    println!("//////////////////////// Delete ///////////////////////////////");
    println!("///////////////////////////////////////////////////////////////");

    engine.delete(0,&my_int[0..4],CompType::Equ).unwrap();
    rows.reset_pos().unwrap();

    rows = engine.full_scan().unwrap();
    println!("the rows: {:?}", rows);
    rows.reset_pos().unwrap();

    // modify a char
    let my_char: [u8; 6] = [0x48, 0x41, 0x4C, 0x4D, 0x4F, 0x00];
    let my_char2: [u8; 6] = [0x48, 0x41, 0x4C, 0x4c, 0x4C, 0x00];
    let values = [(2 as usize, &(my_char2[..]))];
    println!("///////////////////////////////////////////////////////////////");
    println!("//////////////////////// Modify ///////////////////////////////");
    println!("///////////////////////////////////////////////////////////////");
    engine.modify(2, &my_char, CompType::Equ, &values).unwrap();

    rows.reset_pos().unwrap();

    rows = engine.full_scan().unwrap();
    println!("the rows: {:?}", rows);
    //rows.reset_pos().unwrap();

    rows = engine.full_scan().unwrap();
    println!("the rows2: {:?}", rows);

    let mut cols = Vec::new();
    cols.push(Column {
        name: "Heiner".into(),
        sql_type: SqlType::Char(6),
        allow_null: false,
        description: "Heiner".to_string(),
        is_primary_key: true,
    });

    let db = Database::create("test").unwrap();
    let _test = db.create_table("test", cols, 1).unwrap();

    let mut engine = FlatFile::new(_test);
    engine.create_table().unwrap();

    let mut rnd_data = vec![0x48, 0x41, 0x4C, 0x4C, 0x4F, 0x00];
    engine.insert_row(&rnd_data).unwrap();

    rows = engine.full_scan().unwrap();
    println!("the rows: {:?}", rows);

    rnd_data = vec![0x48, 0x41, 0x4C, 0x4C, 0x4D, 0x00];
    engine.insert_row(&rnd_data).unwrap();

    let rows2 = engine.full_scan().unwrap();
    println!("the rows2: {:?}", rows2);
}

fn _type_test() {
    let my_int: [u8; 4] = [20, 30, 40, 50]; //0001:0100:0001:1110:0010:1000:0011:0010 -> 337520690
    let my_other_int: [u8; 4] = [10, 5, 0, 2];//0000:1010:0000:0101:0000:0000:0000:0010 -> 168099842

    let my_bool: [u8; 3] = [0, 0, 0];
    let my_other_bool: [u8; 3] = [0, 0, 0];

    let my_strin: [u8; 2] = [0, 41];
    let my_other_strin: [u8; 2] = [0, 41];

    let my_sqltype_int = SqlType::Int;
    let my_sqltype_bool = SqlType::Bool;
    let my_sqltype_char = SqlType::Char(7);
    println!("check for int:");

    println!("is equal: {:?}",my_sqltype_int.cmp(
        &my_int[0..4], &my_other_int[0..4], CompType::Equ).unwrap()
    );
    println!("is not equal: {:?}",my_sqltype_int.cmp(
        &my_int[0..4], &my_other_int[0..4], CompType::NEqu).unwrap()
    );
    println!("is greater: {:?}",my_sqltype_int.cmp(
        &my_int[0..4], &my_other_int[0..4], CompType::GThan).unwrap()
    );
    println!("is lesser: {:?}",my_sqltype_int.cmp(
        &my_int[0..4], &my_other_int[0..4], CompType::SThan).unwrap()
    );
    println!("is greater equal: {:?}",my_sqltype_int.cmp(
        &my_int[0..4], &my_other_int[0..4], CompType::GEThan).unwrap()
    );
    println!("is lesser equal: {:?}",my_sqltype_int.cmp(
        &my_int[0..4], &my_other_int[0..4], CompType::SEThan).unwrap()
    );

    println!("check for bool:");
    println!("is equal: {:?}",my_sqltype_bool.cmp(
        &my_bool[0..3], &my_other_bool[0..3], CompType::Equ).unwrap()
    );
    println!("is not equal: {:?}",my_sqltype_bool.cmp(
        &my_bool[0..3], &my_other_bool[0..3], CompType::NEqu).unwrap()
    );

    println!("check for string:");
    println!("is equal: {:?}",my_sqltype_char.cmp(
        &my_strin[0..2], &my_other_strin[0..2], CompType::Equ).unwrap()
    );
    println!("is not equal: {:?}",my_sqltype_char.cmp(
        &my_strin[0..2], &my_other_strin[0..2], CompType::NEqu).unwrap()
    );

}
<commit_msg>fix table_test<commit_after>extern crate server;
extern crate bincode;
extern crate log;

use server::storage::*;
use bincode::rustc_serialize::{encode_into};
use bincode::SizeLimit;
use server::logger;
use server::parse::ast::DataSrc;
use std::io::Cursor;

fn main() {

    logger::with_loglevel(::log::LogLevelFilter::Trace)
        .with_logfile(std::path::Path::new("log.txt"))
        .enable().unwrap();

    let ty = SqlType::Int;
    let mut v = Vec::new();
    let _ = encode_into(&ty, &mut v, SizeLimit::Infinite);

    //let db = Database::create("storage_team").unwrap();
    let db = Database::load("storage_team").unwrap();

    let mut cols = Vec::new();
    cols.push(Column {
        name: "Heiner".into(),
        sql_type: SqlType::Int,
        allow_null: false,
        description: "Heiner".to_string(),
        is_primary_key: true,
    });
    cols.push(Column {
        name: "Mathias".into(),
        sql_type: SqlType::Bool,
        allow_null: false,
        description: "Mathias".to_string(),
        is_primary_key: false,
    });
    cols.push(Column {
        name: "Dennis".into(),
        sql_type: SqlType::Char(6),
        allow_null: false,
        description: "Dennis".to_string(),
        is_primary_key: false,
    });

    let mut my_data: Vec<Option<DataSrc>> = Vec::new();
    my_data.push(Some(DataSrc::Int(10)));
    my_data.push(Some(DataSrc::Bool(1)));
    my_data.push(Some(DataSrc::String("sechs".to_string())));

   //let _storage_team = db.create_table("storage_team", cols, 1).unwrap();

   let _storage_team = db.load_table("storage_team").unwrap();

    //RRROOOOWWWWSSS
    let v = Vec::<u8>::new();
    let c = Cursor::new(v);
    let data = vec![1, 2, 3, 4, 1, 0x48, 0x41, 0x4C, 0x4C, 0x4F, 0x00];

    let mut rows = Rows::new(c, &_storage_team.columns());
    rows.add_row(&data).unwrap();
    rows.reset_pos().unwrap();

    let mut d = Vec::<u8>::new();

    rows.next_row(&mut d).unwrap();
    println!{"{:?}", d}

    let h = rows.get_value(&d, 2);
    println!{"{:?}", h}

    rows.delete_row().unwrap();

    rows.reset_pos().unwrap();

    d.clear();

    flat_file_test();

}

fn flat_file_test() {
    println!("start flat file test");

    let data = Database::load("storage_team").unwrap();

    {
        let t = data.load_table("storage_team").unwrap();
        let mut engine = FlatFile::new(t);
        engine.create_table().unwrap();
        let mut rnd_data = vec![0, 0, 0, 1, 0, 0x48, 0x41, 0x4C, 0x4C, 0x4F, 0x00];

        engine.insert_row(&rnd_data).unwrap();
        rnd_data = vec![0, 0, 0, 2, 0, 0x48, 0x41, 0x4C, 0x4C, 0x4F, 0x00];
        engine.insert_row(&rnd_data).unwrap();

        rnd_data = vec![0, 0, 0, 3, 0, 0x48, 0x41, 0x4C, 0x4D, 0x4F, 0x00];
        engine.insert_row(&rnd_data).unwrap();

        rnd_data = vec![0, 0, 0, 4, 1, 0x48, 0x41, 0x4C, 0x4D, 0x4F, 0x00];
        engine.insert_row(&rnd_data).unwrap();
    }

    let t = data.load_table("storage_team").unwrap();
    let mut engine = FlatFile::new(t);

    // delete with bool
    let my_bool: [u8; 1] = [0x01];
    engine.delete(1, &my_bool[..], CompType::Equ).unwrap();

    // delete with char
    // let my_char: [u8; 6] = [0x48, 0x41, 0x4C, 0x4D, 0x4F, 0x00];
    // println!("{:?}", my_char);
    // engine.delete(2,&my_char[0..6],CompType::Equ).unwrap();

    println!("///////////////////////////////////////////////////////////////");
    println!("/////////////////////// Lookup ////////////////////////////////");
    println!("///////////////////////////////////////////////////////////////");

    let my_int: [u8; 4] = [0, 0, 0, 1];
    let mut rows = engine.lookup(0,&my_int[0..4],CompType::Equ).unwrap();
    rows.reset_pos().unwrap();

    println!("engine.lookup rows: {:?}", rows);

    println!("///////////////////////////////////////////////////////////////");
    println!("//////////////////////// Delete ///////////////////////////////");
    println!("///////////////////////////////////////////////////////////////");

    engine.delete(0,&my_int[0..4],CompType::Equ).unwrap();
    rows.reset_pos().unwrap();

    rows = engine.full_scan().unwrap();
    println!("the rows: {:?}", rows);
    rows.reset_pos().unwrap();

    // modify a char
    let my_char: [u8; 6] = [0x48, 0x41, 0x4C, 0x4D, 0x4F, 0x00];
    let my_char2: [u8; 6] = [0x48, 0x41, 0x4C, 0x4c, 0x4C, 0x00];
    let values = [(2 as usize, &(my_char2[..]))];
    println!("///////////////////////////////////////////////////////////////");
    println!("//////////////////////// Modify ///////////////////////////////");
    println!("///////////////////////////////////////////////////////////////");
    engine.modify(2, &my_char, CompType::Equ, &values).unwrap();

    rows.reset_pos().unwrap();

    rows = engine.full_scan().unwrap();
    println!("the rows: {:?}", rows);
    //rows.reset_pos().unwrap();

    rows = engine.full_scan().unwrap();
    println!("the rows2: {:?}", rows);

    let mut cols = Vec::new();
    cols.push(Column {
        name: "Heiner".into(),
        sql_type: SqlType::Char(6),
        allow_null: false,
        description: "Heiner".to_string(),
        is_primary_key: true,
    });

    let db = Database::create("test").unwrap();
    let _test = db.create_table("test", cols, EngineID::FlatFile).unwrap();

    let mut engine = FlatFile::new(_test);
    engine.create_table().unwrap();

    let mut rnd_data = vec![0x48, 0x41, 0x4C, 0x4C, 0x4F, 0x00];
    engine.insert_row(&rnd_data).unwrap();

    rows = engine.full_scan().unwrap();
    println!("the rows: {:?}", rows);

    rnd_data = vec![0x48, 0x41, 0x4C, 0x4C, 0x4D, 0x00];
    engine.insert_row(&rnd_data).unwrap();

    let rows2 = engine.full_scan().unwrap();
    println!("the rows2: {:?}", rows2);
}

fn _type_test() {
    let my_int: [u8; 4] = [20, 30, 40, 50]; //0001:0100:0001:1110:0010:1000:0011:0010 -> 337520690
    let my_other_int: [u8; 4] = [10, 5, 0, 2];//0000:1010:0000:0101:0000:0000:0000:0010 -> 168099842

    let my_bool: [u8; 3] = [0, 0, 0];
    let my_other_bool: [u8; 3] = [0, 0, 0];

    let my_strin: [u8; 2] = [0, 41];
    let my_other_strin: [u8; 2] = [0, 41];

    let my_sqltype_int = SqlType::Int;
    let my_sqltype_bool = SqlType::Bool;
    let my_sqltype_char = SqlType::Char(7);
    println!("check for int:");

    println!("is equal: {:?}",my_sqltype_int.cmp(
        &my_int[0..4], &my_other_int[0..4], CompType::Equ).unwrap()
    );
    println!("is not equal: {:?}",my_sqltype_int.cmp(
        &my_int[0..4], &my_other_int[0..4], CompType::NEqu).unwrap()
    );
    println!("is greater: {:?}",my_sqltype_int.cmp(
        &my_int[0..4], &my_other_int[0..4], CompType::GThan).unwrap()
    );
    println!("is lesser: {:?}",my_sqltype_int.cmp(
        &my_int[0..4], &my_other_int[0..4], CompType::SThan).unwrap()
    );
    println!("is greater equal: {:?}",my_sqltype_int.cmp(
        &my_int[0..4], &my_other_int[0..4], CompType::GEThan).unwrap()
    );
    println!("is lesser equal: {:?}",my_sqltype_int.cmp(
        &my_int[0..4], &my_other_int[0..4], CompType::SEThan).unwrap()
    );

    println!("check for bool:");
    println!("is equal: {:?}",my_sqltype_bool.cmp(
        &my_bool[0..3], &my_other_bool[0..3], CompType::Equ).unwrap()
    );
    println!("is not equal: {:?}",my_sqltype_bool.cmp(
        &my_bool[0..3], &my_other_bool[0..3], CompType::NEqu).unwrap()
    );

    println!("check for string:");
    println!("is equal: {:?}",my_sqltype_char.cmp(
        &my_strin[0..2], &my_other_strin[0..2], CompType::Equ).unwrap()
    );
    println!("is not equal: {:?}",my_sqltype_char.cmp(
        &my_strin[0..2], &my_other_strin[0..2], CompType::NEqu).unwrap()
    );

}
<|endoftext|>


<commit_before>use byteorder::{LittleEndian, WriteBytesExt};

#[cfg(target_arch = "x86_64")]
pub use self::x64::*;

#[cfg(target_arch = "x86_64")]
pub mod x64;

#[cfg(target_arch = "aarch64")]
use self::arm64::*;

#[cfg(target_arch = "aarch64")]
pub mod arm64;

use std::convert::TryInto;

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct Label(usize);

pub struct Assembler {
    code: Vec<u8>,
    labels: Vec<Option<u32>>,
    unresolved_jumps: Vec<(u32, Label, JumpKind)>,
    position: usize,
}

impl Assembler {
    pub fn new() -> Assembler {
        Assembler {
            code: Vec::new(),
            labels: Vec::new(),
            unresolved_jumps: Vec::new(),
            position: 0,
        }
    }

    pub fn create_label(&mut self) -> Label {
        self.labels.push(None);

        Label(self.labels.len() - 1)
    }

    pub fn create_and_bind_label(&mut self) -> Label {
        self.labels.push(Some(self.position().try_into().unwrap()));
        Label(self.labels.len() - 1)
    }

    pub fn bind_label(&mut self, lbl: Label) {
        let Label(idx) = lbl;
        assert!(self.labels[idx].is_none());
        self.labels[idx] = Some(self.position().try_into().unwrap());
    }

    pub fn bind_label_to(&mut self, lbl: Label, offset: u32) {
        let Label(idx) = lbl;
        assert!(self.labels[idx].is_none());
        self.labels[idx] = Some(offset);
    }

    fn offset(&self, lbl: Label) -> Option<u32> {
        let Label(idx) = lbl;
        self.labels[idx]
    }

    pub fn finalize(mut self) -> Vec<u8> {
        self.resolve_jumps();
        self.code
    }

    pub fn position(&self) -> usize {
        self.position
    }

    pub fn set_position(&mut self, pos: usize) {
        self.position = pos;
    }

    pub fn set_position_end(&mut self) {
        self.position = self.code.len();
    }

    pub fn emit_u8(&mut self, value: u8) {
        if self.position == self.code.len() {
            self.code.push(value);
        } else {
            self.code[self.position] = value;
        }
        self.position += 1;
    }

    pub fn emit_u32(&mut self, value: u32) {
        if self.position == self.code.len() {
            self.code.write_u32::<LittleEndian>(value).unwrap()
        } else {
            (&mut self.code[self.position..])
                .write_u32::<LittleEndian>(value)
                .unwrap();
        }
        self.position += 4;
    }

    pub fn emit_u64(&mut self, value: u64) {
        if self.position == self.code.len() {
            self.code.write_u64::<LittleEndian>(value).unwrap()
        } else {
            (&mut self.code[self.position..])
                .write_u64::<LittleEndian>(value)
                .unwrap();
        }
        self.position += 8;
    }
}
<commit_msg>asm: introduce AssemblerBuffer<commit_after>use byteorder::{LittleEndian, WriteBytesExt};

#[cfg(target_arch = "x86_64")]
pub use self::x64::*;

#[cfg(target_arch = "x86_64")]
pub mod x64;

#[cfg(target_arch = "aarch64")]
use self::arm64::*;

#[cfg(target_arch = "aarch64")]
pub mod arm64;

use std::convert::TryInto;

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct Label(usize);

pub struct Assembler {
    unresolved_jumps: Vec<(u32, Label, JumpKind)>,
    buffer: AssemblerBuffer,
}

impl Assembler {
    pub fn new() -> Assembler {
        Assembler {
            unresolved_jumps: Vec::new(),
            buffer: AssemblerBuffer::new(),
        }
    }

    pub fn create_label(&mut self) -> Label {
        self.buffer.create_label()
    }

    pub fn create_and_bind_label(&mut self) -> Label {
        self.buffer.create_and_bind_label()
    }

    pub fn bind_label(&mut self, lbl: Label) {
        self.buffer.bind_label(lbl);
    }

    pub fn bind_label_to(&mut self, lbl: Label, offset: u32) {
        self.buffer.bind_label_to(lbl, offset);
    }

    fn offset(&self, lbl: Label) -> Option<u32> {
        self.buffer.offset(lbl)
    }

    pub fn finalize(mut self) -> Vec<u8> {
        self.resolve_jumps();
        self.buffer.code
    }

    pub fn position(&self) -> usize {
        self.buffer.position()
    }

    pub fn set_position(&mut self, pos: usize) {
        self.buffer.set_position(pos);
    }

    pub fn set_position_end(&mut self) {
        self.buffer.set_position_end();
    }

    pub fn emit_u8(&mut self, value: u8) {
        self.buffer.emit_u8(value);
    }

    pub fn emit_u32(&mut self, value: u32) {
        self.buffer.emit_u32(value);
    }

    pub fn emit_u64(&mut self, value: u64) {
        self.buffer.emit_u64(value);
    }
}

struct AssemblerBuffer {
    code: Vec<u8>,
    position: usize,
    labels: Vec<Option<u32>>,
}

impl AssemblerBuffer {
    fn new() -> AssemblerBuffer {
        AssemblerBuffer {
            code: Vec::new(),
            position: 0,
            labels: Vec::new(),
        }
    }

    fn create_label(&mut self) -> Label {
        self.labels.push(None);

        Label(self.labels.len() - 1)
    }

    fn create_and_bind_label(&mut self) -> Label {
        self.labels.push(Some(self.position().try_into().unwrap()));
        Label(self.labels.len() - 1)
    }

    fn bind_label(&mut self, lbl: Label) {
        let Label(idx) = lbl;
        assert!(self.labels[idx].is_none());
        self.labels[idx] = Some(self.position().try_into().unwrap());
    }

    fn bind_label_to(&mut self, lbl: Label, offset: u32) {
        let Label(idx) = lbl;
        assert!(self.labels[idx].is_none());
        self.labels[idx] = Some(offset);
    }

    fn offset(&self, lbl: Label) -> Option<u32> {
        let Label(idx) = lbl;
        self.labels[idx]
    }

    fn position(&self) -> usize {
        self.position
    }

    fn set_position(&mut self, pos: usize) {
        self.position = pos;
    }

    fn set_position_end(&mut self) {
        self.position = self.code.len();
    }

    fn emit_u8(&mut self, value: u8) {
        if self.position == self.code.len() {
            self.code.push(value);
        } else {
            self.code[self.position] = value;
        }
        self.position += 1;
    }

    fn emit_u32(&mut self, value: u32) {
        if self.position == self.code.len() {
            self.code.write_u32::<LittleEndian>(value).unwrap()
        } else {
            (&mut self.code[self.position..])
                .write_u32::<LittleEndian>(value)
                .unwrap();
        }
        self.position += 4;
    }

    fn emit_u64(&mut self, value: u64) {
        if self.position == self.code.len() {
            self.code.write_u64::<LittleEndian>(value).unwrap()
        } else {
            (&mut self.code[self.position..])
                .write_u64::<LittleEndian>(value)
                .unwrap();
        }
        self.position += 8;
    }
}
<|endoftext|>


<commit_before>// Test that duplicate matcher binding names are caught at declaration time, rather than at macro
// invocation time.

#![allow(unused_macros)]
#![warn(duplicate_matcher_binding_name)]

macro_rules! foo1 {
    ($a:ident, $a:ident) => {}; //~ERROR duplicate matcher binding
    ($a:ident, $a:path) => {};  //~ERROR duplicate matcher binding
}

macro_rules! foo2 {
    ($a:ident) => {}; // OK
    ($a:path) => {};  // OK
}

macro_rules! foo3 {
    ($a:ident, $($a:ident),*) => {}; //~ERROR duplicate matcher binding
    ($($a:ident)+ # $($($a:path),+);*) => {}; //~ERROR duplicate matcher binding
}

fn main() {}
<commit_msg>remove warn<commit_after>// Test that duplicate matcher binding names are caught at declaration time, rather than at macro
// invocation time.

#![allow(unused_macros)]

macro_rules! foo1 {
    ($a:ident, $a:ident) => {}; //~ERROR duplicate matcher binding
    ($a:ident, $a:path) => {};  //~ERROR duplicate matcher binding
}

macro_rules! foo2 {
    ($a:ident) => {}; // OK
    ($a:path) => {};  // OK
}

macro_rules! foo3 {
    ($a:ident, $($a:ident),*) => {}; //~ERROR duplicate matcher binding
    ($($a:ident)+ # $($($a:path),+);*) => {}; //~ERROR duplicate matcher binding
}

fn main() {}
<|endoftext|>