<commit_before>use futures_core::future::{FusedFuture, Future};
use futures_core::task::{LocalWaker, Poll, Waker};
use slab::Slab;
use std::{fmt, mem, usize};
use std::cell::UnsafeCell;
use std::ops::{Deref, DerefMut};
use std::pin::Pin;
use std::sync::Mutex as StdMutex;
use std::sync::atomic::{AtomicUsize, Ordering};

/// A futures-aware mutex.
pub struct Mutex<T> {
    state: AtomicUsize,
    value: UnsafeCell<T>,
    waiters: StdMutex<Slab<Waiter>>,
}

impl<T> fmt::Debug for Mutex<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let state = self.state.load(Ordering::SeqCst);
        f.debug_struct("Mutex")
            .field("is_locked", &((state & IS_LOCKED) != 0))
            .field("has_waiters", &((state & IS_LOCKED) != 0))
            .finish()
    }
}

enum Waiter {
    Waiting(Waker),
    Woken,
}

impl Waiter {
    fn register(&mut self, lw: &LocalWaker) {
        match self {
            Waiter::Waiting(waker) => if !lw.will_wake_nonlocal(waker) {
                *waker = lw.clone().into_waker();
            },
            Waiter::Woken => *self = Waiter::Waiting(lw.clone().into_waker()),
        }
    }

    fn wake(&mut self) {
        match mem::replace(self, Waiter::Woken) {
            Waiter::Waiting(waker) => waker.wake(),
            Waiter::Woken => {},
        }
    }
}

#[allow(clippy::identity_op)] // https://github.com/rust-lang/rust-clippy/issues/3445
const IS_LOCKED: usize = 1 << 0;
const HAS_WAITERS: usize = 1 << 1;

impl<T> Mutex<T> {
    /// Creates a new futures-aware mutex.
    pub fn new(t: T) -> Mutex<T> {
        Mutex {
            state: AtomicUsize::new(0),
            value: UnsafeCell::new(t),
            waiters: StdMutex::new(Slab::new()),
        }
    }

    /// Attempt to acquire the lock immediately.
    ///
    /// If the lock is currently held, this will return `None`.
    pub fn try_lock(&self) -> Option<MutexGuard<'_, T>> {
        let old_state = self.state.fetch_or(IS_LOCKED, Ordering::Acquire);
        if (old_state & IS_LOCKED) == 0 {
            Some(MutexGuard { mutex: self })
        } else {
            None
        }
    }

    /// Acquire the lock asynchronously.
    ///
    /// This method returns a future that will resolve once the loch has been
    /// successfully acquired.
    pub fn lock(&self) -> MutexAcquire<'_, T> {
        MutexAcquire {
            mutex: Some(self),
            wait_key: WAIT_KEY_NONE,
        }
    }

    fn remove_waker(&self, wait_key: usize, wake_another: bool) {
        if wait_key != WAIT_KEY_NONE {
            let mut waiters = self.waiters.lock().unwrap();
            match waiters.remove(wait_key) {
                Waiter::Waiting(_) => {},
                Waiter::Woken => {
                    // We were awoken, but then dropped before we could
                    // wake up to acquire the lock. Wake up another
                    // waiter.
                    if wake_another {
                        if let Some((_i, waiter)) = waiters.iter_mut().next() {
                            waiter.wake();
                        }
                    }
                }
            }
            if waiters.is_empty() {
                self.state.fetch_and(!HAS_WAITERS, Ordering::Relaxed); // released by mutex unlock
            }
        }
    }
}

// Sentinel for when no slot in the `Slab` has been dedicated to this object.
const WAIT_KEY_NONE: usize = usize::MAX;

/// A future which resolves when the target mutex has been successfully acquired.
pub struct MutexAcquire<'a, T: 'a> {
    // `None` indicates that the mutex was successfully acquired.
    mutex: Option<&'a Mutex<T>>,
    wait_key: usize,
}

impl<T> fmt::Debug for MutexAcquire<'_, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("MutexAcquire")
            .field("was_acquired", &self.mutex.is_none())
            .field("mutex", &self.mutex)
            .field("wait_key", &(
                    if self.wait_key == WAIT_KEY_NONE {
                        None
                    } else {
                        Some(self.wait_key)
                    }
                ))
            .finish()
    }
}

impl<T> FusedFuture for MutexAcquire<'_, T> {
    fn is_terminated(&self) -> bool {
        self.mutex.is_none()
    }
}

impl<'a, T> Future for MutexAcquire<'a, T> {
    type Output = MutexGuard<'a, T>;

    fn poll(mut self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<Self::Output> {
        let mutex = self.mutex.expect("polled MutexAcquire after completion");

        if let Some(lock) = mutex.try_lock() {
            mutex.remove_waker(self.wait_key, false);
            self.mutex = None;
            return Poll::Ready(lock);
        }

        {
            let mut waiters = mutex.waiters.lock().unwrap();
            if self.wait_key == WAIT_KEY_NONE {
                self.wait_key = waiters.insert(Waiter::Waiting(lw.clone().into_waker()));
                if waiters.len() == 1 {
                    mutex.state.fetch_or(HAS_WAITERS, Ordering::Relaxed); // released by mutex unlock
                }
            } else {
                waiters[self.wait_key].register(lw);
            }
        }

        // Ensure that we haven't raced `MutexGuard::drop`'s unlock path by
        // attempting to acquire the lock again.
        if let Some(lock) = mutex.try_lock() {
            mutex.remove_waker(self.wait_key, false);
            self.mutex = None;
            return Poll::Ready(lock);
        }

        Poll::Pending
    }
}

impl<T> Drop for MutexAcquire<'_, T> {
    fn drop(&mut self) {
        if let Some(mutex) = self.mutex {
            // This future was dropped before it acquired the mutex.
            //
            // Remove ourselves from the map, waking up another waiter if we
            // had been awoken to acquire the lock.
            mutex.remove_waker(self.wait_key, true);
        }
    }
}

/// An RAII guard returned by the `lock` and `try_lock` methods.
/// When this structure is dropped (falls out of scope), the lock will be
/// unlocked.
pub struct MutexGuard<'a, T: 'a> {
    mutex: &'a Mutex<T>,
}

impl<T: fmt::Debug> fmt::Debug for MutexGuard<'_, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("MutexGuard")
            .field("value", &*self)
            .field("mutex", &self.mutex)
            .finish()
    }
}

impl<T> Drop for MutexGuard<'_, T> {
    fn drop(&mut self) {
        let old_state = self.mutex.state.fetch_and(!IS_LOCKED, Ordering::AcqRel);
        if (old_state & HAS_WAITERS) != 0 {
            let mut waiters = self.mutex.waiters.lock().unwrap();
            if let Some((_i, waiter)) = waiters.iter_mut().next() {
                waiter.wake();
            }
        }
    }
}

impl<T> Deref for MutexGuard<'_, T> {
    type Target = T;
    fn deref(&self) -> &T {
        unsafe { &*self.mutex.value.get() }
    }
}

impl<T> DerefMut for MutexGuard<'_, T> {
    fn deref_mut(&mut self) -> &mut T {
        unsafe { &mut *self.mutex.value.get() }
    }
}

// Mutexes can be moved freely between threads and acquired on any thread so long
// as the inner value can be safely sent between threads.
unsafe impl<T: Send> Send for Mutex<T> {}
unsafe impl<T: Send> Sync for Mutex<T> {}

// It's safe to switch which thread the acquire is being attempted on so long as
// `T` can be accessed on that thread.
unsafe impl<T: Send> Send for MutexAcquire<'_, T> {}
// doesn't have any interesting `&self` methods (only Debug)
unsafe impl<T> Sync for MutexAcquire<'_, T> {}

// Safe to send since we don't track any thread-specific details-- the inner
// lock is essentially spinlock-equivalent (attempt to flip an atomic bool)
unsafe impl<T: Send> Send for MutexGuard<'_, T> {}
unsafe impl<T: Sync> Sync for MutexGuard<'_, T> {}
<commit_msg>futures_util::lock::Mutex review fixups<commit_after>use futures_core::future::{FusedFuture, Future};
use futures_core::task::{LocalWaker, Poll, Waker};
use slab::Slab;
use std::{fmt, mem, usize};
use std::cell::UnsafeCell;
use std::ops::{Deref, DerefMut};
use std::pin::Pin;
use std::sync::Mutex as StdMutex;
use std::sync::atomic::{AtomicUsize, Ordering};

/// A futures-aware mutex.
pub struct Mutex<T> {
    state: AtomicUsize,
    value: UnsafeCell<T>,
    waiters: StdMutex<Slab<Waiter>>,
}

impl<T> fmt::Debug for Mutex<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let state = self.state.load(Ordering::SeqCst);
        f.debug_struct("Mutex")
            .field("is_locked", &((state & IS_LOCKED) != 0))
            .field("has_waiters", &((state & HAS_WAITERS) != 0))
            .finish()
    }
}

enum Waiter {
    Waiting(Waker),
    Woken,
}

impl Waiter {
    fn register(&mut self, lw: &LocalWaker) {
        match self {
            Waiter::Waiting(waker) if lw.will_wake_nonlocal(waker) => {},
            _ => *self = Waiter::Waiting(lw.clone().into_waker()),
        }
    }

    fn wake(&mut self) {
        match mem::replace(self, Waiter::Woken) {
            Waiter::Waiting(waker) => waker.wake(),
            Waiter::Woken => {},
        }
    }
}

#[allow(clippy::identity_op)] // https://github.com/rust-lang/rust-clippy/issues/3445
const IS_LOCKED: usize = 1 << 0;
const HAS_WAITERS: usize = 1 << 1;

impl<T> Mutex<T> {
    /// Creates a new futures-aware mutex.
    pub fn new(t: T) -> Mutex<T> {
        Mutex {
            state: AtomicUsize::new(0),
            value: UnsafeCell::new(t),
            waiters: StdMutex::new(Slab::new()),
        }
    }

    /// Attempt to acquire the lock immediately.
    ///
    /// If the lock is currently held, this will return `None`.
    pub fn try_lock(&self) -> Option<MutexGuard<'_, T>> {
        let old_state = self.state.fetch_or(IS_LOCKED, Ordering::Acquire);
        if (old_state & IS_LOCKED) == 0 {
            Some(MutexGuard { mutex: self })
        } else {
            None
        }
    }

    /// Acquire the lock asynchronously.
    ///
    /// This method returns a future that will resolve once the lock has been
    /// successfully acquired.
    pub fn lock(&self) -> MutexAcquire<'_, T> {
        MutexAcquire {
            mutex: Some(self),
            wait_key: WAIT_KEY_NONE,
        }
    }

    fn remove_waker(&self, wait_key: usize, wake_another: bool) {
        if wait_key != WAIT_KEY_NONE {
            let mut waiters = self.waiters.lock().unwrap();
            match waiters.remove(wait_key) {
                Waiter::Waiting(_) => {},
                Waiter::Woken => {
                    // We were awoken, but then dropped before we could
                    // wake up to acquire the lock. Wake up another
                    // waiter.
                    if wake_another {
                        if let Some((_i, waiter)) = waiters.iter_mut().next() {
                            waiter.wake();
                        }
                    }
                }
            }
            if waiters.is_empty() {
                self.state.fetch_and(!HAS_WAITERS, Ordering::Relaxed); // released by mutex unlock
            }
        }
    }
}

// Sentinel for when no slot in the `Slab` has been dedicated to this object.
const WAIT_KEY_NONE: usize = usize::MAX;

/// A future which resolves when the target mutex has been successfully acquired.
pub struct MutexAcquire<'a, T: 'a> {
    // `None` indicates that the mutex was successfully acquired.
    mutex: Option<&'a Mutex<T>>,
    wait_key: usize,
}

impl<T> fmt::Debug for MutexAcquire<'_, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("MutexAcquire")
            .field("was_acquired", &self.mutex.is_none())
            .field("mutex", &self.mutex)
            .field("wait_key", &(
                    if self.wait_key == WAIT_KEY_NONE {
                        None
                    } else {
                        Some(self.wait_key)
                    }
                ))
            .finish()
    }
}

impl<T> FusedFuture for MutexAcquire<'_, T> {
    fn is_terminated(&self) -> bool {
        self.mutex.is_none()
    }
}

impl<'a, T> Future for MutexAcquire<'a, T> {
    type Output = MutexGuard<'a, T>;

    fn poll(mut self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<Self::Output> {
        let mutex = self.mutex.expect("polled MutexAcquire after completion");

        if let Some(lock) = mutex.try_lock() {
            mutex.remove_waker(self.wait_key, false);
            self.mutex = None;
            return Poll::Ready(lock);
        }

        {
            let mut waiters = mutex.waiters.lock().unwrap();
            if self.wait_key == WAIT_KEY_NONE {
                self.wait_key = waiters.insert(Waiter::Waiting(lw.clone().into_waker()));
                if waiters.len() == 1 {
                    mutex.state.fetch_or(HAS_WAITERS, Ordering::Relaxed); // released by mutex unlock
                }
            } else {
                waiters[self.wait_key].register(lw);
            }
        }

        // Ensure that we haven't raced `MutexGuard::drop`'s unlock path by
        // attempting to acquire the lock again.
        if let Some(lock) = mutex.try_lock() {
            mutex.remove_waker(self.wait_key, false);
            self.mutex = None;
            return Poll::Ready(lock);
        }

        Poll::Pending
    }
}

impl<T> Drop for MutexAcquire<'_, T> {
    fn drop(&mut self) {
        if let Some(mutex) = self.mutex {
            // This future was dropped before it acquired the mutex.
            //
            // Remove ourselves from the map, waking up another waiter if we
            // had been awoken to acquire the lock.
            mutex.remove_waker(self.wait_key, true);
        }
    }
}

/// An RAII guard returned by the `lock` and `try_lock` methods.
/// When this structure is dropped (falls out of scope), the lock will be
/// unlocked.
pub struct MutexGuard<'a, T: 'a> {
    mutex: &'a Mutex<T>,
}

impl<T: fmt::Debug> fmt::Debug for MutexGuard<'_, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("MutexGuard")
            .field("value", &*self)
            .field("mutex", &self.mutex)
            .finish()
    }
}

impl<T> Drop for MutexGuard<'_, T> {
    fn drop(&mut self) {
        let old_state = self.mutex.state.fetch_and(!IS_LOCKED, Ordering::AcqRel);
        if (old_state & HAS_WAITERS) != 0 {
            let mut waiters = self.mutex.waiters.lock().unwrap();
            if let Some((_i, waiter)) = waiters.iter_mut().next() {
                waiter.wake();
            }
        }
    }
}

impl<T> Deref for MutexGuard<'_, T> {
    type Target = T;
    fn deref(&self) -> &T {
        unsafe { &*self.mutex.value.get() }
    }
}

impl<T> DerefMut for MutexGuard<'_, T> {
    fn deref_mut(&mut self) -> &mut T {
        unsafe { &mut *self.mutex.value.get() }
    }
}

// Mutexes can be moved freely between threads and acquired on any thread so long
// as the inner value can be safely sent between threads.
unsafe impl<T: Send> Send for Mutex<T> {}
unsafe impl<T: Send> Sync for Mutex<T> {}

// It's safe to switch which thread the acquire is being attempted on so long as
// `T` can be accessed on that thread.
unsafe impl<T: Send> Send for MutexAcquire<'_, T> {}
// doesn't have any interesting `&self` methods (only Debug)
unsafe impl<T> Sync for MutexAcquire<'_, T> {}

// Safe to send since we don't track any thread-specific details-- the inner
// lock is essentially spinlock-equivalent (attempt to flip an atomic bool)
unsafe impl<T: Send> Send for MutexGuard<'_, T> {}
unsafe impl<T: Sync> Sync for MutexGuard<'_, T> {}
<|endoftext|>


<commit_before>extern crate chrono;
extern crate clap;
extern crate log;
extern crate env_logger;
extern crate rainyproxy;

use std::env;
use chrono::*;
use clap::{App, Arg};
use log::LogRecord;
use env_logger::LogBuilder;
use rainyproxy::RainyProxy;

fn main() {
    let matches = App::new("rainy")
                      .version("0.0.1")
                      .author("meganehouser")
                      .arg(Arg::with_name("addr")
                               .short("a")
                               .long("address")
                               .value_name("ADDRESS")
                               .help("listen address (ip address : port no)")
                               .required(false))
                      .arg(Arg::with_name("loglevel")
                               .short("l")
                               .long("loglevel")
                               .value_name("LOG_LEVEL")
                               .required(false))
                      .get_matches();

    let addr = matches.value_of("address").unwrap_or("127.0.0.1:8800");
    let mut builder = init_builder(matches.value_of("loglevel").unwrap_or("info"));
    builder.init().unwrap();

    let proxy = RainyProxy::new(&addr);
    proxy.serve();
}

fn init_builder(level: &str) -> LogBuilder {
    let rainy_level = format!("rainy={}", level);
    let format = |record: &LogRecord| {
        format!("[{}] {} {}",
                UTC::now().to_rfc3339(),
                record.level(),
                record.args())
    };

    let mut builder = LogBuilder::new();
    builder.format(format);

    let log_level = match env::var("RUST_LOG") {
        Ok(ref rust_log) => {
            [rust_log.as_str(), rainy_level.as_str()]
                .join(",")
                .to_string()
        }
        Err(_) => rainy_level,
    };

    builder.parse(&log_level);

    builder
}
<commit_msg>modify parameter name of "address"<commit_after>extern crate chrono;
extern crate clap;
extern crate log;
extern crate env_logger;
extern crate rainyproxy;

use std::env;
use chrono::*;
use clap::{App, Arg};
use log::LogRecord;
use env_logger::LogBuilder;
use rainyproxy::RainyProxy;

fn main() {
    let matches = App::new("rainy")
                      .version("0.0.1")
                      .author("meganehouser")
                      .arg(Arg::with_name("addr")
                               .short("a")
                               .long("address")
                               .value_name("ADDRESS")
                               .help("listen address (ip address : port no)")
                               .required(false))
                      .arg(Arg::with_name("loglevel")
                               .short("l")
                               .long("loglevel")
                               .value_name("LOG_LEVEL")
                               .required(false))
                      .get_matches();

    let addr = matches.value_of("addr").unwrap_or("127.0.0.1:8800");
    let mut builder = init_builder(matches.value_of("loglevel").unwrap_or("info"));
    builder.init().unwrap();

    let proxy = RainyProxy::new(&addr);
    proxy.serve();
}

fn init_builder(level: &str) -> LogBuilder {
    let rainy_level = format!("rainy={}", level);
    let format = |record: &LogRecord| {
        format!("[{}] {} {}",
                UTC::now().to_rfc3339(),
                record.level(),
                record.args())
    };

    let mut builder = LogBuilder::new();
    builder.format(format);

    let log_level = match env::var("RUST_LOG") {
        Ok(ref rust_log) => {
            [rust_log.as_str(), rainy_level.as_str()]
                .join(",")
                .to_string()
        }
        Err(_) => rainy_level,
    };

    builder.parse(&log_level);

    builder
}
<|endoftext|>


<commit_before>use std::collections::HashSet;
use mem_map::*;
use cartridge::Cartridge;
use memory::Memory;
use gpu::Gpu;
use device::Device;
use apu::Apu;
use timer::Timer;
use gamepad::Gamepad;

pub struct Interconnect {
    cartridge: Cartridge,
    gpu: Gpu,
    apu: Apu,
    timer: Timer,
    gamepad: Gamepad,

    internal_ram: Memory,
    high_ram: Memory,
    if_register: u8,
    ie_register: u8,

    serial_transfer_data: u8,
    serial_control: u8,

    trigger_watchpoint: bool,
    pub watchpoints: HashSet<u16>,

    dma_source: u16,
    dma_index: u16,
    dma_active: bool,
}

impl Interconnect {
    pub fn new(cartridge: Cartridge) -> Interconnect {
        Interconnect {
            cartridge: cartridge,
            gpu: Gpu::new(),
            apu: Apu::new(),
            timer: Timer::default(),
            gamepad: Gamepad::new(),

            internal_ram: Memory::new(INTERNAL_RAM_LENGTH),
            high_ram: Memory::new(HIGH_RAM_END),

            if_register: 0,
            ie_register: 0,

            serial_transfer_data: 0,
            serial_control: 0,

            watchpoints: HashSet::new(),
            trigger_watchpoint: false,

            dma_source: 0,
            dma_index: 0,
            dma_active: false,
        }
    }

    pub fn read_byte(&self, addr: u16) -> u8 {
        match addr {
            ROM_START...ROM_END => self.cartridge.read_byte(addr - ROM_START),
            VRAM_START...VRAM_END => self.gpu.read_vram(addr - VRAM_START),
            CRAM_START...CRAM_END => self.cartridge.read_byte(addr - ROM_START),
            INTERNAL_RAM_START...INTERNAL_RAM_END => {
                self.internal_ram.read_byte(addr - INTERNAL_RAM_START)
            }
            IRAM_ECHO_START...IRAM_ECHO_END => self.internal_ram.read_byte(addr - IRAM_ECHO_START),
            OAM_START...OAM_END => self.gpu.read_oam(addr - OAM_START),
            0xff00 => self.gamepad.read_reg(),

            // TODO - implement serial port (Link cable)
            0xff01 | 0xff02 => 0,

            0xff04...0xff07 => self.timer.read_reg(addr),
            0xff0f => self.if_register,
            0xff10...0xff3f => self.apu.read_reg(addr),
            0xff40...0xff4f => self.gpu.read_reg(addr),
            HIGH_RAM_START...HIGH_RAM_END => self.high_ram.read_byte(addr - HIGH_RAM_START),
            0xffff => self.ie_register,

            // Unused addresses return 0xff for reads
            _ => 0xff,
        }
    }

    pub fn write_byte(&mut self, addr: u16, val: u8) {
        if self.watchpoints.contains(&addr) {
            self.trigger_watchpoint = true;
        }

        match addr {
            ROM_START...ROM_END => self.cartridge.write(addr - ROM_START, val),
            VRAM_START...VRAM_END => self.gpu.write_vram(addr - VRAM_START, val),
            CRAM_START...CRAM_END => self.cartridge.write(addr - ROM_START, val),
            INTERNAL_RAM_START...INTERNAL_RAM_END => {
                self.internal_ram.write_byte(addr - INTERNAL_RAM_START, val)
            }
            IRAM_ECHO_START...IRAM_ECHO_END => {
                self.internal_ram.write_byte(addr - IRAM_ECHO_START, val)
            }
            HIGH_RAM_START...HIGH_RAM_END => self.high_ram.write_byte(addr - HIGH_RAM_START, val),
            OAM_START...OAM_END => self.gpu.write_oam(addr - OAM_START, val),
            0xff00 => self.gamepad.write_reg(val),

            // TODO - implement serial port (Link cable)
            0xff01 => self.serial_transfer_data = val,
            0xff02 => self.serial_control = val,

            0xff04...0xff07 => self.timer.write_reg(addr, val),
            0xff0f => self.if_register = val,
            0xff10...0xff3f => self.apu.write_reg(addr, val),
            0xff46 => {
                self.dma_source = addr;
                self.dma_index = 0;
                self.dma_active = true;
            }
            0xff40...0xff4b => self.gpu.write_reg(addr, val),
            0xff50 => self.cartridge.disable_boot_rom(),
            0xffff => self.ie_register = val,
            _ => {} // Writes to unused addresses have no effect
        }
    }

    pub fn read_halfword(&self, addr: u16) -> u16 {
        let lsb = self.read_byte(addr);
        let msb = self.read_byte(addr + 1);

        ((msb as u16) << 8) | (lsb as u16)
    }

    pub fn write_halfword(&mut self, addr: u16, val: u16) {
        let lsb = (val & 0xff) as u8;
        let msb = (val >> 8) as u8;

        self.write_byte(addr, lsb);
        self.write_byte(addr + 1, msb);
    }

    pub fn step(&mut self, cycles: u16, device: &mut Device) -> bool {
        if self.dma_active {
            let index = self.dma_index;
            let val = self.read_byte(self.dma_source + self.dma_index);
            self.write_byte(OAM_START + index, val);
            self.dma_index += 1;

            if self.dma_index > 160 {
                self.dma_active = false;
            }
        }

        let gpu_int = self.gpu.step(cycles, device);
        let timer_int = self.timer.step(cycles, device);
        let gamepad_int = self.gamepad.step(cycles, device);

        let gpu_int_flag = gpu_int & self.ie_register;
        self.if_register |= gpu_int_flag;
        let timer_flag = timer_int & self.ie_register;
        self.if_register |= timer_flag;
        let gamepad_flag = gamepad_int & self.ie_register;
        self.if_register |= gamepad_flag;

        let trigger_watchpoint = self.trigger_watchpoint;
        self.trigger_watchpoint = false;
        trigger_watchpoint
    }

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

    pub fn get_height(&self) -> usize {
        self.gpu.get_height()
    }
}
<commit_msg>Fix address for DMA transfer<commit_after>use std::collections::HashSet;
use mem_map::*;
use cartridge::Cartridge;
use memory::Memory;
use gpu::Gpu;
use device::Device;
use apu::Apu;
use timer::Timer;
use gamepad::Gamepad;

pub struct Interconnect {
    cartridge: Cartridge,
    gpu: Gpu,
    apu: Apu,
    timer: Timer,
    gamepad: Gamepad,

    internal_ram: Memory,
    high_ram: Memory,
    if_register: u8,
    ie_register: u8,

    serial_transfer_data: u8,
    serial_control: u8,

    trigger_watchpoint: bool,
    pub watchpoints: HashSet<u16>,

    dma_source: u16,
    dma_index: u16,
    dma_active: bool,
}

impl Interconnect {
    pub fn new(cartridge: Cartridge) -> Interconnect {
        Interconnect {
            cartridge: cartridge,
            gpu: Gpu::new(),
            apu: Apu::new(),
            timer: Timer::default(),
            gamepad: Gamepad::new(),

            internal_ram: Memory::new(INTERNAL_RAM_LENGTH),
            high_ram: Memory::new(HIGH_RAM_END),

            if_register: 0,
            ie_register: 0,

            serial_transfer_data: 0,
            serial_control: 0,

            watchpoints: HashSet::new(),
            trigger_watchpoint: false,

            dma_source: 0,
            dma_index: 0,
            dma_active: false,
        }
    }

    pub fn read_byte(&self, addr: u16) -> u8 {
        match addr {
            ROM_START...ROM_END => self.cartridge.read_byte(addr - ROM_START),
            VRAM_START...VRAM_END => self.gpu.read_vram(addr - VRAM_START),
            CRAM_START...CRAM_END => self.cartridge.read_byte(addr - ROM_START),
            INTERNAL_RAM_START...INTERNAL_RAM_END => {
                self.internal_ram.read_byte(addr - INTERNAL_RAM_START)
            }
            IRAM_ECHO_START...IRAM_ECHO_END => self.internal_ram.read_byte(addr - IRAM_ECHO_START),
            OAM_START...OAM_END => self.gpu.read_oam(addr - OAM_START),
            0xff00 => self.gamepad.read_reg(),

            // TODO - implement serial port (Link cable)
            0xff01 | 0xff02 => 0,

            0xff04...0xff07 => self.timer.read_reg(addr),
            0xff0f => self.if_register,
            0xff10...0xff3f => self.apu.read_reg(addr),
            0xff40...0xff4f => self.gpu.read_reg(addr),
            HIGH_RAM_START...HIGH_RAM_END => self.high_ram.read_byte(addr - HIGH_RAM_START),
            0xffff => self.ie_register,

            // Unused addresses return 0xff for reads
            _ => 0xff,
        }
    }

    pub fn write_byte(&mut self, addr: u16, val: u8) {
        if self.watchpoints.contains(&addr) {
            self.trigger_watchpoint = true;
        }

        match addr {
            ROM_START...ROM_END => self.cartridge.write(addr - ROM_START, val),
            VRAM_START...VRAM_END => self.gpu.write_vram(addr - VRAM_START, val),
            CRAM_START...CRAM_END => self.cartridge.write(addr - ROM_START, val),
            INTERNAL_RAM_START...INTERNAL_RAM_END => {
                self.internal_ram.write_byte(addr - INTERNAL_RAM_START, val)
            }
            IRAM_ECHO_START...IRAM_ECHO_END => {
                self.internal_ram.write_byte(addr - IRAM_ECHO_START, val)
            }
            HIGH_RAM_START...HIGH_RAM_END => self.high_ram.write_byte(addr - HIGH_RAM_START, val),
            OAM_START...OAM_END => self.gpu.write_oam(addr - OAM_START, val),
            0xff00 => self.gamepad.write_reg(val),

            // TODO - implement serial port (Link cable)
            0xff01 => self.serial_transfer_data = val,
            0xff02 => self.serial_control = val,

            0xff04...0xff07 => self.timer.write_reg(addr, val),
            0xff0f => self.if_register = val,
            0xff10...0xff3f => self.apu.write_reg(addr, val),
            0xff46 => {
                self.dma_source = (val as u16) << 8;
                self.dma_index = 0;
                self.dma_active = true;
            }
            0xff40...0xff4b => self.gpu.write_reg(addr, val),
            0xff50 => self.cartridge.disable_boot_rom(),
            0xffff => self.ie_register = val,
            _ => {} // Writes to unused addresses have no effect
        }
    }

    pub fn read_halfword(&self, addr: u16) -> u16 {
        let lsb = self.read_byte(addr);
        let msb = self.read_byte(addr + 1);

        ((msb as u16) << 8) | (lsb as u16)
    }

    pub fn write_halfword(&mut self, addr: u16, val: u16) {
        let lsb = (val & 0xff) as u8;
        let msb = (val >> 8) as u8;

        self.write_byte(addr, lsb);
        self.write_byte(addr + 1, msb);
    }

    pub fn step(&mut self, cycles: u16, device: &mut Device) -> bool {
        if self.dma_active {
            let index = self.dma_index;
            let val = self.read_byte(self.dma_source + index);
            self.write_byte(OAM_START + index, val);
            self.dma_index += 1;

            if self.dma_index >= 160 {
                self.dma_active = false;
            }
        }

        let gpu_int = self.gpu.step(cycles, device);
        let timer_int = self.timer.step(cycles, device);
        let gamepad_int = self.gamepad.step(cycles, device);

        let gpu_int_flag = gpu_int & self.ie_register;
        self.if_register |= gpu_int_flag;
        let timer_flag = timer_int & self.ie_register;
        self.if_register |= timer_flag;
        let gamepad_flag = gamepad_int & self.ie_register;
        self.if_register |= gamepad_flag;

        let trigger_watchpoint = self.trigger_watchpoint;
        self.trigger_watchpoint = false;
        trigger_watchpoint
    }

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

    pub fn get_height(&self) -> usize {
        self.gpu.get_height()
    }
}
<|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/. */

use eutil::slice_to_str;
use libc::{self, size_t, c_int, c_ushort, c_void};
use libc::types::os::arch::c95::wchar_t;
use std::char;
use std::cmp::Ordering;
use std::mem;
use std::ptr;
use std::slice;
use std::string;
use types::{cef_string_utf16_t, cef_string_utf8_t, cef_string_wide_t};
use types::{cef_string_userfree_utf16_t, cef_string_userfree_utf8_t, cef_string_userfree_wide_t};

//cef_string

#[no_mangle]
#[allow(private_no_mangle_fns)]
extern "C" fn string_wide_dtor(str: *mut wchar_t) {
    unsafe {
        libc::free(str as *mut c_void)
    }
}

#[no_mangle]
#[allow(private_no_mangle_fns)]
extern "C" fn string_utf8_dtor(str: *mut u8) {
    unsafe {
        libc::free(str as *mut c_void)
    }
}

#[no_mangle]
#[allow(private_no_mangle_fns)]
extern "C" fn string_utf16_dtor(str: *mut c_ushort) {
    unsafe {
        libc::free(str as *mut c_void)
    }
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_wide_free(cs: *mut cef_string_userfree_wide_t) {
    cef_string_wide_clear(cs);
    unsafe {
        libc::free(cs as *mut c_void)
    }
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_utf8_free(cs: *mut cef_string_userfree_utf8_t) {
    unsafe {
        cef_string_utf8_clear(cs);
        libc::free(cs as *mut c_void)
    }
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_utf16_free(cs: cef_string_userfree_utf16_t) {
    unsafe {
        cef_string_utf16_clear(cs);
        libc::free(cs as *mut c_void)
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_clear(cs: *mut cef_string_utf8_t) {
    unsafe {
        (*cs).dtor.map(|dtor| dtor((*cs).str));
        (*cs).length = 0;
        (*cs).str = 0 as *mut u8;
        (*cs).dtor = None;
    }
}

#[inline(never)]
#[no_mangle]
pub extern "C" fn cef_string_userfree_utf8_alloc() -> *mut cef_string_utf8_t {
    unsafe {
        libc::calloc(1, mem::size_of::<cef_string_utf8_t>() as u64) as *mut cef_string_utf8_t
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_set(src: *const u8, src_len: size_t, output: *mut cef_string_utf8_t, copy: c_int) -> c_int {
    cef_string_utf8_clear(output);
    unsafe {
       if copy != 0 {
           if !src.is_null() && src_len > 0 {
             (*output).str = libc::calloc(1, src_len + 1) as *mut u8;
             if (*output).str.is_null() {
                 return 0;
             }

             ptr::copy(src, (*output).str, src_len as usize);
             (*output).length = src_len;
             (*output).dtor = Some(string_utf8_dtor as extern "C" fn(*mut u8));
           }
       } else {
         (*output).str = src as *mut _;
         (*output).length = src_len;
         (*output).dtor = None;
       }
    }
    return 1;
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_cmp(a: *const cef_string_utf8_t, b: *const cef_string_utf8_t) -> c_int {
    unsafe {
        let astr = (*a).str as *const u8;
        let bstr = (*b).str as *const u8;
        let astr = slice::from_raw_parts(astr, (*a).length as usize);
        let bstr = slice::from_raw_parts(bstr, (*b).length as usize);
        match astr.cmp(bstr) {
            Ordering::Less => -1,
            Ordering::Equal => 0,
            Ordering::Greater => 1
        }
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_to_utf16(src: *const u8, src_len: size_t, output: *mut cef_string_utf16_t) -> c_int {
    slice_to_str(src, src_len as usize, |result| {
        let conv = result.utf16_units().collect::<Vec<u16>>();
        cef_string_utf16_set(conv.as_ptr(), conv.len() as size_t, output, 1);
        1
    })
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_to_utf8(src: *const u16, src_len: size_t, output: *mut cef_string_utf8_t) -> c_int {
    unsafe {
        let ustr = slice::from_raw_parts(src, src_len as usize);
        match string::String::from_utf16(ustr) {
            Ok(str) => {
                cef_string_utf8_set(str.as_bytes().as_ptr(), str.len() as size_t, output, 1);
                1 as c_int
            },
            _ =>  0 as c_int
        }
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_clear(cs: *mut cef_string_utf16_t) {
    unsafe {
        (*cs).dtor.map(|dtor| dtor((*cs).str));
        (*cs).length = 0;
        (*cs).str = 0 as *mut c_ushort;
        (*cs).dtor = None;
    }
}

#[inline(never)]
#[no_mangle]
pub extern "C" fn cef_string_userfree_utf16_alloc() -> *mut cef_string_utf16_t {
    unsafe {
        libc::calloc(1, mem::size_of::<cef_string_utf16_t>() as u64) as *mut cef_string_utf16_t
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_set(src: *const c_ushort, src_len: size_t, output: *mut cef_string_utf16_t, copy: c_int) -> c_int {
    cef_string_utf16_clear(output);
    unsafe {
       if copy != 0 {
           if !src.is_null() && src_len > 0 {
             (*output).str = libc::calloc(1, (src_len + 1) * mem::size_of::<c_ushort>() as u64) as
                 *mut u16;
             if (*output).str.is_null() {
                 return 0;
             }

             ptr::copy(src, (*output).str, src_len as usize);
             (*output).length = src_len;
             (*output).dtor = Some(string_utf16_dtor as extern "C" fn(*mut c_ushort));
           }
       } else {
         (*output).str = src as *mut _;
         (*output).length = src_len;
         (*output).dtor = None;
       }
    }
    return 1;
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_cmp(a: *const cef_string_utf16_t, b: *const cef_string_utf16_t) -> c_int {
    unsafe {
        let astr = (*a).str as *const _;
        let bstr = (*b).str as *const _;
        let astr: &[u16] = slice::from_raw_parts(astr, (*a).length as usize);
        let bstr: &[u16] = slice::from_raw_parts(bstr, (*b).length as usize);
        match astr.cmp(bstr) {
            Ordering::Less => -1,
            Ordering::Equal => 0,
            Ordering::Greater => 1
        }
    }
}

#[no_mangle]
pub extern "C" fn cef_string_wide_clear(cs: *mut cef_string_wide_t) {
    unsafe {
        (*cs).dtor.map(|dtor| dtor((*cs).str));
        (*cs).length = 0;
        (*cs).str = 0 as *mut wchar_t;
        (*cs).dtor = None;
    }
}

#[inline(never)]
#[no_mangle]
pub extern "C" fn cef_string_userfree_wide_alloc() -> *mut cef_string_wide_t {
    unsafe {
        libc::calloc(1, mem::size_of::<cef_string_wide_t>() as u64) as *mut cef_string_wide_t
    }
}

#[no_mangle]
pub extern "C" fn cef_string_wide_set(src: *const wchar_t, src_len: size_t, output: *mut cef_string_wide_t, copy: c_int) -> c_int {
    cef_string_wide_clear(output);
    unsafe {
       if copy != 0 {
           if !src.is_null() && src_len > 0 {
             (*output).str = libc::calloc(1, (src_len + 1) * mem::size_of::<wchar_t>() as u64) as
                 *mut wchar_t;
             if (*output).str.is_null() {
                 return 0;
             }

             ptr::copy(src, (*output).str, src_len as usize);
             (*output).length = src_len;
             (*output).dtor = Some(string_wide_dtor as extern "C" fn(*mut wchar_t));
           }
       } else {
         (*output).str = src as *mut _;
         (*output).length = src_len;
         (*output).dtor = None;
       }
    }
    return 1;
}

#[no_mangle]
pub extern "C" fn cef_string_wide_cmp(a: *const cef_string_wide_t, b: *const cef_string_wide_t) -> c_int {
    unsafe {
        let astr = (*a).str as *const wchar_t;
        let bstr = (*b).str as *const wchar_t;
        let astr = slice::from_raw_parts(astr, (*a).length as usize);
        let bstr = slice::from_raw_parts(bstr, (*b).length as usize);
        match astr.cmp(bstr) {
            Ordering::Less => -1,
            Ordering::Equal => 0,
            Ordering::Greater => 1
        }
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_to_wide(src: *const u8, src_len: size_t, output: *mut cef_string_wide_t) -> c_int {
    if mem::size_of::<wchar_t>() == mem::size_of::<u16>() {
         return cef_string_utf8_to_utf16(src, src_len, output as *mut cef_string_utf16_t);
    }
    slice_to_str(src, src_len as usize, |result| {
        let conv = result.chars().map(|c| c as u32).collect::<Vec<u32>>();
        cef_string_wide_set(conv.as_ptr() as *const wchar_t, conv.len() as size_t, output, 1)
    })
}

#[no_mangle]
pub extern "C" fn cef_string_wide_to_utf8(src: *const wchar_t, src_len: size_t, output: *mut cef_string_utf8_t) -> c_int {
    if mem::size_of::<wchar_t>() == mem::size_of::<u16>() {
         return cef_string_utf16_to_utf8(src as *const u16, src_len, output);
    }
    unsafe {
        let ustr = slice::from_raw_parts(src, src_len as usize);
        let conv = ustr.iter().map(|&c| char::from_u32(c as u32).unwrap_or('\u{FFFD}')).collect::<String>();
        cef_string_utf8_set(conv.as_bytes().as_ptr(), conv.len() as size_t, output, 1)
    }
}

#[no_mangle]
pub extern "C" fn cef_string_ascii_to_utf16(src: *const u8, src_len: size_t, output: *mut cef_string_utf16_t) -> c_int {
    slice_to_str(src, src_len as usize, |result| {
        let conv = result.utf16_units().collect::<Vec<u16>>();
        cef_string_utf16_set(conv.as_ptr(), conv.len() as size_t, output, 1)
    })
}

#[no_mangle]
pub extern "C" fn cef_string_ascii_to_wide(src: *const u8, src_len: size_t, output: *mut cef_string_wide_t) -> c_int {
    unsafe {
        let ustr = slice::from_raw_parts(src, src_len as usize);
        let conv = ustr.iter().map(|&c| c as u8).collect::<Vec<u8>>();
        cef_string_wide_set(conv.as_ptr() as *const wchar_t, conv.len() as size_t, output, 1)
    }
}

pub fn empty_utf16_string() -> cef_string_utf16_t {
    cef_string_utf16_t {
        str: ptr::null_mut(),
        length: 0,
        dtor: None,
    }
}

pub fn string_to_userfree_string(string: cef_string_utf16_t) -> cef_string_userfree_utf16_t {
    unsafe {
        let allocation = libc::malloc(mem::size_of::<cef_string_utf16_t>() as size_t)
            as cef_string_userfree_utf16_t;
        ptr::write(allocation, string);
        allocation
    }
}

pub fn empty_utf16_userfree_string() -> cef_string_userfree_utf16_t {
    string_to_userfree_string(empty_utf16_string())
}

<commit_msg>Improve indentation in CEF strings.<commit_after>/* 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/. */

use eutil::slice_to_str;
use libc::{self, size_t, c_int, c_ushort, c_void};
use libc::types::os::arch::c95::wchar_t;
use std::char;
use std::cmp::Ordering;
use std::mem;
use std::ptr;
use std::slice;
use std::string;
use types::{cef_string_utf16_t, cef_string_utf8_t, cef_string_wide_t};
use types::{cef_string_userfree_utf16_t, cef_string_userfree_utf8_t, cef_string_userfree_wide_t};

//cef_string

#[no_mangle]
#[allow(private_no_mangle_fns)]
extern "C" fn string_wide_dtor(str: *mut wchar_t) {
    unsafe {
        libc::free(str as *mut c_void)
    }
}

#[no_mangle]
#[allow(private_no_mangle_fns)]
extern "C" fn string_utf8_dtor(str: *mut u8) {
    unsafe {
        libc::free(str as *mut c_void)
    }
}

#[no_mangle]
#[allow(private_no_mangle_fns)]
extern "C" fn string_utf16_dtor(str: *mut c_ushort) {
    unsafe {
        libc::free(str as *mut c_void)
    }
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_wide_free(cs: *mut cef_string_userfree_wide_t) {
    cef_string_wide_clear(cs);
    unsafe {
        libc::free(cs as *mut c_void)
    }
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_utf8_free(cs: *mut cef_string_userfree_utf8_t) {
    unsafe {
        cef_string_utf8_clear(cs);
        libc::free(cs as *mut c_void)
    }
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_utf16_free(cs: cef_string_userfree_utf16_t) {
    unsafe {
        cef_string_utf16_clear(cs);
        libc::free(cs as *mut c_void)
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_clear(cs: *mut cef_string_utf8_t) {
    unsafe {
        (*cs).dtor.map(|dtor| dtor((*cs).str));
        (*cs).length = 0;
        (*cs).str = 0 as *mut u8;
        (*cs).dtor = None;
    }
}

#[inline(never)]
#[no_mangle]
pub extern "C" fn cef_string_userfree_utf8_alloc() -> *mut cef_string_utf8_t {
    unsafe {
        libc::calloc(1, mem::size_of::<cef_string_utf8_t>() as u64) as *mut cef_string_utf8_t
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_set(src: *const u8, src_len: size_t, output: *mut cef_string_utf8_t, copy: c_int) -> c_int {
    cef_string_utf8_clear(output);
    unsafe {
       if copy != 0 {
           if !src.is_null() && src_len > 0 {
               (*output).str = libc::calloc(1, src_len + 1) as *mut u8;
               if (*output).str.is_null() {
                   return 0;
               }

               ptr::copy(src, (*output).str, src_len as usize);
               (*output).length = src_len;
               (*output).dtor = Some(string_utf8_dtor as extern "C" fn(*mut u8));
           }
       } else {
           (*output).str = src as *mut _;
           (*output).length = src_len;
           (*output).dtor = None;
       }
    }
    return 1;
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_cmp(a: *const cef_string_utf8_t, b: *const cef_string_utf8_t) -> c_int {
    unsafe {
        let astr = (*a).str as *const u8;
        let bstr = (*b).str as *const u8;
        let astr = slice::from_raw_parts(astr, (*a).length as usize);
        let bstr = slice::from_raw_parts(bstr, (*b).length as usize);
        match astr.cmp(bstr) {
            Ordering::Less => -1,
            Ordering::Equal => 0,
            Ordering::Greater => 1
        }
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_to_utf16(src: *const u8, src_len: size_t, output: *mut cef_string_utf16_t) -> c_int {
    slice_to_str(src, src_len as usize, |result| {
        let conv = result.utf16_units().collect::<Vec<u16>>();
        cef_string_utf16_set(conv.as_ptr(), conv.len() as size_t, output, 1);
        1
    })
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_to_utf8(src: *const u16, src_len: size_t, output: *mut cef_string_utf8_t) -> c_int {
    unsafe {
        let ustr = slice::from_raw_parts(src, src_len as usize);
        match string::String::from_utf16(ustr) {
            Ok(str) => {
                cef_string_utf8_set(str.as_bytes().as_ptr(), str.len() as size_t, output, 1);
                1 as c_int
            },
            _ =>  0 as c_int
        }
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_clear(cs: *mut cef_string_utf16_t) {
    unsafe {
        (*cs).dtor.map(|dtor| dtor((*cs).str));
        (*cs).length = 0;
        (*cs).str = 0 as *mut c_ushort;
        (*cs).dtor = None;
    }
}

#[inline(never)]
#[no_mangle]
pub extern "C" fn cef_string_userfree_utf16_alloc() -> *mut cef_string_utf16_t {
    unsafe {
        libc::calloc(1, mem::size_of::<cef_string_utf16_t>() as u64) as *mut cef_string_utf16_t
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_set(src: *const c_ushort, src_len: size_t, output: *mut cef_string_utf16_t, copy: c_int) -> c_int {
    cef_string_utf16_clear(output);
    unsafe {
       if copy != 0 {
           if !src.is_null() && src_len > 0 {
               (*output).str = libc::calloc(1, (src_len + 1) * mem::size_of::<c_ushort>() as u64) as
                   *mut u16;
               if (*output).str.is_null() {
                   return 0;
               }

               ptr::copy(src, (*output).str, src_len as usize);
               (*output).length = src_len;
               (*output).dtor = Some(string_utf16_dtor as extern "C" fn(*mut c_ushort));
           }
       } else {
           (*output).str = src as *mut _;
           (*output).length = src_len;
           (*output).dtor = None;
       }
    }
    return 1;
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_cmp(a: *const cef_string_utf16_t, b: *const cef_string_utf16_t) -> c_int {
    unsafe {
        let astr = (*a).str as *const _;
        let bstr = (*b).str as *const _;
        let astr: &[u16] = slice::from_raw_parts(astr, (*a).length as usize);
        let bstr: &[u16] = slice::from_raw_parts(bstr, (*b).length as usize);
        match astr.cmp(bstr) {
            Ordering::Less => -1,
            Ordering::Equal => 0,
            Ordering::Greater => 1
        }
    }
}

#[no_mangle]
pub extern "C" fn cef_string_wide_clear(cs: *mut cef_string_wide_t) {
    unsafe {
        (*cs).dtor.map(|dtor| dtor((*cs).str));
        (*cs).length = 0;
        (*cs).str = 0 as *mut wchar_t;
        (*cs).dtor = None;
    }
}

#[inline(never)]
#[no_mangle]
pub extern "C" fn cef_string_userfree_wide_alloc() -> *mut cef_string_wide_t {
    unsafe {
        libc::calloc(1, mem::size_of::<cef_string_wide_t>() as u64) as *mut cef_string_wide_t
    }
}

#[no_mangle]
pub extern "C" fn cef_string_wide_set(src: *const wchar_t, src_len: size_t, output: *mut cef_string_wide_t, copy: c_int) -> c_int {
    cef_string_wide_clear(output);
    unsafe {
       if copy != 0 {
           if !src.is_null() && src_len > 0 {
               (*output).str = libc::calloc(1, (src_len + 1) * mem::size_of::<wchar_t>() as u64) as
                   *mut wchar_t;
               if (*output).str.is_null() {
                   return 0;
               }

               ptr::copy(src, (*output).str, src_len as usize);
               (*output).length = src_len;
               (*output).dtor = Some(string_wide_dtor as extern "C" fn(*mut wchar_t));
           }
       } else {
           (*output).str = src as *mut _;
           (*output).length = src_len;
           (*output).dtor = None;
       }
    }
    return 1;
}

#[no_mangle]
pub extern "C" fn cef_string_wide_cmp(a: *const cef_string_wide_t, b: *const cef_string_wide_t) -> c_int {
    unsafe {
        let astr = (*a).str as *const wchar_t;
        let bstr = (*b).str as *const wchar_t;
        let astr = slice::from_raw_parts(astr, (*a).length as usize);
        let bstr = slice::from_raw_parts(bstr, (*b).length as usize);
        match astr.cmp(bstr) {
            Ordering::Less => -1,
            Ordering::Equal => 0,
            Ordering::Greater => 1
        }
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_to_wide(src: *const u8, src_len: size_t, output: *mut cef_string_wide_t) -> c_int {
    if mem::size_of::<wchar_t>() == mem::size_of::<u16>() {
         return cef_string_utf8_to_utf16(src, src_len, output as *mut cef_string_utf16_t);
    }
    slice_to_str(src, src_len as usize, |result| {
        let conv = result.chars().map(|c| c as u32).collect::<Vec<u32>>();
        cef_string_wide_set(conv.as_ptr() as *const wchar_t, conv.len() as size_t, output, 1)
    })
}

#[no_mangle]
pub extern "C" fn cef_string_wide_to_utf8(src: *const wchar_t, src_len: size_t, output: *mut cef_string_utf8_t) -> c_int {
    if mem::size_of::<wchar_t>() == mem::size_of::<u16>() {
         return cef_string_utf16_to_utf8(src as *const u16, src_len, output);
    }
    unsafe {
        let ustr = slice::from_raw_parts(src, src_len as usize);
        let conv = ustr.iter().map(|&c| char::from_u32(c as u32).unwrap_or('\u{FFFD}')).collect::<String>();
        cef_string_utf8_set(conv.as_bytes().as_ptr(), conv.len() as size_t, output, 1)
    }
}

#[no_mangle]
pub extern "C" fn cef_string_ascii_to_utf16(src: *const u8, src_len: size_t, output: *mut cef_string_utf16_t) -> c_int {
    slice_to_str(src, src_len as usize, |result| {
        let conv = result.utf16_units().collect::<Vec<u16>>();
        cef_string_utf16_set(conv.as_ptr(), conv.len() as size_t, output, 1)
    })
}

#[no_mangle]
pub extern "C" fn cef_string_ascii_to_wide(src: *const u8, src_len: size_t, output: *mut cef_string_wide_t) -> c_int {
    unsafe {
        let ustr = slice::from_raw_parts(src, src_len as usize);
        let conv = ustr.iter().map(|&c| c as u8).collect::<Vec<u8>>();
        cef_string_wide_set(conv.as_ptr() as *const wchar_t, conv.len() as size_t, output, 1)
    }
}

pub fn empty_utf16_string() -> cef_string_utf16_t {
    cef_string_utf16_t {
        str: ptr::null_mut(),
        length: 0,
        dtor: None,
    }
}

pub fn string_to_userfree_string(string: cef_string_utf16_t) -> cef_string_userfree_utf16_t {
    unsafe {
        let allocation = libc::malloc(mem::size_of::<cef_string_utf16_t>() as size_t)
            as cef_string_userfree_utf16_t;
        ptr::write(allocation, string);
        allocation
    }
}

pub fn empty_utf16_userfree_string() -> cef_string_userfree_utf16_t {
    string_to_userfree_string(empty_utf16_string())
}

<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

extern crate glsl_to_spirv;

#[test]
fn test1() {
    let shader = r#"
#version 330

out vec4 f_color;

void main() {
    f_color = vec4(1.0);
}
"#;

    glsl_to_spirv::compile(shader, glsl_to_spirv::ShaderType::Fragment).unwrap();
}
<commit_msg>Fix glslang test<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

extern crate glsl_to_spirv;

#[test]
fn test1() {
    let shader = r#"
#version 330

layout(location = 0) out vec4 f_color;

void main() {
    f_color = vec4(1.0);
}
"#;

    glsl_to_spirv::compile(shader, glsl_to_spirv::ShaderType::Fragment).unwrap();
}
<|endoftext|>


<commit_before>
struct CircularBuffer<T : Copy> {
  seqno : usize,
  data  : Vec<T>,
}

struct CircularBufferIterator<'a, T: 'a + Copy> {
  buffer    : &'a CircularBuffer<T>,
  position  : usize,
  limit     : usize,
}

impl <T : Copy> CircularBuffer<T> {
  fn new(size : usize, default_value : T) -> CircularBuffer<T> {

    if size == 0 { panic!("size cannot be zero"); }

    let mut ret = CircularBuffer {
      seqno : 0,
      data  : vec![],
    };

    // make sure there is enough place and fill it with the
    // default value
    ret.data.resize(size, default_value);
    ret
  }

  fn min_pos(&self) -> usize {
    if self.seqno < self.data.len() {
      0
    } else {
      (self.seqno - self.data.len()) as usize
    }
  }

  fn iter(&self) -> CircularBufferIterator<T> {
    CircularBufferIterator{
      buffer: self,
      position: self.min_pos(),
      limit: self.seqno
     }
  }

  fn put<F>(&mut self, setter: F) -> usize
    where F : FnMut(&mut T)
  {
    // calculate where to put the data
    let pos = self.seqno % self.data.len();

    // get a reference to the data
    let mut opt : Option<&mut T> = self.data.get_mut(pos);

    let mut setter = setter;

    // make sure the index worked
    match opt.as_mut() {
      Some(v) => setter(v),
      None    => { panic!("out of bounds {}", pos); }
    }

    // increase sequence number
    self.seqno += 1;
    self.seqno
  }

  fn get(&self, at: &usize) -> (Option<&T>, usize) {

    let min_pos : usize = if self.seqno < self.data.len() {
      0
    } else {
      (self.seqno - self.data.len()) as usize
    };

    if *at < min_pos      { return (Option::None, min_pos);    }
    if *at >= self.seqno  { return (Option::None, self.seqno); }

    let pos = *at % self.data.len();

    (self.data.get(pos), *at+1)
  }

  fn get_range<F>(&self, from: &usize, to: &usize, getter: F) -> usize
    where F : FnMut(&T)
  {
    if from > to { panic!("from:{} > to:{}", from, to); }

    // figure out the minimum and maximum position
    let min_pos : usize = if self.seqno < self.data.len() {
      0
    } else {
      (self.seqno - self.data.len()) as usize
    };

    let max_pos : usize = self.seqno;

    // cannot return past (overwritten) elements
    if *to < min_pos { return min_pos; }

    // cannot return future elements
    if *from >= max_pos { return max_pos; }

    // constrain start to min_pos
    let start : usize = if *from > min_pos {
      *from
    } else {
      min_pos
    };

    // constrain end to max_pos
    let end : usize = if *to > max_pos {
      max_pos
    } else {
      *to
    };

    let start_pos   = start % self.data.len();
    let end_pos     = end % self.data.len();
    let mut getter  = getter;

    let mut get_range_fn = |from_pos: usize, to_pos: usize| {
      for i in from_pos..to_pos {
        let act_value : Option<&T> = self.data.get(i);
        match act_value {
          Some(v) => { getter(v); }
          None => { panic!("index is out of range i={}",i); }
        };
      }
    };

    if end_pos > start_pos {
      // one contigous range
      get_range_fn(start_pos, end_pos);
    } else {
      // range split into two
      get_range_fn(start_pos, self.data.len());
      get_range_fn(0, end_pos);
    }

    end
  }
}

impl <'_, T: '_ + Copy> Iterator for CircularBufferIterator<'_, T> {
  type Item = T;

  fn next(&mut self) -> Option<T> {
    if self.position >= self.limit {
      None
    } else {
      let at = self.position % self.buffer.data.len();
      match self.buffer.data.get(at) {
        Some(v) => Some(*v),
        None => None
      }
    }
  }
}

pub fn tests() {
  let mut x = CircularBuffer::new(4, 0 as i32);
  x.put(|v| *v = 1);
  let mut y : i32 = 2;
  x.put(|v| { *v = y; y += 1; });
  x.put(|v| { *v = y; y += 1; });
  x.put(|v| { *v = y; y += 1; });
  x.put(|v| { *v = y; y += 1; });

  let ret = x.get_range( &0, &100, |val : &i32| {
    println!("A: {}", *val);
  });
  println!("ret={} min_pos={}", ret,x.min_pos());

  let it = x.iter();
  for i in it {
    println!("B: {}", i);
  }

  let count  = x.iter().count();
  let max    = x.iter().max();
  let first  = x.iter().take(1).last();
  let last   = x.iter().last();

  println!("count={} max={} first={} last={}",
    count,
    max.unwrap(),
    first.unwrap(),
    last.unwrap());
}

#[test]
#[should_panic]
fn create_zero_sized() {
  let _x = CircularBuffer::new(0, 0 as i32);
}

#[test]
fn create_non_zero_sized() {
  let _x = CircularBuffer::new(1, 0 as i32);
}

#[test]
fn can_put() {
  let mut x = CircularBuffer::new(1, 0 as i32);
  x.put(|v| *v = 1);
}

#[test]
fn can_put_with_env() {
  let mut x = CircularBuffer::new(1, 0 as i32);
  let mut y = 0;
  let my_fn = |v : &mut i32| {
    *v = y;
    y += 1;
  };
  x.put(&my_fn);
  x.put(&my_fn);
  x.put(&my_fn);
}

#[test]
fn can_put_with_env2() {
  let mut x = CircularBuffer::new(1, 0 as i32);
  let mut y = 0;
  x.put(|v| { *v = y; y += 1; });
}
<commit_msg>second iterator<commit_after>
struct CircularBuffer<T : Copy> {
  seqno : usize,
  data  : Vec<T>,
}

struct CircularBufferIterator<'a, T: 'a + Copy> {
  buffer    : &'a CircularBuffer<T>,
  position  : usize,
  limit     : usize,
}

impl <T : Copy> CircularBuffer<T> {
  fn new(size : usize, default_value : T) -> CircularBuffer<T> {

    if size == 0 { panic!("size cannot be zero"); }

    let mut ret = CircularBuffer {
      seqno : 0,
      data  : vec![],
    };

    // make sure there is enough place and fill it with the
    // default value
    ret.data.resize(size, default_value);
    ret
  }

  fn min_pos(&self) -> usize {
    if self.seqno < self.data.len() {
      0
    } else {
      (self.seqno - self.data.len()) as usize
    }
  }

  fn iter(&self) -> CircularBufferIterator<T> {
    CircularBufferIterator{
      buffer: self,
      position: self.min_pos(),
      limit: self.seqno
     }
  }

  fn put<F>(&mut self, setter: F) -> usize
    where F : FnMut(&mut T)
  {
    // calculate where to put the data
    let pos = self.seqno % self.data.len();

    // get a reference to the data
    let mut opt : Option<&mut T> = self.data.get_mut(pos);

    let mut setter = setter;

    // make sure the index worked
    match opt.as_mut() {
      Some(v) => setter(v),
      None    => { panic!("out of bounds {}", pos); }
    }

    // increase sequence number
    self.seqno += 1;
    self.seqno
  }
}

impl <'_, T: '_ + Copy> Iterator for CircularBufferIterator<'_, T> {
  type Item = T;

  fn next(&mut self) -> Option<T> {
    if self.position >= self.limit {
      None
    } else {
      let at = self.position % self.buffer.data.len();
      self.position += 1;
      match self.buffer.data.get(at) {
        Some(v) => Some(*v),
        None => None
      }
    }
  }
}

pub fn tests() {
  let mut x = CircularBuffer::new(4, 0 as i32);
  x.put(|v| *v = 1);
  let mut y : i32 = 2;
  x.put(|v| { *v = y; y += 1; });
  x.put(|v| { *v = y; y += 1; });
  x.put(|v| { *v = y; y += 1; });
  x.put(|v| { *v = y; y += 1; });

  let it = x.iter();
  for i in it {
    println!("B: {}", i);
  }

  let count  = x.iter().count();
  let max    = x.iter().max();
  let first  = x.iter().take(1).last();
  let last   = x.iter().last();

  println!("count={} max={} first={} last={}",
    count,
    max.unwrap(),
    first.unwrap(),
    last.unwrap());
}

#[test]
#[should_panic]
fn create_zero_sized() {
  let _x = CircularBuffer::new(0, 0 as i32);
}

#[test]
fn create_non_zero_sized() {
  let _x = CircularBuffer::new(1, 0 as i32);
}

#[test]
fn can_put() {
  let mut x = CircularBuffer::new(1, 0 as i32);
  x.put(|v| *v = 1);
}

#[test]
fn can_put_with_env() {
  let mut x = CircularBuffer::new(1, 0 as i32);
  let mut y = 0;
  let my_fn = |v : &mut i32| {
    *v = y;
    y += 1;
  };
  x.put(&my_fn);
  x.put(&my_fn);
  x.put(&my_fn);
}

#[test]
fn can_put_with_env2() {
  let mut x = CircularBuffer::new(1, 0 as i32);
  let mut y = 0;
  x.put(|v| { *v = y; y += 1; });
}
<|endoftext|>


<commit_before>use std::iter::Peekable;

use ::opcodes::OpCode;
use assembler::token::Token;

#[derive(Debug, PartialEq)]
pub struct ParserError {
    message: String,
}

impl ParserError {
    fn expected_instruction(line: u32) -> ParserError {
        ParserError::from(format!("Instruction expected. Line {}", line))
    }

    fn invalid_opcode_addressing_mode_combination(line: u32) -> ParserError {
        ParserError::from(format!("Invalid addressing mode for opcode. Line {}", line))
    }

    fn unexpected_eol(line: u32) -> ParserError {
        ParserError::from(format!("Unexpected end of line. Line {}", line))
    }
}

impl From<String> for ParserError {
    fn from(error: String) -> ParserError {
        ParserError { message: error }
    }
}

impl<'a> From<&'a str> for ParserError {
    fn from(error: &str) -> ParserError {
        ParserError { message: error.into() }
    }
}

pub struct Parser {
    tokens: Vec<Vec<Token>>,
    line: u32,
}

/// Parser processes a list of 6502 Assembly tokens
impl Parser {
    pub fn new(tokens: Vec<Vec<Token>>) -> Parser {
        Parser {
            tokens: tokens,
            line: 0,
        }
    }

    /// Processes its tokens and either returns them to the caller
    /// or produces an error
    pub fn parse(&mut self) -> Result<Vec<Vec<Token>>, ParserError> {
        for line in &self.tokens {
            self.line += 1;
            let mut peeker = line.iter().peekable();
            // Check what starts the line
            let token = peeker.peek().unwrap().clone();

            match *token {
                Token::Label(_) => {
                    // if its a label, consume it and move on
                    peeker.next();
                    if let None = peeker.peek() {
                        return Err(ParserError::expected_instruction(self.line));
                    }
                    let next = *peeker.peek().unwrap();
                    if let &Token::OpCode(_) = next {
                        Self::handle_opcode(&mut peeker, &&next, self.line)?;
                    } else {
                        return Err(ParserError::expected_instruction(self.line));
                    }
                }
                _ => (),
            }
        }
        Ok(self.tokens.iter().map(|v| v.clone()).collect())
    }

    fn handle_opcode<'a, I>(mut peeker: &mut Peekable<I>,
                            token: &Token,
                            line: u32)
                            -> Result<(), ParserError>
        where I: Iterator<Item = &'a Token>
    {
        if let None = peeker.peek() {
            Err(ParserError::unexpected_eol(line))
        } else {
            peeker.next();
            let next = *peeker.peek().unwrap();
            let addressing_mode = next.to_addressing_mode();
            if let &Token::OpCode(ref mnemonic) = token {
                if let Some(opcode) = OpCode::from_mnemonic_and_addressing_mode(mnemonic.clone(),
                                                                                addressing_mode) {
                    Ok(())
                } else {
                    Err(ParserError::invalid_opcode_addressing_mode_combination(line))
                }
            } else {
                Err(ParserError::expected_instruction(line))
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use ::assembler::token::{ImmediateBase, Token};

    #[test]
    fn errors_on_multiple_labels() {
        let mut parser = Parser::new(vec![vec![Token::Label("MAIN".into()),
                                               Token::Label("METHOD".into()),
                                               Token::OpCode("LDA".into()),
                                               Token::Immediate("10".into(),
                                                                ImmediateBase::Base16)]]);

        assert_eq!(Err(ParserError::expected_instruction(1)), parser.parse());
    }

    #[test]
    fn does_not_error_on_single_label() {
        let mut parser = Parser::new(vec![vec![Token::Label("MAIN".into()),
                                               Token::OpCode("LDA".into()),
                                               Token::Immediate("10".into(),
                                                                ImmediateBase::Base16)]]);

        assert_eq!(&[Token::Label("MAIN".into()),
                     Token::OpCode("LDA".into()),
                     Token::Immediate("10".into(), ImmediateBase::Base16)],
                   &parser.parse().unwrap()[0][..]);
    }

    #[test]
    fn can_detect_invalid_addressing_modes() {
        let mut parser = Parser::new(vec![vec![Token::Label("MAIN".into()),
                                               Token::OpCode("LDX".into()),
                                               Token::IndirectY("10".into())]]);

        assert_eq!(Err(ParserError::invalid_opcode_addressing_mode_combination(1)),
                   parser.parse());
    }

    #[test]
    fn does_not_error_on_valid_addressing_modes() {
        let mut parser = Parser::new(vec![vec![Token::Label("MAIN".into()),
                                               Token::OpCode("LDA".into()),
                                               Token::IndirectY("10".into())]]);

        let result = parser.parse().unwrap();
        assert_eq!(&[Token::Label("MAIN".into()),
                     Token::OpCode("LDA".into()),
                     Token::IndirectY("10".into())],
                   &result[0][..]);
    }
}<commit_msg>Add single label line support<commit_after>use std::iter::Peekable;

use ::opcodes::OpCode;
use assembler::token::Token;

#[derive(Debug, PartialEq)]
pub struct ParserError {
    message: String,
}

impl ParserError {
    fn expected_instruction(line: u32) -> ParserError {
        ParserError::from(format!("Instruction expected. Line {}", line))
    }

    fn invalid_opcode_addressing_mode_combination(line: u32) -> ParserError {
        ParserError::from(format!("Invalid addressing mode for opcode. Line {}", line))
    }

    fn unexpected_eol(line: u32) -> ParserError {
        ParserError::from(format!("Unexpected end of line. Line {}", line))
    }
}

impl From<String> for ParserError {
    fn from(error: String) -> ParserError {
        ParserError { message: error }
    }
}

impl<'a> From<&'a str> for ParserError {
    fn from(error: &str) -> ParserError {
        ParserError { message: error.into() }
    }
}

pub struct Parser {
    tokens: Vec<Vec<Token>>,
    line: u32,
}

/// Parser processes a list of 6502 Assembly tokens
impl Parser {
    pub fn new(tokens: Vec<Vec<Token>>) -> Parser {
        Parser {
            tokens: tokens,
            line: 0,
        }
    }

    /// Processes its tokens and either returns them to the caller
    /// or produces an error
    pub fn parse(&mut self) -> Result<Vec<Vec<Token>>, ParserError> {
        let successful_result = self.tokens.iter().map(|v| v.clone()).collect();

        for line in &self.tokens {
            self.line += 1;
            let mut peeker = line.iter().peekable();
            // Check what starts the line
            let token = peeker.peek().unwrap().clone();

            match *token {
                Token::Label(_) => {
                    // if its a label, consume it and move on
                    peeker.next();
                    if let None = peeker.peek() {
                        // If its just a label, thats fine
                        return Ok(successful_result);
                    }
                    let next = *peeker.peek().unwrap();
                    if let &Token::OpCode(_) = next {
                        Self::handle_opcode(&mut peeker, &&next, self.line)?;
                    } else {
                        return Err(ParserError::expected_instruction(self.line));
                    }
                }
                _ => (),
            }
        }

        Ok(successful_result)
    }

    fn handle_opcode<'a, I>(mut peeker: &mut Peekable<I>,
                            token: &Token,
                            line: u32)
                            -> Result<(), ParserError>
        where I: Iterator<Item = &'a Token>
    {
        if let None = peeker.peek() {
            Err(ParserError::unexpected_eol(line))
        } else {
            peeker.next();
            let next = *peeker.peek().unwrap();
            let addressing_mode = next.to_addressing_mode();
            if let &Token::OpCode(ref mnemonic) = token {
                if let Some(opcode) = OpCode::from_mnemonic_and_addressing_mode(mnemonic.clone(),
                                                                                addressing_mode) {
                    Ok(())
                } else {
                    Err(ParserError::invalid_opcode_addressing_mode_combination(line))
                }
            } else {
                Err(ParserError::expected_instruction(line))
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use ::assembler::token::{ImmediateBase, Token};

    #[test]
    fn errors_on_multiple_labels() {
        let mut parser = Parser::new(vec![vec![Token::Label("MAIN".into()),
                                               Token::Label("METHOD".into()),
                                               Token::OpCode("LDA".into()),
                                               Token::Immediate("10".into(),
                                                                ImmediateBase::Base16)]]);

        assert_eq!(Err(ParserError::expected_instruction(1)), parser.parse());
    }

    #[test]
    fn does_not_error_on_single_label() {
        let mut parser = Parser::new(vec![vec![Token::Label("MAIN".into()),
                                               Token::OpCode("LDA".into()),
                                               Token::Immediate("10".into(),
                                                                ImmediateBase::Base16)]]);

        assert_eq!(&[Token::Label("MAIN".into()),
                     Token::OpCode("LDA".into()),
                     Token::Immediate("10".into(), ImmediateBase::Base16)],
                   &parser.parse().unwrap()[0][..]);
    }

    #[test]
    fn can_detect_invalid_addressing_modes() {
        let mut parser = Parser::new(vec![vec![Token::Label("MAIN".into()),
                                               Token::OpCode("LDX".into()),
                                               Token::IndirectY("10".into())]]);

        assert_eq!(Err(ParserError::invalid_opcode_addressing_mode_combination(1)),
                   parser.parse());
    }

    #[test]
    fn does_not_error_on_valid_addressing_modes() {
        let mut parser = Parser::new(vec![vec![Token::Label("MAIN".into()),
                                               Token::OpCode("LDA".into()),
                                               Token::IndirectY("10".into())]]);

        let result = parser.parse().unwrap();
        assert_eq!(&[Token::Label("MAIN".into()),
                     Token::OpCode("LDA".into()),
                     Token::IndirectY("10".into())],
                   &result[0][..]);
    }

    #[test]
    fn does_not_error_on_label_only_line() {
        let mut parser = Parser::new(vec![vec![Token::Label("MAIN".into())],
                                          vec![Token::OpCode("LDA".into()),
                                               Token::Absolute("4400".into())]]);

        let result = parser.parse().unwrap();

        assert_eq!(&[Token::Label("MAIN".into())], &result[0][..]);
        assert_eq!(&[Token::OpCode("LDA".into()), Token::Absolute("4400".into())],
                   &result[1][..]);
    }
}<|endoftext|>


<commit_before>use kay::{ID, ActorSystem, World, Fate};
use kay::swarm::{Swarm, SubActor, CreateWith};
use compact::{CVec, CDict};
use core::simulation::{TimeOfDay, Timestamp};

use super::resources::{ResourceMap, ResourceId, ResourceAmount, Entry};
use ordered_float::OrderedFloat;

mod judgement_table;
use self::judgement_table::judgement_table;

mod tasks;
use self::tasks::Task;

mod buildings;

use super::market::{Market, Evaluate, Search, EvaluatedDeal, EvaluatedSearchResult,
                    GetApplicableDeal, ApplicableDeal, StartedUsing, StoppedUsing};
use super::super::lanes_and_cars::pathfinding::trip::{Trip, Start, CreatedTrip, TripResult};

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

#[derive(Compact, Clone)]
struct DecisionResourceEntry {
    n_deals_expected: usize,
    deals: CVec<EvaluatedDeal>,
}

#[derive(Compact, Clone)]
enum DecisionState {
    None,
    Choosing(MemberIdx, Timestamp, CDict<ResourceId, DecisionResourceEntry>),
    WaitingForTrip(MemberIdx),
}

#[derive(Compact, Clone, SubActor)]
pub struct Family {
    _id: Option<ID>,
    resources: ResourceMap<ResourceAmount>,
    member_resources: CVec<ResourceMap<ResourceAmount>>,
    member_tasks: CVec<Task>,
    decision_state: DecisionState,
    used_offers: ResourceMap<ID>,
    member_used_offers: CVec<ResourceMap<ID>>,
}

const N_TOP_PROBLEMS: usize = 3;

use super::resources::r_properties;

fn resource_graveness_helper(resource: ResourceId, amount: ResourceAmount, time: TimeOfDay) -> f32 {
    -amount * judgement_table().importance(resource, time)
}

impl Family {
    pub fn top_problems(&self, member: MemberIdx, time: TimeOfDay) -> Vec<(ResourceId, f32)> {
        let mut resource_graveness = self.resources
            .iter()
            .chain(self.member_resources[member.0].iter())
            .map(|&Entry(resource, amount)| {
                (resource, resource_graveness_helper(resource, amount, time))
            })
            .collect::<Vec<_>>();
        resource_graveness.sort_by_key(|&(_r, i)| OrderedFloat(i));

        resource_graveness.truncate(N_TOP_PROBLEMS);
        resource_graveness
    }

    pub fn find_new_task_for(&mut self,
                             member: MemberIdx,
                             tick: Timestamp,
                             location: ID,
                             world: &mut World) {
        let mut decision_entries = CDict::<ResourceId, DecisionResourceEntry>::new();
        let time = TimeOfDay::from_tick(tick);

        for (resource, _) in self.top_problems(member, time) {
            let maybe_offer = if r_properties(resource).supplier_shared {
                self.used_offers.get(resource)
            } else {
                self.member_used_offers[member.0].get(resource)
            };

            if let Some(&offer) = maybe_offer {
                world.send(offer, Evaluate { time, location, requester: self.id() });
            } else {
                world.send_to_id_of::<Market, _>(Search {
                                                     time,
                                                     location,
                                                     resource,
                                                     requester: self.id(),
                                                 });
            }

            decision_entries.insert(resource,
                                    DecisionResourceEntry {
                                        n_deals_expected: 1,
                                        deals: CVec::new(),
                                    });
        }

        self.decision_state = DecisionState::Choosing(member, tick, decision_entries);
    }

    pub fn choose_deal(&mut self, world: &mut World) {
        let (member, tick, best_offer) =
            if let DecisionState::Choosing(member, tick, ref entries) = self.decision_state {
                let time = TimeOfDay::from_tick(tick);
                let maybe_best = entries
                    .values()
                    .flat_map(|entry| {
                        entry
                            .deals
                            .iter()
                            .filter(|evaluated| evaluated.from < time && evaluated.to > time)
                            .map(|evaluated| {
                                let give_alleviation =
                                    resource_graveness_helper(evaluated.deal.give.0,
                                                              -evaluated.deal.give.1,
                                                              time);
                                let take_graveness: f32 = evaluated
                                    .deal
                                    .take
                                    .iter()
                                    .map(|&Entry(resource, amount)| {
                                        resource_graveness_helper(resource, -amount, time)
                                    })
                                    .sum();

                                let usefulness = give_alleviation /
                                                 (take_graveness *
                                                  evaluated.deal.duration.seconds() as f32);

                                (usefulness, evaluated)
                            })
                    })
                    .collect::<Vec<_>>()
                    .into_iter()
                    .max_by_key(|&(u, _e)| OrderedFloat(u));

                let best = maybe_best
                    .expect("TODO: deal with no suitable offer at all")
                    .1;
                let task = &mut self.member_tasks[member.0];

                *task = if let TaskState::IdleAt(loc) = task.state {
                    Task {
                        offer: best.offer,
                        goal: best.deal.give.0,
                        duration: best.deal.duration,
                        state: TaskState::GettingReadyAt(loc),
                    }
                } else {
                    panic!("Member who gets new task should be idle");
                };

                (member, tick, best.offer)
            } else {
                panic!("Tried to choose deal while not deciding");
            };

        self.decision_state = DecisionState::WaitingForTrip(member);
        world.send(best_offer, GetApplicableDeal(self.id(), member));
        self.start_trip(member, tick, world);
    }

    pub fn start_trip(&mut self, member: MemberIdx, tick: Timestamp, world: &mut World) {
        if let Task {
                   offer,
                   state: TaskState::GettingReadyAt(source),
                   ..
               } = self.member_tasks[member.0] {
            world.send_to_id_of::<Swarm<Trip>, _>(CreateWith(Trip::new(source,
                                                                       offer,
                                                                       Some(self.id())),
                                                             Start(tick)));
        } else {
            panic!("Member should be getting ready before starting trip");
        }
    }
}

use core::simulation::Wake;
use self::tasks::TaskState;

pub fn setup(system: &mut ActorSystem) {
    system.add(Swarm::<Family>::new(),
               Swarm::<Family>::subactors(|mut each_family| {
        each_family.on(|&Wake { current_tick }, family, world| {
            if let DecisionState::None = family.decision_state {
                let maybe_idle_idx_loc = family
                    .member_tasks
                    .iter()
                    .enumerate()
                    .filter_map(|(idx, m)| match m.state {
                                    TaskState::IdleAt(loc) => Some((idx, loc)),
                                    _ => None,
                                })
                    .next();
                if let Some((idle_member_idx, location)) = maybe_idle_idx_loc {
                    family.find_new_task_for(MemberIdx(idle_member_idx),
                                             current_tick,
                                             location,
                                             world);
                }
            };
            Fate::Live
        });

        each_family.on(|&EvaluatedSearchResult { resource, n_to_expect, ref some_results },
                        family,
                        world| {
            let done = if let DecisionState::Choosing(_, _, ref mut entries) =
                family.decision_state {
                {
                    let entry = entries
                        .get_mut(resource)
                        .expect("Should have an entry for queried resource");
                    entry.n_deals_expected = n_to_expect;
                    entry.deals.extend(some_results.clone());
                }

                entries
                    .values()
                    .all(|entry| entry.n_deals_expected == entry.deals.len())
            } else {
                panic!("Received unexpected deal");
            };
            if done {
                family.choose_deal(world);
            }
            Fate::Live
        });

        each_family.on(|&CreatedTrip(trip), family, _| {
            family.decision_state = if let DecisionState::WaitingForTrip(member) =
                family.decision_state {
                family.member_tasks[member.0].state = TaskState::InTrip(trip);
                DecisionState::None
            } else {
                panic!("Should be in waiting for trip state")
            };
            Fate::Live
        });

        each_family.on(move |&TripResult { id, location, tick, failed }, family, world| {
            let (matching_task_member, matching_resource, matching_offer) =
                family
                    .member_tasks
                    .iter()
                    .enumerate()
                    .filter_map(|(idx, task)| if let TaskState::InTrip(trip_id) = task.state {
                                    if trip_id == id {
                                        Some((MemberIdx(idx), task.goal, task.offer))
                                    } else {
                                        None
                                    }
                                } else {
                                    None
                                })
                    .next()
                    .expect("Should have a matching task");
            {
                let family_id = family.id();
                let shared = r_properties(matching_resource).supplier_shared;
                let used_offers = if shared {
                    &mut family.used_offers
                } else {
                    &mut family.member_used_offers[matching_task_member.0]
                };

                let maybe_member = if shared {
                    Some(matching_task_member)
                } else {
                    None
                };

                if failed {
                    used_offers.remove(matching_resource);
                    world.send(matching_offer, StoppedUsing(family_id, maybe_member));
                } else {
                    used_offers.insert(matching_resource, matching_offer);
                    world.send(matching_offer, StartedUsing(family_id, maybe_member));
                }
            }

            if failed {
                family.stop_task(matching_task_member, location, world);
            } else {
                family.start_task(matching_task_member, tick, location, world);
            }
            Fate::Live
        });

        each_family.on(|&ApplicableDeal(ref deal, member), family, _| {
            let resource_deltas = deal.take
                .iter()
                .map(|&Entry(resource, amount)| (resource, -amount))
                .chain(Some(deal.give));
            for (resource, delta) in resource_deltas {
                let resources = if r_properties(resource).ownership_shared {
                    &mut family.resources
                } else {
                    &mut family.member_resources[member.0]
                };
                *resources.mut_entry_or(resource, 0.0) += delta;
            }
            Fate::Live
        });
    }));
}

#[derive(Compact, Clone, SubActor)]
pub struct Company {
    _id: Option<ID>,
    resources: ResourceMap<ResourceAmount>,
    worker_tasks: CVec<Task>,
    used_offers: ResourceMap<ID>,
    own_offers: CVec<ID>,
}
<commit_msg>add ref from household to building #150<commit_after>use kay::{ID, ActorSystem, World, Fate};
use kay::swarm::{Swarm, SubActor, CreateWith};
use compact::{CVec, CDict};
use core::simulation::{TimeOfDay, Timestamp};

use super::resources::{ResourceMap, ResourceId, ResourceAmount, Entry};
use ordered_float::OrderedFloat;

mod judgement_table;
use self::judgement_table::judgement_table;

mod tasks;
use self::tasks::Task;

mod buildings;

use super::market::{Market, Evaluate, Search, EvaluatedDeal, EvaluatedSearchResult,
                    GetApplicableDeal, ApplicableDeal, StartedUsing, StoppedUsing};
use super::super::lanes_and_cars::pathfinding::trip::{Trip, Start, CreatedTrip, TripResult};

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

#[derive(Compact, Clone)]
struct DecisionResourceEntry {
    n_deals_expected: usize,
    deals: CVec<EvaluatedDeal>,
}

#[derive(Compact, Clone)]
enum DecisionState {
    None,
    Choosing(MemberIdx, Timestamp, CDict<ResourceId, DecisionResourceEntry>),
    WaitingForTrip(MemberIdx),
}

#[derive(Compact, Clone, SubActor)]
pub struct Family {
    _id: Option<ID>,
    home: ID,
    resources: ResourceMap<ResourceAmount>,
    member_resources: CVec<ResourceMap<ResourceAmount>>,
    member_tasks: CVec<Task>,
    decision_state: DecisionState,
    used_offers: ResourceMap<ID>,
    member_used_offers: CVec<ResourceMap<ID>>,
}

const N_TOP_PROBLEMS: usize = 3;

use super::resources::r_properties;

fn resource_graveness_helper(resource: ResourceId, amount: ResourceAmount, time: TimeOfDay) -> f32 {
    -amount * judgement_table().importance(resource, time)
}

impl Family {
    pub fn top_problems(&self, member: MemberIdx, time: TimeOfDay) -> Vec<(ResourceId, f32)> {
        let mut resource_graveness = self.resources
            .iter()
            .chain(self.member_resources[member.0].iter())
            .map(|&Entry(resource, amount)| {
                (resource, resource_graveness_helper(resource, amount, time))
            })
            .collect::<Vec<_>>();
        resource_graveness.sort_by_key(|&(_r, i)| OrderedFloat(i));

        resource_graveness.truncate(N_TOP_PROBLEMS);
        resource_graveness
    }

    pub fn find_new_task_for(&mut self,
                             member: MemberIdx,
                             tick: Timestamp,
                             location: ID,
                             world: &mut World) {
        let mut decision_entries = CDict::<ResourceId, DecisionResourceEntry>::new();
        let time = TimeOfDay::from_tick(tick);

        for (resource, _) in self.top_problems(member, time) {
            let maybe_offer = if r_properties(resource).supplier_shared {
                self.used_offers.get(resource)
            } else {
                self.member_used_offers[member.0].get(resource)
            };

            if let Some(&offer) = maybe_offer {
                world.send(offer, Evaluate { time, location, requester: self.id() });
            } else {
                world.send_to_id_of::<Market, _>(Search {
                                                     time,
                                                     location,
                                                     resource,
                                                     requester: self.id(),
                                                 });
            }

            decision_entries.insert(resource,
                                    DecisionResourceEntry {
                                        n_deals_expected: 1,
                                        deals: CVec::new(),
                                    });
        }

        self.decision_state = DecisionState::Choosing(member, tick, decision_entries);
    }

    pub fn choose_deal(&mut self, world: &mut World) {
        let (member, tick, best_offer) =
            if let DecisionState::Choosing(member, tick, ref entries) = self.decision_state {
                let time = TimeOfDay::from_tick(tick);
                let maybe_best = entries
                    .values()
                    .flat_map(|entry| {
                        entry
                            .deals
                            .iter()
                            .filter(|evaluated| evaluated.from < time && evaluated.to > time)
                            .map(|evaluated| {
                                let give_alleviation =
                                    resource_graveness_helper(evaluated.deal.give.0,
                                                              -evaluated.deal.give.1,
                                                              time);
                                let take_graveness: f32 = evaluated
                                    .deal
                                    .take
                                    .iter()
                                    .map(|&Entry(resource, amount)| {
                                        resource_graveness_helper(resource, -amount, time)
                                    })
                                    .sum();

                                let usefulness = give_alleviation /
                                                 (take_graveness *
                                                  evaluated.deal.duration.seconds() as f32);

                                (usefulness, evaluated)
                            })
                    })
                    .collect::<Vec<_>>()
                    .into_iter()
                    .max_by_key(|&(u, _e)| OrderedFloat(u));

                let best = maybe_best
                    .expect("TODO: deal with no suitable offer at all")
                    .1;
                let task = &mut self.member_tasks[member.0];

                *task = if let TaskState::IdleAt(loc) = task.state {
                    Task {
                        offer: best.offer,
                        goal: best.deal.give.0,
                        duration: best.deal.duration,
                        state: TaskState::GettingReadyAt(loc),
                    }
                } else {
                    panic!("Member who gets new task should be idle");
                };

                (member, tick, best.offer)
            } else {
                panic!("Tried to choose deal while not deciding");
            };

        self.decision_state = DecisionState::WaitingForTrip(member);
        world.send(best_offer, GetApplicableDeal(self.id(), member));
        self.start_trip(member, tick, world);
    }

    pub fn start_trip(&mut self, member: MemberIdx, tick: Timestamp, world: &mut World) {
        if let Task {
                   offer,
                   state: TaskState::GettingReadyAt(source),
                   ..
               } = self.member_tasks[member.0] {
            world.send_to_id_of::<Swarm<Trip>, _>(CreateWith(Trip::new(source,
                                                                       offer,
                                                                       Some(self.id())),
                                                             Start(tick)));
        } else {
            panic!("Member should be getting ready before starting trip");
        }
    }
}

use core::simulation::Wake;
use self::tasks::TaskState;

pub fn setup(system: &mut ActorSystem) {
    system.add(Swarm::<Family>::new(),
               Swarm::<Family>::subactors(|mut each_family| {
        each_family.on(|&Wake { current_tick }, family, world| {
            if let DecisionState::None = family.decision_state {
                let maybe_idle_idx_loc = family
                    .member_tasks
                    .iter()
                    .enumerate()
                    .filter_map(|(idx, m)| match m.state {
                                    TaskState::IdleAt(loc) => Some((idx, loc)),
                                    _ => None,
                                })
                    .next();
                if let Some((idle_member_idx, location)) = maybe_idle_idx_loc {
                    family.find_new_task_for(MemberIdx(idle_member_idx),
                                             current_tick,
                                             location,
                                             world);
                }
            };
            Fate::Live
        });

        each_family.on(|&EvaluatedSearchResult { resource, n_to_expect, ref some_results },
                        family,
                        world| {
            let done = if let DecisionState::Choosing(_, _, ref mut entries) =
                family.decision_state {
                {
                    let entry = entries
                        .get_mut(resource)
                        .expect("Should have an entry for queried resource");
                    entry.n_deals_expected = n_to_expect;
                    entry.deals.extend(some_results.clone());
                }

                entries
                    .values()
                    .all(|entry| entry.n_deals_expected == entry.deals.len())
            } else {
                panic!("Received unexpected deal");
            };
            if done {
                family.choose_deal(world);
            }
            Fate::Live
        });

        each_family.on(|&CreatedTrip(trip), family, _| {
            family.decision_state = if let DecisionState::WaitingForTrip(member) =
                family.decision_state {
                family.member_tasks[member.0].state = TaskState::InTrip(trip);
                DecisionState::None
            } else {
                panic!("Should be in waiting for trip state")
            };
            Fate::Live
        });

        each_family.on(move |&TripResult { id, location, tick, failed }, family, world| {
            let (matching_task_member, matching_resource, matching_offer) =
                family
                    .member_tasks
                    .iter()
                    .enumerate()
                    .filter_map(|(idx, task)| if let TaskState::InTrip(trip_id) = task.state {
                                    if trip_id == id {
                                        Some((MemberIdx(idx), task.goal, task.offer))
                                    } else {
                                        None
                                    }
                                } else {
                                    None
                                })
                    .next()
                    .expect("Should have a matching task");
            {
                let family_id = family.id();
                let shared = r_properties(matching_resource).supplier_shared;
                let used_offers = if shared {
                    &mut family.used_offers
                } else {
                    &mut family.member_used_offers[matching_task_member.0]
                };

                let maybe_member = if shared {
                    Some(matching_task_member)
                } else {
                    None
                };

                if failed {
                    used_offers.remove(matching_resource);
                    world.send(matching_offer, StoppedUsing(family_id, maybe_member));
                } else {
                    used_offers.insert(matching_resource, matching_offer);
                    world.send(matching_offer, StartedUsing(family_id, maybe_member));
                }
            }

            if failed {
                family.stop_task(matching_task_member, location, world);
            } else {
                family.start_task(matching_task_member, tick, location, world);
            }
            Fate::Live
        });

        each_family.on(|&ApplicableDeal(ref deal, member), family, _| {
            let resource_deltas = deal.take
                .iter()
                .map(|&Entry(resource, amount)| (resource, -amount))
                .chain(Some(deal.give));
            for (resource, delta) in resource_deltas {
                let resources = if r_properties(resource).ownership_shared {
                    &mut family.resources
                } else {
                    &mut family.member_resources[member.0]
                };
                *resources.mut_entry_or(resource, 0.0) += delta;
            }
            Fate::Live
        });
    }));
}

#[derive(Compact, Clone, SubActor)]
pub struct Company {
    _id: Option<ID>,
    site: ID,
    resources: ResourceMap<ResourceAmount>,
    worker_tasks: CVec<Task>,
    used_offers: ResourceMap<ID>,
    own_offers: CVec<ID>,
}
<|endoftext|>