<commit_before>
use super::cartridge::Cartridge;
use super::sound::Sound;
use super::lcd::Lcd;
use super::constants::*;

use num::FromPrimitive;
use std::io;
use std::collections::VecDeque;

use std::fs::File;
use std::io::Write;

#[derive(Debug,Clone,Serialize,Deserialize)]
pub struct Bus {
    pub cartridge: Cartridge,
    // TODO: Expose in better way
    pub lcd: Lcd,
    pub sound: Sound,
    wram: Vec<u8>,
    hram: Vec<u8>,
    pub io: IoPorts,
}

enum_from_primitive! {
#[derive(Debug,PartialEq)]
enum IoAddress {
    Joypad = 0xff00,
    Sb = 0xff01,
    Sc = 0xff02,
    Div = 0xff04,
    Tima = 0xff05,
    Tma = 0xff06,
    Tac = 0xff07,
    If = 0xff0f,
    Ie = 0xffff
}
}

#[derive(Debug,Clone,Serialize,Deserialize)]
pub struct Timers {
    div: u8,
    tima: u8,
    tma: u8,
    tac: u8,

    div_counter: isize,
    tima_counter: isize,
    tima_running: bool,
}

impl Timers {
    fn new() -> Timers {
        let mut timers = Timers {
            div: 0,
            tima: 0,
            tma: 0,
            tac: 0,
            div_counter: 0,
            tima_counter: 0,
            tima_running: false,
        };
        timers.write_tac(0);
        timers
    }

    pub fn tick(&mut self, cycles: usize) -> u8 {
        let mut interrupt = 0u8;

        if cycles > 12 {
            interrupt |= self.tick(12);
            interrupt |= self.tick(cycles - 12);
            return interrupt;
        }

        self.div_counter -= cycles as isize;
        if self.div_counter <= 0 {
            self.div_counter += (CPU_FREQ / 16384) as isize;
            self.div = self.div.wrapping_add(1);
        }

        if self.tima_running {
            self.tima_counter -= cycles as isize;
            if self.tima_counter <= 0 {
                self.tima_counter += (CPU_FREQ / self.get_tac_freq()) as isize;
                self.tima = self.tima.wrapping_add(1);
                if self.tima == 0 {
                    interrupt |= INT_MASK_TIMER;
                    self.tima = self.tma;
                }
            }
        }
        interrupt
    }

    fn get_tac_freq(&self) -> usize {
        match self.tac & 0x03 {
            0b00 => 4096,
            0b01 => 262144,
            0b10 => 65536,
            0b11 => 16384,
            _ => unreachable!(),
        }
    }
    fn write_div(&mut self) {
        self.div = 0;
        self.div_counter = 0;
    }
    fn write_tima(&mut self, value: u8) {
        self.tima = value;
        // self.tima_counter = (CPU_FREQ / self.get_tac_freq()) as isize - 4;
    }
    fn write_tma(&mut self, value: u8) {
        self.tma = value;
    }
    fn write_tac(&mut self, value: u8) {
        self.tac = value & 0x07;
        self.tima_running = (self.tac & 0x04) != 0;
        trace!("Setting tima freq to {}", self.get_tac_freq());
    }
}

#[derive(Debug,Clone,Serialize,Deserialize)]
pub struct IoPorts {
    joypad: u8,
    serial_data: u8,
    serial_transfer_control: u8,
    pub timers: Timers,

    // TODO expose through other means
    pub interrupt_enable: u8,
    pub interrupt_flags: u8,

    pub joypad_all_buttons: u8,

    pub serial_out: VecDeque<u8>,
}

impl IoPorts {
    fn new() -> IoPorts {
        IoPorts {
            joypad: 0xff,
            serial_data: 0,
            serial_transfer_control: 0,
            timers: Timers::new(),
            interrupt_enable: 0,
            interrupt_flags: 0,
            joypad_all_buttons: 0xff,
            serial_out: VecDeque::new()
        }
    }

    fn write(&mut self, addr: u16, value: u8) {
        match IoAddress::from_u16(addr) {
            Some(x) => {
                trace!("Writing 0x{:02X} to {:?} (0x{:04X})", value, x, addr);
                match x {
                    IoAddress::Joypad => {
                        self.joypad = value | !0x30;
                    }
                    IoAddress::Sb => self.serial_data = value,
                    IoAddress::Sc => {
                        if value & 0x80 == 0x80 {
                            self.serial_out.push_back(self.serial_data);
                        }
                    }
                    IoAddress::Div => self.timers.write_div(),
                    IoAddress::Tima => self.timers.write_tima(value),
                    IoAddress::Tma => self.timers.write_tma(value),
                    IoAddress::Tac => self.timers.write_tac(value),
                    IoAddress::Ie => self.interrupt_enable = value & 0x1f,
                    IoAddress::If => self.interrupt_flags = value & 0x1f,
                }
            }
            None => {
                debug!("WRITE 0x{:02X} to IOPORT 0x{:04X} not recognized (ignoring)",
                       value,
                       addr);
            }
        }
    }

    fn read(&self, addr: u16) -> u8 {
        match IoAddress::from_u16(addr) {
            Some(x) => {
                let value = match x {
                    IoAddress::Sb => self.serial_data,
                    IoAddress::Joypad => {
                        (if self.joypad & 0x10 == 0 {
                            self.joypad_all_buttons & 0xf
                        } else {
                            0
                        }) |
                        (if self.joypad & 0x20 == 0 {
                            self.joypad_all_buttons >> 4
                        } else {
                            0
                        }) | self.joypad & 0xf0
                    }
                    IoAddress::Sc => self.serial_transfer_control,
                    IoAddress::Div => self.timers.div,
                    IoAddress::Tima => self.timers.tima,
                    IoAddress::Tma => self.timers.tma,
                    IoAddress::Tac => self.timers.tac,
                    IoAddress::Ie => self.interrupt_enable,
                    IoAddress::If => self.interrupt_flags,
                    // _ => panic!("IOPORT {:02X} NOT MAPPED FOR READING", addr)
                };
                value
            }
            None => {
                warn!("READ from IOPORT 0x{:04X} not recognized (ignoring)", addr);
                0
            }
        }
    }
}

impl Bus {
    pub fn new(cartridge: Cartridge) -> Bus {
        Bus {
            hram: vec![0u8; 0x7f],
            wram: vec![0u8; 0x2000],
            lcd: Lcd::new(),
            sound: Sound::new(),
            cartridge: cartridge,
            io: IoPorts::new(),
        }
    }

    pub fn dequeue_samples(&mut self) -> Vec<(i8, i8)> {
        self.sound.dump_audio()
    }

    pub fn dump_wram(&mut self) -> io::Result<()> {
        let mut f = try!(File::create("wram.dump"));
        try!(f.write_all(&self.wram));
        Ok(())
    }

    pub fn read(&self, addr: u16) -> u8 {
        let value = match addr {
            MEM_LCD_IO_DMA => 0xff,
            MEM_CARTRIDGE_ROM_START...MEM_CARTRIDGE_ROM_END =>
                self.cartridge.read(addr),
            MEM_LCD_VRAM_START...MEM_LCD_VRAM_END => self.lcd.read(addr),
            MEM_CARTRIDGE_RAM_START...MEM_CARTRIDGE_RAM_END =>
                self.cartridge.read(addr),
            0xc000...0xdfff => self.wram[(addr - 0xc000) as usize],
            0xe000...0xfdff => self.wram[(addr - 0xe000) as usize],
            MEM_LCD_OAM_START...MEM_LCD_OAM_END => self.lcd.read(addr),
            0xff10...0xff27 => self.sound.read(addr),
            MEM_LCD_IO_START...MEM_LCD_IO_END => self.lcd.read(addr),
            0xff00...0xff0f | 0xff28...0xff7f | 0xffff => self.io.read(addr),
            0xff80...0xfffe => self.hram[(addr - 0xff80) as usize],
            _ => {
                trace!("Reading unmapped {:x}, just returning 0xff", addr);
                0xff
            }
        };
        value
    }
    pub fn read16(&self, addr: u16) -> u16 {
        self.read(addr) as u16 | (self.read(addr + 1) as u16) << 8
    }
    pub fn write16(&mut self, addr: u16, value: u16) {
        self.write(addr, value as u8);
        self.write(addr + 1, (value >> 8) as u8);
    }
    pub fn write(&mut self, addr: u16, value: u8) {
        trace!("Writing {:02x} to {:04x}", value, addr);
        match addr {
            MEM_LCD_IO_DMA => {
                // TODO Refactor stuff in IoPorts to Bus
                // TODO This should not be needed before sprites are implemented
                let src_addr = (value as u16) << 8;
                let dst_addr = 0xfe00;
                for i in 0x00..0x9f {
                    let d = self.read(src_addr + i);
                    self.write(dst_addr + i, d);
                }
            }
            MEM_CARTRIDGE_ROM_START...MEM_CARTRIDGE_ROM_END =>
                self.cartridge.write(addr, value),
            MEM_LCD_VRAM_START...MEM_LCD_VRAM_END => self.lcd.write(addr, value),
            MEM_CARTRIDGE_RAM_START...MEM_CARTRIDGE_RAM_END =>
                self.cartridge.write(addr, value),
            0xc000...0xdfff => self.wram[(addr - 0xc000) as usize] = value,
            0xe000...0xfdff => self.wram[(addr - 0xe000) as usize] = value,
            MEM_LCD_OAM_START...MEM_LCD_OAM_END => self.lcd.write(addr, value),
            0xff10...0xff27 => self.sound.write(addr, value),
            MEM_LCD_IO_START...MEM_LCD_IO_END => self.lcd.write(addr, value),
            0xff00...0xff0f | 0xff28...0xff7f | 0xffff => self.io.write(addr, value),
            0xff80...0xfffe => self.hram[(addr - 0xff80) as usize] = value,
            _ => trace!("NOT MAPPED FOR WRITE {:x} (value 0b{:05b})", addr, value),
        }
    }
}
<commit_msg>Make JOYP return f when no key set is active<commit_after>
use super::cartridge::Cartridge;
use super::sound::Sound;
use super::lcd::Lcd;
use super::constants::*;

use num::FromPrimitive;
use std::io;
use std::collections::VecDeque;

use std::fs::File;
use std::io::Write;

#[derive(Debug,Clone,Serialize,Deserialize)]
pub struct Bus {
    pub cartridge: Cartridge,
    // TODO: Expose in better way
    pub lcd: Lcd,
    pub sound: Sound,
    wram: Vec<u8>,
    hram: Vec<u8>,
    pub io: IoPorts,
}

enum_from_primitive! {
#[derive(Debug,PartialEq)]
enum IoAddress {
    Joypad = 0xff00,
    Sb = 0xff01,
    Sc = 0xff02,
    Div = 0xff04,
    Tima = 0xff05,
    Tma = 0xff06,
    Tac = 0xff07,
    If = 0xff0f,
    Ie = 0xffff
}
}

#[derive(Debug,Clone,Serialize,Deserialize)]
pub struct Timers {
    div: u8,
    tima: u8,
    tma: u8,
    tac: u8,

    div_counter: isize,
    tima_counter: isize,
    tima_running: bool,
}

impl Timers {
    fn new() -> Timers {
        let mut timers = Timers {
            div: 0,
            tima: 0,
            tma: 0,
            tac: 0,
            div_counter: 0,
            tima_counter: 0,
            tima_running: false,
        };
        timers.write_tac(0);
        timers
    }

    pub fn tick(&mut self, cycles: usize) -> u8 {
        let mut interrupt = 0u8;

        if cycles > 12 {
            interrupt |= self.tick(12);
            interrupt |= self.tick(cycles - 12);
            return interrupt;
        }

        self.div_counter -= cycles as isize;
        if self.div_counter <= 0 {
            self.div_counter += (CPU_FREQ / 16384) as isize;
            self.div = self.div.wrapping_add(1);
        }

        if self.tima_running {
            self.tima_counter -= cycles as isize;
            if self.tima_counter <= 0 {
                self.tima_counter += (CPU_FREQ / self.get_tac_freq()) as isize;
                self.tima = self.tima.wrapping_add(1);
                if self.tima == 0 {
                    interrupt |= INT_MASK_TIMER;
                    self.tima = self.tma;
                }
            }
        }
        interrupt
    }

    fn get_tac_freq(&self) -> usize {
        match self.tac & 0x03 {
            0b00 => 4096,
            0b01 => 262144,
            0b10 => 65536,
            0b11 => 16384,
            _ => unreachable!(),
        }
    }
    fn write_div(&mut self) {
        self.div = 0;
        self.div_counter = 0;
    }
    fn write_tima(&mut self, value: u8) {
        self.tima = value;
        // self.tima_counter = (CPU_FREQ / self.get_tac_freq()) as isize - 4;
    }
    fn write_tma(&mut self, value: u8) {
        self.tma = value;
    }
    fn write_tac(&mut self, value: u8) {
        self.tac = value & 0x07;
        self.tima_running = (self.tac & 0x04) != 0;
        trace!("Setting tima freq to {}", self.get_tac_freq());
    }
}

#[derive(Debug,Clone,Serialize,Deserialize)]
pub struct IoPorts {
    joypad: u8,
    serial_data: u8,
    serial_transfer_control: u8,
    pub timers: Timers,

    // TODO expose through other means
    pub interrupt_enable: u8,
    pub interrupt_flags: u8,

    pub joypad_all_buttons: u8,

    pub serial_out: VecDeque<u8>,
}

impl IoPorts {
    fn new() -> IoPorts {
        IoPorts {
            joypad: 0xff,
            serial_data: 0,
            serial_transfer_control: 0,
            timers: Timers::new(),
            interrupt_enable: 0,
            interrupt_flags: 0,
            joypad_all_buttons: 0xff,
            serial_out: VecDeque::new()
        }
    }

    fn write(&mut self, addr: u16, value: u8) {
        match IoAddress::from_u16(addr) {
            Some(x) => {
                trace!("Writing 0x{:02X} to {:?} (0x{:04X})", value, x, addr);
                match x {
                    IoAddress::Joypad => {
                        self.joypad = value | !0x30;
                    }
                    IoAddress::Sb => self.serial_data = value,
                    IoAddress::Sc => {
                        if value & 0x80 == 0x80 {
                            self.serial_out.push_back(self.serial_data);
                        }
                    }
                    IoAddress::Div => self.timers.write_div(),
                    IoAddress::Tima => self.timers.write_tima(value),
                    IoAddress::Tma => self.timers.write_tma(value),
                    IoAddress::Tac => self.timers.write_tac(value),
                    IoAddress::Ie => self.interrupt_enable = value & 0x1f,
                    IoAddress::If => self.interrupt_flags = value & 0x1f,
                }
            }
            None => {
                debug!("WRITE 0x{:02X} to IOPORT 0x{:04X} not recognized (ignoring)",
                       value,
                       addr);
            }
        }
    }

    fn read(&self, addr: u16) -> u8 {
        match IoAddress::from_u16(addr) {
            Some(x) => {
                let value = match x {
                    IoAddress::Sb => self.serial_data,
                    IoAddress::Joypad => {
                        (if self.joypad & 0x10 == 0 {
                            self.joypad_all_buttons & 0xf
                        } else {
                            0xf
                        } &
                        if self.joypad & 0x20 == 0 {
                            self.joypad_all_buttons >> 4
                        } else {
                            0xf
                        }) | (self.joypad & 0xf0)
                    }
                    IoAddress::Sc => self.serial_transfer_control,
                    IoAddress::Div => self.timers.div,
                    IoAddress::Tima => self.timers.tima,
                    IoAddress::Tma => self.timers.tma,
                    IoAddress::Tac => self.timers.tac,
                    IoAddress::Ie => self.interrupt_enable,
                    IoAddress::If => self.interrupt_flags,
                    // _ => panic!("IOPORT {:02X} NOT MAPPED FOR READING", addr)
                };
                value
            }
            None => {
                warn!("READ from IOPORT 0x{:04X} not recognized (ignoring)", addr);
                0
            }
        }
    }
}

impl Bus {
    pub fn new(cartridge: Cartridge) -> Bus {
        Bus {
            hram: vec![0u8; 0x7f],
            wram: vec![0u8; 0x2000],
            lcd: Lcd::new(),
            sound: Sound::new(),
            cartridge: cartridge,
            io: IoPorts::new(),
        }
    }

    pub fn dequeue_samples(&mut self) -> Vec<(i8, i8)> {
        self.sound.dump_audio()
    }

    pub fn dump_wram(&mut self) -> io::Result<()> {
        let mut f = try!(File::create("wram.dump"));
        try!(f.write_all(&self.wram));
        Ok(())
    }

    pub fn read(&self, addr: u16) -> u8 {
        let value = match addr {
            MEM_LCD_IO_DMA => 0xff,
            MEM_CARTRIDGE_ROM_START...MEM_CARTRIDGE_ROM_END =>
                self.cartridge.read(addr),
            MEM_LCD_VRAM_START...MEM_LCD_VRAM_END => self.lcd.read(addr),
            MEM_CARTRIDGE_RAM_START...MEM_CARTRIDGE_RAM_END =>
                self.cartridge.read(addr),
            0xc000...0xdfff => self.wram[(addr - 0xc000) as usize],
            0xe000...0xfdff => self.wram[(addr - 0xe000) as usize],
            MEM_LCD_OAM_START...MEM_LCD_OAM_END => self.lcd.read(addr),
            0xff10...0xff27 => self.sound.read(addr),
            MEM_LCD_IO_START...MEM_LCD_IO_END => self.lcd.read(addr),
            0xff00...0xff0f | 0xff28...0xff7f | 0xffff => self.io.read(addr),
            0xff80...0xfffe => self.hram[(addr - 0xff80) as usize],
            _ => {
                trace!("Reading unmapped {:x}, just returning 0xff", addr);
                0xff
            }
        };
        value
    }
    pub fn read16(&self, addr: u16) -> u16 {
        self.read(addr) as u16 | (self.read(addr + 1) as u16) << 8
    }
    pub fn write16(&mut self, addr: u16, value: u16) {
        self.write(addr, value as u8);
        self.write(addr + 1, (value >> 8) as u8);
    }
    pub fn write(&mut self, addr: u16, value: u8) {
        trace!("Writing {:02x} to {:04x}", value, addr);
        match addr {
            MEM_LCD_IO_DMA => {
                // TODO Refactor stuff in IoPorts to Bus
                // TODO This should not be needed before sprites are implemented
                let src_addr = (value as u16) << 8;
                let dst_addr = 0xfe00;
                for i in 0x00..0x9f {
                    let d = self.read(src_addr + i);
                    self.write(dst_addr + i, d);
                }
            }
            MEM_CARTRIDGE_ROM_START...MEM_CARTRIDGE_ROM_END =>
                self.cartridge.write(addr, value),
            MEM_LCD_VRAM_START...MEM_LCD_VRAM_END => self.lcd.write(addr, value),
            MEM_CARTRIDGE_RAM_START...MEM_CARTRIDGE_RAM_END =>
                self.cartridge.write(addr, value),
            0xc000...0xdfff => self.wram[(addr - 0xc000) as usize] = value,
            0xe000...0xfdff => self.wram[(addr - 0xe000) as usize] = value,
            MEM_LCD_OAM_START...MEM_LCD_OAM_END => self.lcd.write(addr, value),
            0xff10...0xff27 => self.sound.write(addr, value),
            MEM_LCD_IO_START...MEM_LCD_IO_END => self.lcd.write(addr, value),
            0xff00...0xff0f | 0xff28...0xff7f | 0xffff => self.io.write(addr, value),
            0xff80...0xfffe => self.hram[(addr - 0xff80) as usize] = value,
            _ => trace!("NOT MAPPED FOR WRITE {:x} (value 0b{:05b})", addr, value),
        }
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

// # Mutable Iterators

// ## Part 1

// To start out our introduction to constructing mutable iterators, we will use
// a simple data structure consisting nothing but a vector of integers.  But
// these are our integers, so they are special, which is why we will now call
// them out `SpecialIntegers` type.

struct SpecialIntegers(Vec<u32>);

// To implement an iterator, we essentially need to tell Rust two things:
//   a. What kind of elements will we be iterating over.  When iterating
//      over our structure, we wil want our special integers (which are `u32`).
//   b. What is the next element when we are iterating.
//
// We will therefore have the responsibility of keeping track of where we are at
// while iterating.  We will do this by constructing what is
// oftern called an "iterator interface".  To keep track of our iteration, we will
// need our `SpecialIntegers` data structure and a cursor to keep track of where
// we are.

struct SpecialIntegersIterator<'a> {
    data: &'a mut SpecialIntegers,
    cursor: usize,
}

// We now need to tell rust how to get the next element in our iterator, which
// we accomplish by implementing the `Iterator` trait on our interator inteface.
// There is a problem that we will run into however.  Our iterator interface
// has a mutable borrow of our `SpecialIntegers` data structure.  So while we
// are holding this mutable borrow, we aren't technically allowed to give a mutable
// reference to elements in our list.  We therefore will be required to use unsafe.
// But before we do so, we should stop and think for a second: is what I am doing
// actually safe?

impl<'a> Iterator for &'a mut SpecialIntegersIterator<'a> {
    // The type of object we will be iterating over
    type Item = &'a mut u32;
    fn next(&mut self) -> Option<&'a mut u32> {
        unimplemented!();
    }
}

// However, before we will be able to use this iterator interface, unless you
// are planning on creating a brand new `SpecialIntegersIterator` structure
// each you want to use an iterator, we need to tell Rust how to make this structure
// for wehenever we need an iterator.  We do this by implementing the `IntoIterator`
// trait.  Which, less, tells rust how to make an iterator interface by calling
// `iter_mut`.

impl<'a> IntoIterator for &'a mut SpecialIntegers {
    type Item =  &'a mut u32;
    type IntoIter = SpecialIntegers;

    fn into_iter(&mut self) -> &'a mut SpecialIntegersIterator<'a> {
        unimplemented!();
    }
}

// ## Part 2

// We will implement a simple tree that could, say, represent a simple DOM
// structure.  You may notice that we don't actually allow for text in our
// simple representation, but this isn't important here, what we really want
// to investigate is how we would implement a mutable iterator using our custom
// data structure.  Our DOM structure will only allow for four different types
// of nodes: Header, Paragraph, Text, and Images.

enum NodeType {
    Header,
    Paragraph,
    Text,
    Image,
}

// Each node with have a list of `children` nodes and a tag for the respective
// DOM element type.

struct DomNode {
    children: Vec<DomNode>,
    node_type: NodeType
}

// To implement an iterator, we essentially just need to tell Rust two things:
//   a. What kind of elements will we be iteratorating over?  In this example
//      we will be iteratorating over the nodes of our Dom, so we will want
//      to iterate over `NodeType`s.
//   b. What is the next element?
//
// We will therefore have the responsibility of keeping track of where we are at
// while iteratorating over our DOM.  We will do this by constructing what is
// oftern called an "iterator interface".  We make one like this:

struct DomMutIterator<'a> {
    data: &'a mut DomNode,
    cursor: usize,
}

// We provide answers for the questions posted above for Rust by implementing an
// `Iterator` for our iterator interface.

impl<'a> Iterator for DomMutIterator<'a> {
    type Item = &'a mut NodeType;
    fn next(&mut self) -> Option<&'a mut NodeType> {

        // This part will require some thought...

        unimplemented!();
    }
}

fn main() {
}

// Note: Rust implementation of creating a mutable iterator uses a `Range` object which, keeps track of the size of the vector.
// this allows for unchecked boundes [see here](https://doc.rust-lang.org/src/collections/up/src/libcollections/btree/map.rs.html#920).
// we should leave this as an exercise to the reader and show them the source to reference. They use the `Range` object to call the
// recurse in the vector [see here](https://doc.rust-lang.org/src/collections/up/src/libcollections/btree/map.rs.html#920).  Perhaps
// this might be a good idea for us as well.
<commit_msg>fix easy example<commit_after>#![allow(dead_code)]

// # Mutable Iterators

// ## Part 1

// To start out our introduction to constructing mutable iterators, we will use
// a simple data structure consisting nothing but a vector of integers.  But
// these are our integers, so they are special, which is why we will now call
// them out `SpecialIntegers` type.

struct SpecialIntegers(Vec<u32>);

// To implement an iterator, we essentially need to tell Rust two things:
//   a. What kind of elements will we be iterating over.  When iterating
//      over our structure, we wil want our special integers (which are `u32`).
//   b. What is the next element when we are iterating.
//
// We will therefore have the responsibility of keeping track of where we are at
// while iterating.  We will do this by constructing what is
// oftern called an "iterator interface".  To keep track of our iteration, we will
// need our `SpecialIntegers` data structure and a cursor to keep track of where
// we are.

struct SpecialIntegersIterator<'a> {
    data: &'a mut SpecialIntegers,
    cursor: usize,
}

// We now need to tell rust how to get the next element in our iterator, which
// we accomplish by implementing the `Iterator` trait on our interator inteface.
// There is a problem that we will run into however.  Our iterator interface
// has a mutable borrow of our `SpecialIntegers` data structure.  So while we
// are holding this mutable borrow, we aren't technically allowed to give a mutable
// reference to elements in our list.  We therefore will be required to use unsafe.
// But before we do so, we should stop and think for a second: is what I am doing
// actually safe?

impl<'a> Iterator for SpecialIntegersIterator<'a> {
    // The type of object we will be iterating over
    type Item = &'a mut u32;
    fn next(&mut self) -> Option<&'a mut u32> {
        unimplemented!();
    }
}

// However, before we will be able to use this iterator interface, unless you
// are planning on creating a brand new `SpecialIntegersIterator` structure
// each you want to use an iterator, we need to tell Rust how to make this structure
// for wehenever we need an iterator.  We do this by implementing the `IntoIterator`
// trait.  Which, less, tells rust how to make an iterator interface by calling
// `iter_mut`.

impl<'a> IntoIterator for &'a mut SpecialIntegers {
    type Item = &'a mut u32;
    type IntoIter = SpecialIntegersIterator<'a>;

    fn into_iter(self) -> SpecialIntegersIterator<'a> {
        unimplemented!();
    }
}

// ## Part 2

// We will implement a simple tree that could, say, represent a simple DOM
// structure.  You may notice that we don't actually allow for text in our
// simple representation, but this isn't important here, what we really want
// to investigate is how we would implement a mutable iterator using our custom
// data structure.  Our DOM structure will only allow for four different types
// of nodes: Header, Paragraph, Text, and Images.

enum NodeType {
    Header,
    Paragraph,
    Text,
    Image,
}

// Each node with have a list of `children` nodes and a tag for the respective
// DOM element type.

struct DomNode {
    children: Vec<DomNode>,
    node_type: NodeType
}

// To implement an iterator, we essentially just need to tell Rust two things:
//   a. What kind of elements will we be iteratorating over?  In this example
//      we will be iteratorating over the nodes of our Dom, so we will want
//      to iterate over `NodeType`s.
//   b. What is the next element?
//
// We will therefore have the responsibility of keeping track of where we are at
// while iteratorating over our DOM.  We will do this by constructing what is
// oftern called an "iterator interface".  We make one like this:

struct DomMutIterator<'a> {
    data: &'a mut DomNode,
    cursor: usize,
}

// We provide answers for the questions posted above for Rust by implementing an
// `Iterator` for our iterator interface.

impl<'a> Iterator for DomMutIterator<'a> {
    type Item = &'a mut NodeType;
    fn next(&mut self) -> Option<&'a mut NodeType> {

        // This part will require some thought...

        unimplemented!();
    }
}

fn main() {
}

// Note: Rust implementation of creating a mutable iterator uses a `Range` object which, keeps track of the size of the vector.
// this allows for unchecked boundes [see here](https://doc.rust-lang.org/src/collections/up/src/libcollections/btree/map.rs.html#920).
// we should leave this as an exercise to the reader and show them the source to reference. They use the `Range` object to call the
// recurse in the vector [see here](https://doc.rust-lang.org/src/collections/up/src/libcollections/btree/map.rs.html#920).  Perhaps
// this might be a good idea for us as well.
<|endoftext|>


<commit_before>struct RelationArg<'a, T> {
    args: Vec<T>,
    value: Option<&'a [u8]>,
    modifier: RelationModifier
}

enum RelationModifier {
    All,
    Any,
    None
}

enum RelationKind<'a, T> {
    Present(RelationArg<'a, T>),
    NotPresent(RelationArg<'a, T>),
    None
}

struct Relations<'a, T>(Vec<RelationKind<'a, T>>);

impl<'a, T> Relation<'a, T> where T: Eq {
    fn is_sat(&self, &[T]) -> bool {
        for r in self.
    }
}<commit_msg>Remove unneeded file<commit_after><|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use toml::Value;

use store::Result;
use error::{StoreError as SE, StoreErrorKind as SEK};
use libimagerror::into::IntoError;

pub trait TomlValueExt {
    fn insert_with_sep(&mut self, spec: &str, sep: char, v: Value) -> Result<bool>;
    fn set_with_sep(&mut self, spec: &str, sep: char, v: Value) -> Result<Option<Value>>;
    fn read_with_sep(&self, spec: &str, splitchr: char) -> Result<Option<Value>>;
    fn delete_with_sep(&mut self, spec: &str, splitchr: char) -> Result<Option<Value>>;

    #[inline]
    fn insert(&mut self, spec: &str, v: Value) -> Result<bool> {
        self.insert_with_sep(spec, '.', v)
    }

    #[inline]
    fn set(&mut self, spec: &str, v: Value) -> Result<Option<Value>> {
        self.set_with_sep(spec, '.', v)
    }

    #[inline]
    fn read(&self, spec: &str) -> Result<Option<Value>> {
        self.read_with_sep(spec, '.')
    }

    #[inline]
    fn delete(&mut self, spec: &str) -> Result<Option<Value>> {
        self.delete_with_sep(spec, '.')
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
enum Token {
    Key(String),
    Index(usize),
}

impl TomlValueExt for Value {
    /**
     * Insert a header field by a string-spec
     *
     * ```ignore
     *  insert("something.in.a.field", Boolean(true));
     * ```
     *
     * If an array field was accessed which is _out of bounds_ of the array available, the element
     * is appended to the array.
     *
     * Inserts a Boolean in the section "something" -> "in" -> "a" -> "field"
     * A JSON equivalent would be
     *
     *  {
     *      something: {
     *          in: {
     *              a: {
     *                  field: true
     *              }
     *          }
     *      }
     *  }
     *
     * Returns true if header field was set, false if there is already a value
     */
    fn insert_with_sep(&mut self, spec: &str, sep: char, v: Value) -> Result<bool> {
        let tokens = match tokenize(spec, sep) {
            Err(e) => return Err(e),
            Ok(t)  => t
        };

        let destination = match tokens.iter().last() {
            None    => return Err(SE::new(SEK::HeaderPathSyntaxError, None)),
            Some(d) => d,
        };

        let path_to_dest = tokens[..(tokens.len() - 1)].into(); // N - 1 tokens

        // walk N-1 tokens
        let value = match walk_header(self, path_to_dest) {
            Err(e) => return Err(e),
            Ok(v)  => v
        };

        // There is already an value at this place
        if extract(value, destination).is_ok() {
            return Ok(false);
        }

        match *destination {
            // if the destination shall be an map key
            Token::Key(ref s) => match *value {
                /*
                 * Put it in there if we have a map
                 */
                Value::Table(ref mut t) => { t.insert(s.clone(), v); },

                /*
                 * Fail if there is no map here
                 */
                _ => return Err(SEK::HeaderPathTypeFailure.into_error()),
            },

            // if the destination shall be an array
            Token::Index(i) => match *value {

                /*
                 * Put it in there if we have an array
                 */
                Value::Array(ref mut a) => {
                    a.push(v); // push to the end of the array

                    // if the index is inside the array, we swap-remove the element at this
                    // index
                    if a.len() < i {
                        a.swap_remove(i);
                    }
                },

                /*
                 * Fail if there is no array here
                 */
                _ => return Err(SEK::HeaderPathTypeFailure.into_error()),
            },
        }

        Ok(true)
    }

    /**
     * Set a header field by a string-spec
     *
     * ```ignore
     *  set("something.in.a.field", Boolean(true));
     * ```
     *
     * Sets a Boolean in the section "something" -> "in" -> "a" -> "field"
     * A JSON equivalent would be
     *
     *  {
     *      something: {
     *          in: {
     *              a: {
     *                  field: true
     *              }
     *          }
     *      }
     *  }
     *
     * If there is already a value at this place, this value will be overridden and the old value
     * will be returned
     */
    fn set_with_sep(&mut self, spec: &str, sep: char, v: Value) -> Result<Option<Value>> {
        let tokens = match tokenize(spec, sep) {
            Err(e) => return Err(e),
            Ok(t)  => t,
        };
        debug!("tokens = {:?}", tokens);

        let destination = match tokens.iter().last() {
            None    => return Err(SEK::HeaderPathSyntaxError.into_error()),
            Some(d) => d
        };
        debug!("destination = {:?}", destination);

        let path_to_dest = tokens[..(tokens.len() - 1)].into(); // N - 1 tokens
        // walk N-1 tokens
        let value = match walk_header(self, path_to_dest) {
            Err(e) => return Err(e),
            Ok(v)  => v
        };
        debug!("walked value = {:?}", value);

        match *destination {
            // if the destination shall be an map key->value
            Token::Key(ref s) => match *value {
                /*
                 * Put it in there if we have a map
                 */
                Value::Table(ref mut t) => {
                    debug!("Matched Key->Table");
                    return Ok(t.insert(s.clone(), v));
                }

                /*
                 * Fail if there is no map here
                 */
                _ => {
                    debug!("Matched Key->NON-Table");
                    return Err(SEK::HeaderPathTypeFailure.into_error());
                }
            },

            // if the destination shall be an array
            Token::Index(i) => match *value {

                /*
                 * Put it in there if we have an array
                 */
                Value::Array(ref mut a) => {
                    debug!("Matched Index->Array");
                    a.push(v); // push to the end of the array

                    // if the index is inside the array, we swap-remove the element at this
                    // index
                    if a.len() > i {
                        debug!("Swap-Removing in Array {:?}[{:?}] <- {:?}", a, i, a[a.len()-1]);
                        return Ok(Some(a.swap_remove(i)));
                    }

                    debug!("Appended");
                    return Ok(None);
                },

                /*
                 * Fail if there is no array here
                 */
                _ => {
                    debug!("Matched Index->NON-Array");
                    return Err(SEK::HeaderPathTypeFailure.into_error());
                },
            },
        }

        Ok(None)
    }

    /**
     * Read a header field by a string-spec
     *
     * ```ignore
     *  let value = read("something.in.a.field");
     * ```
     *
     * Reads a Value in the section "something" -> "in" -> "a" -> "field"
     * A JSON equivalent would be
     *
     *  {
     *      something: {
     *          in: {
     *              a: {
     *                  field: true
     *              }
     *          }
     *      }
     *  }
     *
     * If there is no a value at this place, None will be returned. This also holds true for Arrays
     * which are accessed at an index which is not yet there, even if the accessed index is much
     * larger than the array length.
     */
    fn read_with_sep(&self, spec: &str, splitchr: char) -> Result<Option<Value>> {
        let tokens = match tokenize(spec, splitchr) {
            Err(e) => return Err(e),
            Ok(t) => t,
        };

        let mut header_clone = self.clone(); // we clone as READing is simpler this way
        // walk N-1 tokens
        match walk_header(&mut header_clone, tokens) {
            Err(e) => match e.err_type() {
                // We cannot find the header key, as there is no path to it
                SEK::HeaderKeyNotFound => Ok(None),
                _ => Err(e),
            },
            Ok(v) => Ok(Some(v.clone())),
        }
    }

    fn delete_with_sep(&mut self, spec: &str, splitchr: char) -> Result<Option<Value>> {
        let tokens = match tokenize(spec, splitchr) {
            Err(e) => return Err(e),
            Ok(t)  => t
        };

        let destination = match tokens.iter().last() {
            None    => return Err(SEK::HeaderPathSyntaxError.into_error()),
            Some(d) => d
        };
        debug!("destination = {:?}", destination);

        let path_to_dest = tokens[..(tokens.len() - 1)].into(); // N - 1 tokens
        // walk N-1 tokens
        let mut value = match walk_header(self, path_to_dest) {
            Err(e) => return Err(e),
            Ok(v)  => v
        };
        debug!("walked value = {:?}", value);

        match *destination {
            // if the destination shall be an map key->value
            Token::Key(ref s) => match *value {
                Value::Table(ref mut t) => {
                    debug!("Matched Key->Table, removing {:?}", s);
                    return Ok(t.remove(s));
                },
                _ => {
                    debug!("Matched Key->NON-Table");
                    return Err(SEK::HeaderPathTypeFailure.into_error());
                }
            },

            // if the destination shall be an array
            Token::Index(i) => match *value {

                // if the index is inside the array, we swap-remove the element at this
                // index
                Value::Array(ref mut a) => if a.len() > i {
                    debug!("Removing in Array {:?}[{:?}]", a, i);
                    return Ok(Some(a.remove(i)));
                } else {
                    return Ok(None);
                },
                _ => {
                    debug!("Matched Index->NON-Array");
                    return Err(SEK::HeaderPathTypeFailure.into_error());
                },
            },
        }

        Ok(None)
    }

}

fn tokenize(spec: &str, splitchr: char) -> Result<Vec<Token>> {
    use std::str::FromStr;

    spec.split(splitchr)
        .map(|s| usize::from_str(s).map(Token::Index).or_else(|_| Ok(Token::Key(String::from(s)))))
        .collect()
}

fn walk_header(v: &mut Value, tokens: Vec<Token>) -> Result<&mut Value> {
    use std::vec::IntoIter;

    fn walk_iter<'a>(v: Result<&'a mut Value>, i: &mut IntoIter<Token>) -> Result<&'a mut Value> {
        let next = i.next();
        v.and_then(move |value| if let Some(token) = next {
            walk_iter(extract(value, &token), i)
        } else {
            Ok(value)
        })
    }

    walk_iter(Ok(v), &mut tokens.into_iter())
}

fn extract_from_table<'a>(v: &'a mut Value, s: &str) -> Result<&'a mut Value> {
    match *v {
        Value::Table(ref mut t) => t.get_mut(&s[..]).ok_or(SEK::HeaderKeyNotFound.into_error()),
        _ => Err(SEK::HeaderPathTypeFailure.into_error()),
    }
}

fn extract_from_array(v: &mut Value, i: usize) -> Result<&mut Value> {
    match *v {
        Value::Array(ref mut a) => if a.len() < i {
            Err(SEK::HeaderKeyNotFound.into_error())
        } else {
            Ok(&mut a[i])
        },
        _ => Err(SEK::HeaderPathTypeFailure.into_error()),
    }
}

fn extract<'a>(v: &'a mut Value, token: &Token) -> Result<&'a mut Value> {
    match *token {
        Token::Key(ref s)  => extract_from_table(v, s),
        Token::Index(i)    => extract_from_array(v, i),
    }
}

<commit_msg>Refactor to use try!() instead of match{}ing<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use toml::Value;

use store::Result;
use error::{StoreError as SE, StoreErrorKind as SEK};
use libimagerror::into::IntoError;

pub trait TomlValueExt {
    fn insert_with_sep(&mut self, spec: &str, sep: char, v: Value) -> Result<bool>;
    fn set_with_sep(&mut self, spec: &str, sep: char, v: Value) -> Result<Option<Value>>;
    fn read_with_sep(&self, spec: &str, splitchr: char) -> Result<Option<Value>>;
    fn delete_with_sep(&mut self, spec: &str, splitchr: char) -> Result<Option<Value>>;

    #[inline]
    fn insert(&mut self, spec: &str, v: Value) -> Result<bool> {
        self.insert_with_sep(spec, '.', v)
    }

    #[inline]
    fn set(&mut self, spec: &str, v: Value) -> Result<Option<Value>> {
        self.set_with_sep(spec, '.', v)
    }

    #[inline]
    fn read(&self, spec: &str) -> Result<Option<Value>> {
        self.read_with_sep(spec, '.')
    }

    #[inline]
    fn delete(&mut self, spec: &str) -> Result<Option<Value>> {
        self.delete_with_sep(spec, '.')
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
enum Token {
    Key(String),
    Index(usize),
}

impl TomlValueExt for Value {
    /**
     * Insert a header field by a string-spec
     *
     * ```ignore
     *  insert("something.in.a.field", Boolean(true));
     * ```
     *
     * If an array field was accessed which is _out of bounds_ of the array available, the element
     * is appended to the array.
     *
     * Inserts a Boolean in the section "something" -> "in" -> "a" -> "field"
     * A JSON equivalent would be
     *
     *  {
     *      something: {
     *          in: {
     *              a: {
     *                  field: true
     *              }
     *          }
     *      }
     *  }
     *
     * Returns true if header field was set, false if there is already a value
     */
    fn insert_with_sep(&mut self, spec: &str, sep: char, v: Value) -> Result<bool> {
        let tokens      = try!(tokenize(spec, sep));
        let destination = try!(tokens.iter().last().ok_or(SEK::HeaderPathSyntaxError.into_error))

        let path_to_dest = tokens[..(tokens.len() - 1)].into(); // N - 1 tokens

        // walk N-1 tokens
        let value = try!(walk_header(self, path_to_dest));

        // There is already an value at this place
        if extract(value, destination).is_ok() {
            return Ok(false);
        }

        match *destination {
            // if the destination shall be an map key
            Token::Key(ref s) => match *value {
                /*
                 * Put it in there if we have a map
                 */
                Value::Table(ref mut t) => { t.insert(s.clone(), v); },

                /*
                 * Fail if there is no map here
                 */
                _ => return Err(SEK::HeaderPathTypeFailure.into_error()),
            },

            // if the destination shall be an array
            Token::Index(i) => match *value {

                /*
                 * Put it in there if we have an array
                 */
                Value::Array(ref mut a) => {
                    a.push(v); // push to the end of the array

                    // if the index is inside the array, we swap-remove the element at this
                    // index
                    if a.len() < i {
                        a.swap_remove(i);
                    }
                },

                /*
                 * Fail if there is no array here
                 */
                _ => return Err(SEK::HeaderPathTypeFailure.into_error()),
            },
        }

        Ok(true)
    }

    /**
     * Set a header field by a string-spec
     *
     * ```ignore
     *  set("something.in.a.field", Boolean(true));
     * ```
     *
     * Sets a Boolean in the section "something" -> "in" -> "a" -> "field"
     * A JSON equivalent would be
     *
     *  {
     *      something: {
     *          in: {
     *              a: {
     *                  field: true
     *              }
     *          }
     *      }
     *  }
     *
     * If there is already a value at this place, this value will be overridden and the old value
     * will be returned
     */
    fn set_with_sep(&mut self, spec: &str, sep: char, v: Value) -> Result<Option<Value>> {
        let tokens = try!(tokenize(spec, sep));
        debug!("tokens = {:?}", tokens);

        let destination = try!(tokens.iter().last().ok_or(SEK::HeaderPathSyntaxError.into_error()))
        debug!("destination = {:?}", destination);

        let path_to_dest = tokens[..(tokens.len() - 1)].into(); // N - 1 tokens
        // walk N-1 tokens
        let value = try!(walk_header(self, path_to_dest));
        debug!("walked value = {:?}", value);

        match *destination {
            // if the destination shall be an map key->value
            Token::Key(ref s) => match *value {
                /*
                 * Put it in there if we have a map
                 */
                Value::Table(ref mut t) => {
                    debug!("Matched Key->Table");
                    return Ok(t.insert(s.clone(), v));
                }

                /*
                 * Fail if there is no map here
                 */
                _ => {
                    debug!("Matched Key->NON-Table");
                    return Err(SEK::HeaderPathTypeFailure.into_error());
                }
            },

            // if the destination shall be an array
            Token::Index(i) => match *value {

                /*
                 * Put it in there if we have an array
                 */
                Value::Array(ref mut a) => {
                    debug!("Matched Index->Array");
                    a.push(v); // push to the end of the array

                    // if the index is inside the array, we swap-remove the element at this
                    // index
                    if a.len() > i {
                        debug!("Swap-Removing in Array {:?}[{:?}] <- {:?}", a, i, a[a.len()-1]);
                        return Ok(Some(a.swap_remove(i)));
                    }

                    debug!("Appended");
                    return Ok(None);
                },

                /*
                 * Fail if there is no array here
                 */
                _ => {
                    debug!("Matched Index->NON-Array");
                    return Err(SEK::HeaderPathTypeFailure.into_error());
                },
            },
        }

        Ok(None)
    }

    /**
     * Read a header field by a string-spec
     *
     * ```ignore
     *  let value = read("something.in.a.field");
     * ```
     *
     * Reads a Value in the section "something" -> "in" -> "a" -> "field"
     * A JSON equivalent would be
     *
     *  {
     *      something: {
     *          in: {
     *              a: {
     *                  field: true
     *              }
     *          }
     *      }
     *  }
     *
     * If there is no a value at this place, None will be returned. This also holds true for Arrays
     * which are accessed at an index which is not yet there, even if the accessed index is much
     * larger than the array length.
     */
    fn read_with_sep(&self, spec: &str, splitchr: char) -> Result<Option<Value>> {
        let tokens = try!(tokenize(spec, splitchr));

        let mut header_clone = self.clone(); // we clone as READing is simpler this way
        // walk N-1 tokens
        match walk_header(&mut header_clone, tokens) {
            Err(e) => match e.err_type() {
                // We cannot find the header key, as there is no path to it
                SEK::HeaderKeyNotFound => Ok(None),
                _ => Err(e),
            },
            Ok(v) => Ok(Some(v.clone())),
        }
    }

    fn delete_with_sep(&mut self, spec: &str, splitchr: char) -> Result<Option<Value>> {
        let tokens      = try!(tokenize(spec, splitchr));
        let destination = try!(tokens.iter().last().ok_or(SEK::HeaderPathSyntaxError.into_error()));
        debug!("destination = {:?}", destination);

        let path_to_dest = tokens[..(tokens.len() - 1)].into(); // N - 1 tokens
        // walk N-1 tokens
        let mut value = try!(walk_header(self, path_to_dest));
        debug!("walked value = {:?}", value);

        match *destination {
            // if the destination shall be an map key->value
            Token::Key(ref s) => match *value {
                Value::Table(ref mut t) => {
                    debug!("Matched Key->Table, removing {:?}", s);
                    return Ok(t.remove(s));
                },
                _ => {
                    debug!("Matched Key->NON-Table");
                    return Err(SEK::HeaderPathTypeFailure.into_error());
                }
            },

            // if the destination shall be an array
            Token::Index(i) => match *value {

                // if the index is inside the array, we swap-remove the element at this
                // index
                Value::Array(ref mut a) => if a.len() > i {
                    debug!("Removing in Array {:?}[{:?}]", a, i);
                    return Ok(Some(a.remove(i)));
                } else {
                    return Ok(None);
                },
                _ => {
                    debug!("Matched Index->NON-Array");
                    return Err(SEK::HeaderPathTypeFailure.into_error());
                },
            },
        }

        Ok(None)
    }

}

fn tokenize(spec: &str, splitchr: char) -> Result<Vec<Token>> {
    use std::str::FromStr;

    spec.split(splitchr)
        .map(|s| usize::from_str(s).map(Token::Index).or_else(|_| Ok(Token::Key(String::from(s)))))
        .collect()
}

fn walk_header(v: &mut Value, tokens: Vec<Token>) -> Result<&mut Value> {
    use std::vec::IntoIter;

    fn walk_iter<'a>(v: Result<&'a mut Value>, i: &mut IntoIter<Token>) -> Result<&'a mut Value> {
        let next = i.next();
        v.and_then(move |value| if let Some(token) = next {
            walk_iter(extract(value, &token), i)
        } else {
            Ok(value)
        })
    }

    walk_iter(Ok(v), &mut tokens.into_iter())
}

fn extract_from_table<'a>(v: &'a mut Value, s: &str) -> Result<&'a mut Value> {
    match *v {
        Value::Table(ref mut t) => t.get_mut(&s[..]).ok_or(SEK::HeaderKeyNotFound.into_error()),
        _ => Err(SEK::HeaderPathTypeFailure.into_error()),
    }
}

fn extract_from_array(v: &mut Value, i: usize) -> Result<&mut Value> {
    match *v {
        Value::Array(ref mut a) => if a.len() < i {
            Err(SEK::HeaderKeyNotFound.into_error())
        } else {
            Ok(&mut a[i])
        },
        _ => Err(SEK::HeaderPathTypeFailure.into_error()),
    }
}

fn extract<'a>(v: &'a mut Value, token: &Token) -> Result<&'a mut Value> {
    match *token {
        Token::Key(ref s)  => extract_from_table(v, s),
        Token::Index(i)    => extract_from_array(v, i),
    }
}

<|endoftext|>


<commit_before>use libc::{c_int, c_double};
use std::ffi::CString;
use std::path::Path;
use super::super::geom::Point;
use utils::_string;
use raster::{gdal, Driver};
use raster::driver::_register_drivers;

pub struct Dataset {
    c_dataset: *const (),
}

impl Drop for Dataset {
    fn drop(&mut self) {
        unsafe { gdal::GDALClose(self.c_dataset); }
    }
}

impl Dataset {
    pub fn open(path: &Path) -> Option<Dataset> {
        _register_drivers();
        let filename = path.to_str().unwrap();
        let c_filename = CString::new(filename.as_bytes()).unwrap();
        let c_dataset = unsafe { gdal::GDALOpen(c_filename.as_ptr(), gdal::GA_READONLY) };
        return match c_dataset.is_null() {
            true  => None,
            false => Some(Dataset{c_dataset: c_dataset}),
        };
    }

    pub unsafe fn _with_c_ptr(c_dataset: *const ()) -> Dataset {
        return Dataset{c_dataset: c_dataset};
    }

    pub unsafe fn _c_ptr(&self) -> *const () {
        return self.c_dataset;
    }

    pub fn size(&self) -> (isize, isize) {
        let size_x = unsafe { gdal::GDALGetRasterXSize(self.c_dataset) } as isize;
        let size_y = unsafe { gdal::GDALGetRasterYSize(self.c_dataset) } as isize;
        return (size_x, size_y);
    }

    pub fn driver(&self) -> Driver {
        unsafe {
            let c_driver = gdal::GDALGetDatasetDriver(self.c_dataset);
            return Driver::_with_c_ptr(c_driver);
        };
    }

    pub fn count(&self) -> isize {
        return unsafe { gdal::GDALGetRasterCount(self.c_dataset) } as isize;
    }

    pub fn projection(&self) -> String {
        let rv = unsafe { gdal::GDALGetProjectionRef(self.c_dataset) };
        return _string(rv);
    }

    pub fn set_projection(&self, projection: &str) {
        let c_projection = CString::new(projection.as_bytes()).unwrap();
        unsafe { gdal::GDALSetProjection(self.c_dataset, c_projection.as_ptr()) };
    }

    pub fn set_geo_transform(&self, tr: &[f64]) {
        assert_eq!(tr.len(), 6);
        let rv = unsafe {
            gdal::GDALSetGeoTransform(self.c_dataset, tr.as_ptr())
        } as isize;
        assert!(rv == 0);
    }

    pub fn geo_transform(&self) -> Vec<f64> {
        let mut tr: Vec<c_double> = Vec::with_capacity(6);
        for _ in (0isize..6) { tr.push(0.0); }
        let rv = unsafe {
            gdal::GDALGetGeoTransform(
                self.c_dataset,
                tr.as_mut_ptr()
            )
        } as isize;
        assert!(rv == 0);
        return tr;
    }

    pub fn create_copy(
        &self,
        driver: Driver,
        filename: &str
    ) -> Option<Dataset> {
        use std::ptr::null;
        let c_filename = CString::new(filename.as_bytes()).unwrap();
        let c_dataset = unsafe { gdal::GDALCreateCopy(
                driver._c_ptr(),
                c_filename.as_ptr(),
                self.c_dataset,
                0,
                null(),
                null(),
                null()
            ) };
        return match c_dataset.is_null() {
            true  => None,
            false => Some(Dataset{c_dataset: c_dataset}),
        };
    }

    pub fn read_raster(&self,
        band_index: isize,
        window: Point<isize>,
        window_size: Point<usize>,
        size: Point<usize>
        ) -> ByteBuffer
    {
        let nbytes = size.x * size.y;
        let mut data: Vec<u8> = (0..nbytes).map(|_| 0u8).collect();
        unsafe {
            let c_band = gdal::GDALGetRasterBand(self.c_dataset, band_index as c_int);
            let rv = gdal::GDALRasterIO(
                c_band,
                gdal::GF_READ,
                window.x as c_int,
                window.y as c_int,
                window_size.x as c_int,
                window_size.y as c_int,
                data.as_mut_ptr() as *const (),
                size.x as c_int,
                size.y as c_int,
                gdal::GDT_BYTE,
                0,
                0
            ) as isize;
            assert!(rv == 0);
        };
        return ByteBuffer{
            size: size,
            data: data,
        };
    }

    pub fn write_raster(
        &self,
        band_index: isize,
        window: Point<isize>,
        window_size: Point<usize>,
        buffer: ByteBuffer
    ) {
        assert_eq!(buffer.data.len(), buffer.size.x * buffer.size.y);
        unsafe {
            let c_band = gdal::GDALGetRasterBand(self.c_dataset, band_index as c_int);
            let rv = gdal::GDALRasterIO(
                c_band,
                gdal::GF_WRITE,
                window.x as c_int,
                window.y as c_int,
                window_size.x as c_int,
                window_size.y as c_int,
                buffer.data.as_ptr() as *const (),
                buffer.size.x as c_int,
                buffer.size.y as c_int,
                gdal::GDT_BYTE,
                0,
                0
            ) as isize;
            assert!(rv == 0);
        };
    }
}

pub struct ByteBuffer {
    pub size: Point<usize>,
    pub data: Vec<u8>,
}
<commit_msg>Fix compiler warning<commit_after>use libc::{c_int, c_double};
use std::ffi::CString;
use std::path::Path;
use super::super::geom::Point;
use utils::_string;
use raster::{gdal, Driver};
use raster::driver::_register_drivers;

pub struct Dataset {
    c_dataset: *const (),
}

impl Drop for Dataset {
    fn drop(&mut self) {
        unsafe { gdal::GDALClose(self.c_dataset); }
    }
}

impl Dataset {
    pub fn open(path: &Path) -> Option<Dataset> {
        _register_drivers();
        let filename = path.to_str().unwrap();
        let c_filename = CString::new(filename.as_bytes()).unwrap();
        let c_dataset = unsafe { gdal::GDALOpen(c_filename.as_ptr(), gdal::GA_READONLY) };
        return match c_dataset.is_null() {
            true  => None,
            false => Some(Dataset{c_dataset: c_dataset}),
        };
    }

    pub unsafe fn _with_c_ptr(c_dataset: *const ()) -> Dataset {
        return Dataset{c_dataset: c_dataset};
    }

    pub unsafe fn _c_ptr(&self) -> *const () {
        return self.c_dataset;
    }

    pub fn size(&self) -> (isize, isize) {
        let size_x = unsafe { gdal::GDALGetRasterXSize(self.c_dataset) } as isize;
        let size_y = unsafe { gdal::GDALGetRasterYSize(self.c_dataset) } as isize;
        return (size_x, size_y);
    }

    pub fn driver(&self) -> Driver {
        unsafe {
            let c_driver = gdal::GDALGetDatasetDriver(self.c_dataset);
            return Driver::_with_c_ptr(c_driver);
        };
    }

    pub fn count(&self) -> isize {
        return unsafe { gdal::GDALGetRasterCount(self.c_dataset) } as isize;
    }

    pub fn projection(&self) -> String {
        let rv = unsafe { gdal::GDALGetProjectionRef(self.c_dataset) };
        return _string(rv);
    }

    pub fn set_projection(&self, projection: &str) {
        let c_projection = CString::new(projection.as_bytes()).unwrap();
        unsafe { gdal::GDALSetProjection(self.c_dataset, c_projection.as_ptr()) };
    }

    pub fn set_geo_transform(&self, tr: &[f64]) {
        assert_eq!(tr.len(), 6);
        let rv = unsafe {
            gdal::GDALSetGeoTransform(self.c_dataset, tr.as_ptr())
        } as isize;
        assert!(rv == 0);
    }

    pub fn geo_transform(&self) -> Vec<f64> {
        let mut tr: Vec<c_double> = Vec::with_capacity(6);
        for _ in 0isize..6 { tr.push(0.0); }
        let rv = unsafe {
            gdal::GDALGetGeoTransform(
                self.c_dataset,
                tr.as_mut_ptr()
            )
        } as isize;
        assert!(rv == 0);
        return tr;
    }

    pub fn create_copy(
        &self,
        driver: Driver,
        filename: &str
    ) -> Option<Dataset> {
        use std::ptr::null;
        let c_filename = CString::new(filename.as_bytes()).unwrap();
        let c_dataset = unsafe { gdal::GDALCreateCopy(
                driver._c_ptr(),
                c_filename.as_ptr(),
                self.c_dataset,
                0,
                null(),
                null(),
                null()
            ) };
        return match c_dataset.is_null() {
            true  => None,
            false => Some(Dataset{c_dataset: c_dataset}),
        };
    }

    pub fn read_raster(&self,
        band_index: isize,
        window: Point<isize>,
        window_size: Point<usize>,
        size: Point<usize>
        ) -> ByteBuffer
    {
        let nbytes = size.x * size.y;
        let mut data: Vec<u8> = (0..nbytes).map(|_| 0u8).collect();
        unsafe {
            let c_band = gdal::GDALGetRasterBand(self.c_dataset, band_index as c_int);
            let rv = gdal::GDALRasterIO(
                c_band,
                gdal::GF_READ,
                window.x as c_int,
                window.y as c_int,
                window_size.x as c_int,
                window_size.y as c_int,
                data.as_mut_ptr() as *const (),
                size.x as c_int,
                size.y as c_int,
                gdal::GDT_BYTE,
                0,
                0
            ) as isize;
            assert!(rv == 0);
        };
        return ByteBuffer{
            size: size,
            data: data,
        };
    }

    pub fn write_raster(
        &self,
        band_index: isize,
        window: Point<isize>,
        window_size: Point<usize>,
        buffer: ByteBuffer
    ) {
        assert_eq!(buffer.data.len(), buffer.size.x * buffer.size.y);
        unsafe {
            let c_band = gdal::GDALGetRasterBand(self.c_dataset, band_index as c_int);
            let rv = gdal::GDALRasterIO(
                c_band,
                gdal::GF_WRITE,
                window.x as c_int,
                window.y as c_int,
                window_size.x as c_int,
                window_size.y as c_int,
                buffer.data.as_ptr() as *const (),
                buffer.size.x as c_int,
                buffer.size.y as c_int,
                gdal::GDT_BYTE,
                0,
                0
            ) as isize;
            assert!(rv == 0);
        };
    }
}

pub struct ByteBuffer {
    pub size: Point<usize>,
    pub data: Vec<u8>,
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! This file stolen wholesale from rustc/src/librustc/util/nodemap.rs

use std::default::Default;
use std::hash::Hasher;
use std::num::wrapping::WrappingOps;

/// A speedy hash algorithm for node ids and def ids. The hashmap in
/// libcollections by default uses SipHash which isn't quite as speedy as we
/// want. In the compiler we're not really worried about DOS attempts, so we
/// just default to a non-cryptographic hash.
///
/// This uses FNV hashing, as described here:
/// http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
pub struct FnvHasher(u64);

impl Default for FnvHasher {
    fn default() -> FnvHasher { FnvHasher(0xcbf29ce484222325) }
}

impl Hasher for FnvHasher {
    fn finish(&self) -> u64 { self.0 }
    fn write(&mut self, bytes: &[u8]) {
        let FnvHasher(mut hash) = *self;
        for byte in bytes.iter() {
            hash = hash ^ (*byte as u64);
            hash = hash.wrapping_mul(0x100000001b3);
        }
        *self = FnvHasher(hash);
    }
}
<commit_msg>Remove unused file: components/util/fnv.rs<commit_after><|endoftext|>


<commit_before>#[doc(
    brief = "Provides all access to AST-related, non-sendable info",
    desc =
    "Rustdoc is intended to be parallel, and the rustc AST is filled \
     with shared boxes. The AST service attempts to provide a single \
     place to query AST-related information, shielding the rest of \
     Rustdoc from its non-sendableness."
)];

import rustc::driver::session;
import rustc::driver::driver;
import rustc::driver::diagnostic;
import rustc::driver::diagnostic::handler;
import rustc::syntax::ast;
import rustc::syntax::codemap;
import rustc::middle::ast_map;
import rustc::back::link;
import rustc::util::filesearch;
import rustc::front;
import rustc::middle::resolve;

export ctxt;
export ctxt_handler;
export srv;
export from_str;
export from_file;
export exec;

type ctxt = {
    ast: @ast::crate,
    ast_map: ast_map::map,
    exp_map: resolve::exp_map
};

type srv_owner<T> = fn(srv: srv) -> T;
type ctxt_handler<T> = fn~(ctxt: ctxt) -> T;

type srv = {
    ctxt: ctxt
};

fn from_str<T>(source: str, owner: srv_owner<T>) -> T {
    let (sess, ignore_errors) = build_session();

    let srv = {
        ctxt: build_ctxt(sess, parse::from_str_sess(sess, source),
                         ignore_errors)
    };

    owner(srv)
}

fn from_file<T>(file: str, owner: srv_owner<T>) -> T {
    let (sess, ignore_errors) = build_session();

    let srv = {
        ctxt: build_ctxt(sess, parse::from_file_sess(sess, file),
                         ignore_errors)
    };

    owner(srv)
}

fn build_ctxt(sess: session::session, ast: @ast::crate,
              ignore_errors: @mutable bool) -> ctxt {

    import rustc::front::config;

    let ast = config::strip_unconfigured_items(ast);
    let ast = front::test::modify_for_testing(sess, ast);
    let ast_map = ast_map::map_crate(*ast);
    *ignore_errors = true;
    let exp_map = resolve::resolve_crate_reexports(sess, ast_map, ast);
    *ignore_errors = false;

    {
        ast: ast,
        ast_map: ast_map,
        exp_map: exp_map
    }
}

// FIXME: this whole structure should not be duplicated here. makes it
// painful to add or remove options.
fn build_session() -> (session::session, @mutable bool) {
    let sopts: @session::options = @{
        crate_type: session::lib_crate,
        static: false,
        optimize: 0u,
        debuginfo: false,
        extra_debuginfo: false,
        verify: false,
        lint_opts: [],
        save_temps: false,
        stats: false,
        time_passes: false,
        time_llvm_passes: false,
        output_type: link::output_type_exe,
        addl_lib_search_paths: [],
        maybe_sysroot: none,
        target_triple: driver::host_triple(),
        cfg: [],
        test: false,
        parse_only: false,
        no_trans: false,
        no_asm_comments: false,
        monomorphize: false,
        warn_unused_imports: false
    };

    let codemap = codemap::new_codemap();
    let error_handlers = build_error_handlers(codemap);
    let {emitter, span_handler, ignore_errors} = error_handlers;

    let session = driver::build_session_(sopts, ".", codemap, emitter,
                                         span_handler);
    (session, ignore_errors)
}

type error_handlers = {
    emitter: diagnostic::emitter,
    span_handler: diagnostic::span_handler,
    ignore_errors: @mutable bool
};

// Build a custom error handler that will allow us to ignore non-fatal
// errors
fn build_error_handlers(
    codemap: codemap::codemap
) -> error_handlers {

    type diagnostic_handler = {
        inner: diagnostic::handler,
        ignore_errors: @mutable bool
    };

    impl of diagnostic::handler for diagnostic_handler {
        fn fatal(msg: str) -> ! { self.inner.fatal(msg) }
        fn err(msg: str) { self.inner.err(msg) }
        fn bump_err_count() {
            if !(*self.ignore_errors) {
                self.inner.bump_err_count();
            }
        }
        fn has_errors() -> bool { self.inner.has_errors() }
        fn abort_if_errors() { self.inner.abort_if_errors() }
        fn warn(msg: str) { self.inner.warn(msg) }
        fn note(msg: str) { self.inner.note(msg) }
        fn bug(msg: str) -> ! { self.inner.bug(msg) }
        fn unimpl(msg: str) -> ! { self.inner.unimpl(msg) }
        fn emit(cmsp: option<(codemap::codemap, codemap::span)>,
                msg: str, lvl: diagnostic::level) {
            self.inner.emit(cmsp, msg, lvl)
        }
    }

    let ignore_errors = @mutable false;
    let emitter = fn@(cmsp: option<(codemap::codemap, codemap::span)>,
                       msg: str, lvl: diagnostic::level) {
        if !(*ignore_errors) {
            diagnostic::emit(cmsp, msg, lvl);
        }
    };
    let inner_handler = diagnostic::mk_handler(some(emitter));
    let handler = {
        inner: inner_handler,
        ignore_errors: ignore_errors
    };
    let span_handler = diagnostic::mk_span_handler(
        handler as diagnostic::handler, codemap);

    {
        emitter: emitter,
        span_handler: span_handler,
        ignore_errors: ignore_errors
    }
}

#[test]
fn should_prune_unconfigured_items() {
    let source = "#[cfg(shut_up_and_leave_me_alone)]fn a() { }";
    from_str(source) {|srv|
        exec(srv) {|ctxt|
            assert vec::is_empty(ctxt.ast.node.module.items);
        }
    }
}

#[test]
fn srv_should_build_ast_map() {
    let source = "fn a() { }";
    from_str(source) {|srv|
        exec(srv) {|ctxt|
            assert ctxt.ast_map.size() != 0u
        };
    }
}

#[test]
fn srv_should_build_reexport_map() {
    let source = "import a::b; export b; mod a { mod b { } }";
    from_str(source) {|srv|
        exec(srv) {|ctxt|
            assert ctxt.exp_map.size() != 0u
        };
    }
}

#[test]
fn srv_should_resolve_external_crates() {
    let source = "use std;\
                  fn f() -> std::sha1::sha1 {\
                  std::sha1::mk_sha1() }";
    // Just testing that resolve doesn't crash
    from_str(source) {|_srv| }
}

#[test]
fn srv_should_resolve_core_crate() {
    let source = "fn a() -> option { fail }";
    // Just testing that resolve doesn't crash
    from_str(source) {|_srv| }
}

#[test]
fn srv_should_resolve_non_existant_imports() {
    // We want to ignore things we can't resolve. Shouldn't
    // need to be able to find external crates to create docs.
    let source = "import wooboo; fn a() { }";
    from_str(source) {|_srv| }
}

#[test]
fn srv_should_resolve_non_existant_uses() {
    let source = "use forble; fn a() { }";
    from_str(source) {|_srv| }
}

#[test]
fn should_ignore_external_import_paths_that_dont_exist() {
    let source = "use forble; import forble::bippy;";
    from_str(source) {|_srv| }
}

fn exec<T:send>(
    srv: srv,
    f: fn~(ctxt: ctxt) -> T
) -> T {
    f(srv.ctxt)
}

#[test]
fn srv_should_return_request_result() {
    let source = "fn a() { }";
    from_str(source) {|srv|
        let result = exec(srv) {|_ctxt| 1000};
        assert result == 1000;
    }
}
<commit_msg>rustdoc: Implement astsrv in a dedicated task<commit_after>#[doc(
    brief = "Provides all access to AST-related, non-sendable info",
    desc =
    "Rustdoc is intended to be parallel, and the rustc AST is filled \
     with shared boxes. The AST service attempts to provide a single \
     place to query AST-related information, shielding the rest of \
     Rustdoc from its non-sendableness."
)];

import rustc::driver::session;
import rustc::driver::driver;
import rustc::driver::diagnostic;
import rustc::driver::diagnostic::handler;
import rustc::syntax::ast;
import rustc::syntax::codemap;
import rustc::middle::ast_map;
import rustc::back::link;
import rustc::util::filesearch;
import rustc::front;
import rustc::middle::resolve;

export ctxt;
export ctxt_handler;
export srv::{};
export from_str;
export from_file;
export exec;

type ctxt = {
    ast: @ast::crate,
    ast_map: ast_map::map,
    exp_map: resolve::exp_map
};

type srv_owner<T> = fn(srv: srv) -> T;
type ctxt_handler<T> = fn~(ctxt: ctxt) -> T;
type parser = fn~(session::session, str) -> @ast::crate;

enum msg {
    handle_request(fn~(ctxt)),
    exit
}

enum srv = {
    ch: comm::chan<msg>
};

fn from_str<T>(source: str, owner: srv_owner<T>) -> T {
    run(owner, source, parse::from_str_sess)
}

fn from_file<T>(file: str, owner: srv_owner<T>) -> T {
    run(owner, file, parse::from_file_sess)
}

fn run<T>(owner: srv_owner<T>, source: str, parse: parser) -> T {

    let srv_ = srv({
        ch: task::spawn_listener {|po|
            act(po, source, parse);
        }
    });

    let res = owner(srv_);
    comm::send(srv_.ch, exit);
    ret res;
}

fn act(po: comm::port<msg>, source: str, parse: parser) {
    let (sess, ignore_errors) = build_session();

    let ctxt = build_ctxt(
        sess,
        parse(sess, source),
        ignore_errors
    );

    let keep_going = true;
    while keep_going {
        alt comm::recv(po) {
          handle_request(f) {
            f(ctxt);
          }
          exit {
            keep_going = false;
          }
        }
    }
}

fn exec<T:send>(
    srv: srv,
    +f: fn~(ctxt: ctxt) -> T
) -> T {
    let po = comm::port();
    let ch = comm::chan(po);
    let msg = handle_request(fn~[move f](ctxt: ctxt) {
        comm::send(ch, f(ctxt))
    });
    comm::send(srv.ch, msg);
    comm::recv(po)
}

fn build_ctxt(sess: session::session, ast: @ast::crate,
              ignore_errors: @mutable bool) -> ctxt {

    import rustc::front::config;

    let ast = config::strip_unconfigured_items(ast);
    let ast = front::test::modify_for_testing(sess, ast);
    let ast_map = ast_map::map_crate(*ast);
    *ignore_errors = true;
    let exp_map = resolve::resolve_crate_reexports(sess, ast_map, ast);
    *ignore_errors = false;

    {
        ast: ast,
        ast_map: ast_map,
        exp_map: exp_map
    }
}

// FIXME: this whole structure should not be duplicated here. makes it
// painful to add or remove options.
fn build_session() -> (session::session, @mutable bool) {
    let sopts: @session::options = @{
        crate_type: session::lib_crate,
        static: false,
        optimize: 0u,
        debuginfo: false,
        extra_debuginfo: false,
        verify: false,
        lint_opts: [],
        save_temps: false,
        stats: false,
        time_passes: false,
        time_llvm_passes: false,
        output_type: link::output_type_exe,
        addl_lib_search_paths: [],
        maybe_sysroot: none,
        target_triple: driver::host_triple(),
        cfg: [],
        test: false,
        parse_only: false,
        no_trans: false,
        no_asm_comments: false,
        monomorphize: false,
        warn_unused_imports: false
    };

    let codemap = codemap::new_codemap();
    let error_handlers = build_error_handlers(codemap);
    let {emitter, span_handler, ignore_errors} = error_handlers;

    let session = driver::build_session_(sopts, ".", codemap, emitter,
                                         span_handler);
    (session, ignore_errors)
}

type error_handlers = {
    emitter: diagnostic::emitter,
    span_handler: diagnostic::span_handler,
    ignore_errors: @mutable bool
};

// Build a custom error handler that will allow us to ignore non-fatal
// errors
fn build_error_handlers(
    codemap: codemap::codemap
) -> error_handlers {

    type diagnostic_handler = {
        inner: diagnostic::handler,
        ignore_errors: @mutable bool
    };

    impl of diagnostic::handler for diagnostic_handler {
        fn fatal(msg: str) -> ! { self.inner.fatal(msg) }
        fn err(msg: str) { self.inner.err(msg) }
        fn bump_err_count() {
            if !(*self.ignore_errors) {
                self.inner.bump_err_count();
            }
        }
        fn has_errors() -> bool { self.inner.has_errors() }
        fn abort_if_errors() { self.inner.abort_if_errors() }
        fn warn(msg: str) { self.inner.warn(msg) }
        fn note(msg: str) { self.inner.note(msg) }
        fn bug(msg: str) -> ! { self.inner.bug(msg) }
        fn unimpl(msg: str) -> ! { self.inner.unimpl(msg) }
        fn emit(cmsp: option<(codemap::codemap, codemap::span)>,
                msg: str, lvl: diagnostic::level) {
            self.inner.emit(cmsp, msg, lvl)
        }
    }

    let ignore_errors = @mutable false;
    let emitter = fn@(cmsp: option<(codemap::codemap, codemap::span)>,
                       msg: str, lvl: diagnostic::level) {
        if !(*ignore_errors) {
            diagnostic::emit(cmsp, msg, lvl);
        }
    };
    let inner_handler = diagnostic::mk_handler(some(emitter));
    let handler = {
        inner: inner_handler,
        ignore_errors: ignore_errors
    };
    let span_handler = diagnostic::mk_span_handler(
        handler as diagnostic::handler, codemap);

    {
        emitter: emitter,
        span_handler: span_handler,
        ignore_errors: ignore_errors
    }
}

#[test]
fn should_prune_unconfigured_items() {
    let source = "#[cfg(shut_up_and_leave_me_alone)]fn a() { }";
    from_str(source) {|srv|
        exec(srv) {|ctxt|
            assert vec::is_empty(ctxt.ast.node.module.items);
        }
    }
}

#[test]
fn srv_should_build_ast_map() {
    let source = "fn a() { }";
    from_str(source) {|srv|
        exec(srv) {|ctxt|
            assert ctxt.ast_map.size() != 0u
        };
    }
}

#[test]
fn srv_should_build_reexport_map() {
    let source = "import a::b; export b; mod a { mod b { } }";
    from_str(source) {|srv|
        exec(srv) {|ctxt|
            assert ctxt.exp_map.size() != 0u
        };
    }
}

#[test]
fn srv_should_resolve_external_crates() {
    let source = "use std;\
                  fn f() -> std::sha1::sha1 {\
                  std::sha1::mk_sha1() }";
    // Just testing that resolve doesn't crash
    from_str(source) {|_srv| }
}

#[test]
fn srv_should_resolve_core_crate() {
    let source = "fn a() -> option { fail }";
    // Just testing that resolve doesn't crash
    from_str(source) {|_srv| }
}

#[test]
fn srv_should_resolve_non_existant_imports() {
    // We want to ignore things we can't resolve. Shouldn't
    // need to be able to find external crates to create docs.
    let source = "import wooboo; fn a() { }";
    from_str(source) {|_srv| }
}

#[test]
fn srv_should_resolve_non_existant_uses() {
    let source = "use forble; fn a() { }";
    from_str(source) {|_srv| }
}

#[test]
fn should_ignore_external_import_paths_that_dont_exist() {
    let source = "use forble; import forble::bippy;";
    from_str(source) {|_srv| }
}

#[test]
fn srv_should_return_request_result() {
    let source = "fn a() { }";
    from_str(source) {|srv|
        let result = exec(srv) {|_ctxt| 1000};
        assert result == 1000;
    }
}
<|endoftext|>


<commit_before>use super::dsp::Dsp;
// TODO: This is a placeholder before I start generalizing traits
// from the old code.
use super::apu::Apu;
use super::envelope::Envelope;
use super::brr_block_decoder::BrrBlockDecoder;
use super::dsp_helpers;

pub struct VoiceOutput {
    pub left_out: i32,
    pub right_out: i32,
    pub last_voice_out: i32
}

pub struct Voice {
    dsp: *mut Dsp,
    emulator: *mut Apu,

    pub envelope: Box<Envelope>,

    pub vol_left: u8,
    pub vol_right: u8,
    pub pitch_low: u8,
    pitch_high: u8,
    pub source: u8,
    pub pitch_mod: bool,
    pub noise_on: bool,
    pub echo_on: bool,

    sample_start_address: u32,
    loop_start_address: u32,
    brr_block_decoder: Box<BrrBlockDecoder>,
    sample_address: u32,
    sample_pos: i32,
    current_sample: i32,
    next_sample: i32
}

impl Voice {
    pub fn new(dsp: *mut Dsp, emulator: *mut Apu) -> Voice {
        Voice {
            dsp: dsp,
            emulator: emulator,

            envelope: Box::new(Envelope::new(dsp)),

            vol_left: 0,
            vol_right: 0,
            pitch_low: 0,
            pitch_high: 0x10,
            source: 0,
            pitch_mod: false,
            noise_on: false,
            echo_on: false,

            sample_start_address: 0,
            loop_start_address: 0,
            brr_block_decoder: Box::new(BrrBlockDecoder::new()),
            sample_address: 0,
            sample_pos: 0,
            current_sample: 0,
            next_sample: 0
        }
    }

    #[inline]
    fn dsp(&self) -> &mut Dsp {
        unsafe {
            &mut (*self.dsp)
        }
    }

    #[inline]
    fn emulator(&self) -> &mut Apu {
        unsafe {
            &mut (*self.emulator)
        }
    }

    pub fn render_sample(&mut self, last_voice_out: i32, noise: i32) -> VoiceOutput {
        let mut pitch = ((self.pitch_high as i32) << 8) | (self.pitch_low as i32);
        if self.pitch_mod {
            pitch += ((last_voice_out >> 5) * pitch) >> 10;
        }
        if pitch < 0 {
            pitch = 0;
        }
        if pitch > 0x3fff {
            pitch = 0x3fff;
        }

        let p1 = self.sample_pos;
        let p2 = 0x1000 - p1;
        let mut sample = if self.noise_on {
            ((noise * 2) as i16) as i32
        } else {
            dsp_helpers::clamp((self.current_sample * p2 + self.next_sample * p1) >> 12) & !1
        };

        self.envelope.tick();
        let env_level = self.envelope.level;

        sample = ((sample * env_level) >> 11) & !1;

        if self.brr_block_decoder.is_end && !self.brr_block_decoder.is_looping {
            self.envelope.key_off();
            self.envelope.level = 0;
        }

        self.sample_pos += pitch;
        while self.sample_pos >= 0x1000 {
            self.sample_pos -= 0x1000;
            self.read_next_sample();

            if self.brr_block_decoder.is_finished() {
                if self.brr_block_decoder.is_end && self.brr_block_decoder.is_looping {
                    self.read_entry();
                    self.sample_address = self.loop_start_address;
                }
                self.read_next_block();
            }
        }

        VoiceOutput {
            left_out: dsp_helpers::multiply_volume(sample, self.vol_left),
            right_out: dsp_helpers::multiply_volume(sample, self.vol_right),
            last_voice_out: sample
        }
    }

    pub fn get_pitch_high(&self) -> u8 {
        self.pitch_high
    }

    pub fn set_pitch_high(&mut self, value: u8) {
        self.pitch_high = value & 0x3f;
    }

    pub fn key_on(&mut self) {
        self.read_entry();
        self.sample_address = self.sample_start_address;
        self.brr_block_decoder.reset(0, 0);
        self.read_next_block();
        self.sample_pos = 0;
        self.next_sample = 0;
        self.read_next_sample();
        self.envelope.key_on();
    }

    pub fn key_off(&mut self) {
        self.envelope.key_off();
    }

    fn read_entry(&mut self) {
        self.sample_start_address = self.dsp().read_source_dir_start_address(self.source as i32);
        self.loop_start_address = self.dsp().read_source_dir_loop_address(self.source as i32);
    }

    fn read_next_block(&mut self) {
        let mut buf = [0; 9];
        for i in 0..9 {
            buf[i] = self.emulator().read_u8(self.sample_address + (i as u32));
        }
        self.brr_block_decoder.read(&buf);
        self.sample_address += 9;
    }

    fn read_next_sample(&mut self) {
        self.current_sample = self.next_sample;
        self.next_sample = self.brr_block_decoder.read_next_sample() as i32;
    }
}
<commit_msg>Tiny refactoring<commit_after>use super::dsp::Dsp;
// TODO: This is a placeholder before I start generalizing traits
// from the old code.
use super::apu::Apu;
use super::envelope::Envelope;
use super::brr_block_decoder::BrrBlockDecoder;
use super::dsp_helpers;

pub struct VoiceOutput {
    pub left_out: i32,
    pub right_out: i32,
    pub last_voice_out: i32
}

pub struct Voice {
    dsp: *mut Dsp,
    emulator: *mut Apu,

    pub envelope: Box<Envelope>,

    pub vol_left: u8,
    pub vol_right: u8,
    pub pitch_low: u8,
    pitch_high: u8,
    pub source: u8,
    pub pitch_mod: bool,
    pub noise_on: bool,
    pub echo_on: bool,

    sample_start_address: u32,
    loop_start_address: u32,
    brr_block_decoder: Box<BrrBlockDecoder>,
    sample_address: u32,
    sample_pos: i32,
    current_sample: i32,
    next_sample: i32
}

impl Voice {
    pub fn new(dsp: *mut Dsp, emulator: *mut Apu) -> Voice {
        Voice {
            dsp: dsp,
            emulator: emulator,

            envelope: Box::new(Envelope::new(dsp)),

            vol_left: 0,
            vol_right: 0,
            pitch_low: 0,
            pitch_high: 0x10,
            source: 0,
            pitch_mod: false,
            noise_on: false,
            echo_on: false,

            sample_start_address: 0,
            loop_start_address: 0,
            brr_block_decoder: Box::new(BrrBlockDecoder::new()),
            sample_address: 0,
            sample_pos: 0,
            current_sample: 0,
            next_sample: 0
        }
    }

    #[inline]
    fn dsp(&self) -> &mut Dsp {
        unsafe {
            &mut (*self.dsp)
        }
    }

    #[inline]
    fn emulator(&self) -> &mut Apu {
        unsafe {
            &mut (*self.emulator)
        }
    }

    pub fn render_sample(&mut self, last_voice_out: i32, noise: i32) -> VoiceOutput {
        let mut pitch = ((self.pitch_high as i32) << 8) | (self.pitch_low as i32);
        if self.pitch_mod {
            pitch += ((last_voice_out >> 5) * pitch) >> 10;
        }
        if pitch < 0 {
            pitch = 0;
        }
        if pitch > 0x3fff {
            pitch = 0x3fff;
        }

        let p1 = self.sample_pos;
        let p2 = 0x1000 - p1;
        let mut sample = if !self.noise_on {
            dsp_helpers::clamp((self.current_sample * p2 + self.next_sample * p1) >> 12) & !1
        } else {
            ((noise * 2) as i16) as i32
        };

        self.envelope.tick();
        let env_level = self.envelope.level;

        sample = ((sample * env_level) >> 11) & !1;

        if self.brr_block_decoder.is_end && !self.brr_block_decoder.is_looping {
            self.envelope.key_off();
            self.envelope.level = 0;
        }

        self.sample_pos += pitch;
        while self.sample_pos >= 0x1000 {
            self.sample_pos -= 0x1000;
            self.read_next_sample();

            if self.brr_block_decoder.is_finished() {
                if self.brr_block_decoder.is_end && self.brr_block_decoder.is_looping {
                    self.read_entry();
                    self.sample_address = self.loop_start_address;
                }
                self.read_next_block();
            }
        }

        VoiceOutput {
            left_out: dsp_helpers::multiply_volume(sample, self.vol_left),
            right_out: dsp_helpers::multiply_volume(sample, self.vol_right),
            last_voice_out: sample
        }
    }

    pub fn get_pitch_high(&self) -> u8 {
        self.pitch_high
    }

    pub fn set_pitch_high(&mut self, value: u8) {
        self.pitch_high = value & 0x3f;
    }

    pub fn key_on(&mut self) {
        self.read_entry();
        self.sample_address = self.sample_start_address;
        self.brr_block_decoder.reset(0, 0);
        self.read_next_block();
        self.sample_pos = 0;
        self.next_sample = 0;
        self.read_next_sample();
        self.envelope.key_on();
    }

    pub fn key_off(&mut self) {
        self.envelope.key_off();
    }

    fn read_entry(&mut self) {
        self.sample_start_address = self.dsp().read_source_dir_start_address(self.source as i32);
        self.loop_start_address = self.dsp().read_source_dir_loop_address(self.source as i32);
    }

    fn read_next_block(&mut self) {
        let mut buf = [0; 9];
        for i in 0..9 {
            buf[i] = self.emulator().read_u8(self.sample_address + (i as u32));
        }
        self.brr_block_decoder.read(&buf);
        self.sample_address += 9;
    }

    fn read_next_sample(&mut self) {
        self.current_sample = self.next_sample;
        self.next_sample = self.brr_block_decoder.read_next_sample() as i32;
    }
}
<|endoftext|>


<commit_before>use structure;

pub mod integer;
pub mod sequence;
pub mod octetstring;
pub mod boolean;
pub mod null;

// Reexport everything
pub use integer::Integer;
pub use sequence::{Sequence, SequenceOf, SetOf};
pub use octetstring::OctetString;
pub use boolean::Boolean;
pub use null::Null;

pub trait ASNTag {
    /// Encode yourself into a generic Tag format.
    ///
    /// The only thing that changes between types is how to encode the value they wrap into bytes,
    /// however the encoding of the class and id does not change. By first converting the tag into
    /// a more generic tag (with already encoded payload), we don't have to reimplement the
    /// encoding step for class & id every time.
    fn into_structure(self) -> structure::StructureTag;
}

#[derive(Clone, Debug)]
/// This enum does not cover all ASN.1 Types but only the types needed for LDAPv3.
pub enum Tag {
    Integer(integer::Integer),
    Sequence(sequence::Sequence),
    OctetString(octetstring::OctetString),
    Boolean(boolean::Boolean),
    Null(null::Null),
    StructureTag(structure::StructureTag),
}

impl ASNTag for Tag {
    fn into_structure(self) -> structure::StructureTag {
        match self {
            Tag::Integer(i)      => i.into_structure(),
            Tag::Sequence(i)     => i.into_structure(),
            Tag::OctetString(i)  => i.into_structure(),
            Tag::Boolean(i)      => i.into_structure(),
            Tag::Null(i)         => i.into_structure(),
            Tag::StructureTag(s) => s
        }
    }
}
<commit_msg>Make compile<commit_after>use structure;

pub mod integer;
pub mod sequence;
pub mod octetstring;
pub mod boolean;
pub mod null;

// Reexport everything
pub use self::integer::Integer;
pub use self::sequence::{Sequence, SequenceOf, SetOf};
pub use self::octetstring::OctetString;
pub use self::boolean::Boolean;
pub use self::null::Null;

pub trait ASNTag {
    /// Encode yourself into a generic Tag format.
    ///
    /// The only thing that changes between types is how to encode the value they wrap into bytes,
    /// however the encoding of the class and id does not change. By first converting the tag into
    /// a more generic tag (with already encoded payload), we don't have to reimplement the
    /// encoding step for class & id every time.
    fn into_structure(self) -> structure::StructureTag;
}

#[derive(Clone, Debug)]
/// This enum does not cover all ASN.1 Types but only the types needed for LDAPv3.
pub enum Tag {
    Integer(integer::Integer),
    Sequence(sequence::Sequence),
    OctetString(octetstring::OctetString),
    Boolean(boolean::Boolean),
    Null(null::Null),
    StructureTag(structure::StructureTag),
}

impl ASNTag for Tag {
    fn into_structure(self) -> structure::StructureTag {
        match self {
            Tag::Integer(i)      => i.into_structure(),
            Tag::Sequence(i)     => i.into_structure(),
            Tag::OctetString(i)  => i.into_structure(),
            Tag::Boolean(i)      => i.into_structure(),
            Tag::Null(i)         => i.into_structure(),
            Tag::StructureTag(s) => s
        }
    }
}
<|endoftext|>