<commit_before>//! Interfaces for building [docker](https://www.docker.com/) containers

extern crate rustc_serialize;
extern crate jed;
extern crate url;

use self::super::Docker;
use self::super::transport::Body;
use self::super::rep::{ContainerCreateInfo, Event};
use self::super::rep::Container as ContainerRep;
use std::collections::{BTreeMap, HashMap};
use std::io::Result;
use rustc_serialize::json::{self, Json, ToJson};

/// Interface for building container list request
pub struct ContainerListBuilder<'a> {
    docker: &'a Docker,
    params: HashMap<&'static str, String>,
}

impl<'a> ContainerListBuilder<'a> {
    pub fn new(docker: &'a Docker) -> ContainerListBuilder<'a> {
        ContainerListBuilder {
            docker: docker,
            params: HashMap::new(),
        }
    }

    pub fn all(&mut self) -> &mut ContainerListBuilder<'a> {
        self.params.insert("all", "true".to_owned());
        self
    }

    pub fn since(&mut self, since: &str) -> &mut ContainerListBuilder<'a> {
        self.params.insert("since", since.to_owned());
        self
    }

    pub fn before(&mut self, before: &str) -> &mut ContainerListBuilder<'a> {
        self.params.insert("before", before.to_owned());
        self
    }

    pub fn sized(&mut self) -> &mut ContainerListBuilder<'a> {
        self.params.insert("size", "true".to_owned());
        self
    }

    pub fn build(self) -> Result<Vec<ContainerRep>> {
        let mut params = Vec::new();
        for (k, v) in self.params {
            params.push(format!("{}={}", k, v))
        }
        let mut path = vec!["/containers/json".to_owned()];
        if !params.is_empty() {
            path.push(params.join("&"))
        }
        let raw = try!(self.docker.get(&path.join("?")));
        Ok(json::decode::<Vec<ContainerRep>>(&raw).unwrap())
    }
}

/// Interface for building a new docker container from an existing image
pub struct ContainerBuilder<'a, 'b> {
    docker: &'a Docker,
    image: &'b str,
    hostname: Option<String>,
    user: Option<String>,
    memory: Option<u64>,
}

impl<'a, 'b> ContainerBuilder<'a, 'b> {
    pub fn new(docker: &'a Docker, image: &'b str) -> ContainerBuilder<'a, 'b> {
        ContainerBuilder {
            docker: docker,
            image: image,
            hostname: None,
            user: None,
            memory: None,
        }
    }

    pub fn hostname(&mut self, h: &str) -> &mut ContainerBuilder<'a, 'b> {
        self.hostname = Some(h.to_owned());
        self
    }

    pub fn user(&mut self, u: &str) -> &mut ContainerBuilder<'a, 'b> {
        self.user = Some(u.to_owned());
        self
    }

    pub fn build(&self) -> Result<ContainerCreateInfo> {
        let mut body = BTreeMap::new();
        body.insert("Image".to_owned(), self.image.to_json());
        let json_obj: Json = body.to_json();
        let data = json::encode(&json_obj).unwrap();
        let mut bytes = data.as_bytes();
        let raw = try!(self.docker.post("/containers/create",
                                        Some(Body::new(&mut Box::new(&mut bytes),
                                                       bytes.len() as u64))));
        Ok(json::decode::<ContainerCreateInfo>(&raw).unwrap())
    }
}

/// Interface for buiding an events request
pub struct EventsBuilder<'a, 'b, 'c> {
    docker: &'a Docker,
    since: Option<&'b u64>,
    until: Option<&'c u64>,
}

impl<'a, 'b, 'c> EventsBuilder<'a, 'b, 'c> {
    pub fn new(docker: &'a Docker) -> EventsBuilder<'a, 'b, 'c> {
        EventsBuilder {
            docker: docker,
            since: None,
            until: None,
        }
    }

    /// Filter events since a given timestamp
    pub fn since(mut self, ts: &'b u64) -> EventsBuilder<'a, 'b, 'c> {
        self.since = Some(ts);
        self
    }

    /// Filter events until a given timestamp
    pub fn until(mut self, ts: &'c u64) -> EventsBuilder<'a, 'b, 'c> {
        self.until = Some(ts);
        self
    }

    /// Returns an interator over streamed docker events
    pub fn build(mut self) -> Result<Box<Iterator<Item = Event>>> {
        let mut params = Vec::new();
        if let Some(s) = self.since {
            params.push(format!("since={}", s));
        }
        if let Some(u) = self.until {
            params.push(format!("until={}", u));
        }
        let mut path = vec!["/events".to_owned()];
        if !params.is_empty() {
            path.push(params.join("&"))
        }
        let raw = try!(self.docker.stream_get(&path.join("?")[..]));
        let it = jed::Iter::new(raw).into_iter().map(|j| {
            let s = json::encode(&j).unwrap();
            json::decode::<Event>(&s).unwrap()
        });
        Ok(Box::new(it))
    }
}
<commit_msg>improve builder interface<commit_after>//! Interfaces for building [docker](https://www.docker.com/) containers

extern crate rustc_serialize;
extern crate jed;
extern crate url;

use self::super::Docker;
use self::super::transport::Body;
use self::super::rep::{ContainerCreateInfo, Event};
use self::super::rep::Container as ContainerRep;
use std::collections::{BTreeMap, HashMap};
use std::io::Result;
use rustc_serialize::json::{self, Json, ToJson};

/// Interface for building container list request
pub struct ContainerListBuilder<'a> {
    docker: &'a Docker,
    params: HashMap<&'static str, String>,
}

impl<'a> ContainerListBuilder<'a> {
    pub fn new(docker: &'a Docker) -> ContainerListBuilder<'a> {
        ContainerListBuilder {
            docker: docker,
            params: HashMap::new(),
        }
    }

    pub fn all(&mut self) -> &mut ContainerListBuilder<'a> {
        self.params.insert("all", "true".to_owned());
        self
    }

    pub fn since(&mut self, since: &str) -> &mut ContainerListBuilder<'a> {
        self.params.insert("since", since.to_owned());
        self
    }

    pub fn before(&mut self, before: &str) -> &mut ContainerListBuilder<'a> {
        self.params.insert("before", before.to_owned());
        self
    }

    pub fn sized(&mut self) -> &mut ContainerListBuilder<'a> {
        self.params.insert("size", "true".to_owned());
        self
    }

    pub fn build(self) -> Result<Vec<ContainerRep>> {
        let mut params = Vec::new();
        for (k, v) in self.params {
            params.push(format!("{}={}", k, v))
        }
        let mut path = vec!["/containers/json".to_owned()];
        if !params.is_empty() {
            path.push(params.join("&"))
        }
        let raw = try!(self.docker.get(&path.join("?")));
        Ok(json::decode::<Vec<ContainerRep>>(&raw).unwrap())
    }
}

/// Interface for building a new docker container from an existing image
pub struct ContainerBuilder<'a, 'b> {
    docker: &'a Docker,
    image: &'b str,
    hostname: Option<String>,
    user: Option<String>,
    memory: Option<u64>,
}

impl<'a, 'b> ContainerBuilder<'a, 'b> {
    pub fn new(docker: &'a Docker, image: &'b str) -> ContainerBuilder<'a, 'b> {
        ContainerBuilder {
            docker: docker,
            image: image,
            hostname: None,
            user: None,
            memory: None,
        }
    }

    pub fn hostname(&mut self, h: &str) -> &mut ContainerBuilder<'a, 'b> {
        self.hostname = Some(h.to_owned());
        self
    }

    pub fn user(&mut self, u: &str) -> &mut ContainerBuilder<'a, 'b> {
        self.user = Some(u.to_owned());
        self
    }

    pub fn build(&self) -> Result<ContainerCreateInfo> {
        let mut body = BTreeMap::new();
        body.insert("Image".to_owned(), self.image.to_json());
        let json_obj: Json = body.to_json();
        let data = json::encode(&json_obj).unwrap();
        let mut bytes = data.as_bytes();
        let raw = try!(self.docker.post("/containers/create",
                                        Some(Body::new(&mut Box::new(&mut bytes),
                                                       bytes.len() as u64))));
        Ok(json::decode::<ContainerCreateInfo>(&raw).unwrap())
    }
}

/// Interface for buiding an events request
pub struct EventsBuilder<'a, 'b, 'c> {
    docker: &'a Docker,
    since: Option<&'b u64>,
    until: Option<&'c u64>,
}

impl<'a, 'b, 'c> EventsBuilder<'a, 'b, 'c> {
    pub fn new(docker: &'a Docker) -> EventsBuilder<'a, 'b, 'c> {
        EventsBuilder {
            docker: docker,
            since: None,
            until: None,
        }
    }

    /// Filter events since a given timestamp
    pub fn since(&mut self, ts: &'b u64) -> &mut EventsBuilder<'a, 'b, 'c> {
        self.since = Some(ts);
        self
    }

    /// Filter events until a given timestamp
    pub fn until(&mut self, ts: &'c u64) -> &mut EventsBuilder<'a, 'b, 'c> {
        self.until = Some(ts);
        self
    }

    /// Returns an interator over streamed docker events
    pub fn build(&self) -> Result<Box<Iterator<Item = Event>>> {
        let mut params = Vec::new();
        if let Some(s) = self.since {
            params.push(format!("since={}", s));
        }
        if let Some(u) = self.until {
            params.push(format!("until={}", u));
        }
        let mut path = vec!["/events".to_owned()];
        if !params.is_empty() {
            path.push(params.join("&"))
        }
        let raw = try!(self.docker.stream_get(&path.join("?")[..]));
        let it = jed::Iter::new(raw).into_iter().map(|j| {
            let s = json::encode(&j).unwrap();
            json::decode::<Event>(&s).unwrap()
        });
        Ok(Box::new(it))
    }
}
<|endoftext|>


<commit_before>// The CPU
#![allow(non_snake_case)]
extern crate sdl2;
use c64::opcodes;
use c64::memory;
use c64::vic;
use c64::cia;
use std::cell::RefCell;
use std::rc::Rc;

use utils;

pub type CPUShared = Rc<RefCell<CPU>>;

// status flags for P register
pub enum StatusFlag
{
    Carry            = 1 << 0,
    Zero             = 1 << 1,
    InterruptDisable = 1 << 2,
    DecimalMode      = 1 << 3,
    Break            = 1 << 4,
    Unused           = 1 << 5,
    Overflow         = 1 << 6,
    Negative         = 1 << 7,
}

pub static NMI_VECTOR:   u16 = 0xFFFA;
pub static RESET_VECTOR: u16 = 0xFFFC;
pub static IRQ_VECTOR:   u16 = 0xFFFE;

pub struct CPU
{
    pub PC: u16, // program counter
    pub SP: u8,  // stack pointer
    pub P: u8,   // processor status
    pub A: u8,   // accumulator
    pub X: u8,   // index register
    pub Y: u8,   // index register
    pub mem_ref: Option<memory::MemShared>, // reference to shared system memory
    pub vic_ref: Option<vic::VICShared>,
    pub cia1_ref: Option<cia::CIAShared>,
    pub cia2_ref: Option<cia::CIAShared>,
    pub ba_low: bool,  // is BA low?
    pub cia_irq: bool,
    pub vic_irq: bool,
    nmi: bool,
    pub prev_PC: u16, // previous program counter - for debugging
    pub op_debugger: utils::OpDebugger
}

impl CPU
{
    pub fn new_shared() -> CPUShared
    {
        Rc::new(RefCell::new(CPU
        {
            PC: 0,
            SP: 0xFF,
            P: 0,
            A: 0,
            X: 0,
            Y: 0,
            mem_ref: None,
            vic_ref: None,
            cia1_ref: None,
            cia2_ref: None,
            ba_low: false,
            cia_irq: false,
            vic_irq: false,
            nmi: false,
            prev_PC: 0,
            op_debugger: utils::OpDebugger::new()
        }))
    }

    pub fn set_references(&mut self, memref: memory::MemShared, vicref: vic::VICShared, cia1ref: cia::CIAShared, cia2ref: cia::CIAShared)
    {
        self.mem_ref = Some(memref);
        self.vic_ref = Some(vicref);
        self.cia1_ref = Some(cia1ref);
        self.cia2_ref = Some(cia2ref);
    }

    pub fn set_status_flag(&mut self, flag: StatusFlag, value: bool)
    {
        if value { self.P |=   flag as u8;  }
        else     { self.P &= !(flag as u8); }
    }

    pub fn get_status_flag(&mut self, flag: StatusFlag) -> bool
    {
        self.P & flag as u8 != 0x00
    }

    // these flags will be set in tandem quite often
    pub fn set_zn_flags(&mut self, value: u8)
    {
        self.set_status_flag(StatusFlag::Zero, value == 0x00);
        self.set_status_flag(StatusFlag::Negative, (value as i8) < 0);
    }

    pub fn reset(&mut self)
    {
        // reset program counter
        let pc = self.read_word_le(RESET_VECTOR);
        self.PC = pc;
        self.SP = 0xFF;
        self.ba_low = false;
        self.cia_irq = false;
        self.vic_irq = false;
        self.nmi = false;
    }

    pub fn update(&mut self)
    {
        if self.ba_low { return }
        if self.process_nmi() { return }

        if self.process_irq() { return }
        let op = self.next_byte();
        //println!("${:04X}", self.PC);
        self.process_op(op);
    }

    pub fn next_byte(&mut self) -> u8
    {
        let pc = self.PC;
        let op = self.read_byte(pc);
        self.PC += 1;
        op
    }

    pub fn next_word(&mut self) -> u16
    {
        let word = self.read_word_le(self.PC);
        self.PC += 2;
        word
    }

    // stack memory: $0100 - $01FF (256 byes)
    // TODO: some extra message if stack over/underflow occurs? (right now handled by Rust)
    pub fn push_byte(&mut self, value: u8)
    {
        self.SP -= 0x01;
        let newSP = (self.SP + 0x01) as u16;
        self.write_byte(0x0100 + newSP, value);
    }

    pub fn pop_byte(&mut self) -> u8
    {
        let addr = 0x0100 + (self.SP + 0x01) as u16;
        let value = self.read_byte(addr);
        self.SP += 0x01;
        value
    }

    pub fn push_word(&mut self, value: u16)
    {
        self.SP -= 0x02;
        self.write_word_le(0x0100 + (self.SP + 0x01) as u16, value);
    }

    pub fn pop_word(&mut self) -> u16
    {
        let value = self.read_word_le(0x0100 + (self.SP + 0x01) as u16);
        self.SP += 0x02;
        value
    }

    pub fn write_byte(&mut self, addr: u16, value: u8) -> bool
    {
        let mut on_vic_write: vic::VICCallbackAction = vic::VICCallbackAction::None;
        let mut on_cia_write: cia::CIACallbackAction = cia::CIACallbackAction::None;
        let mem_write_ok: bool;
        match addr
        {
            // VIC-II address space
            0xD000...0xD400 => mem_write_ok = as_mut!(self.vic_ref).write_register(addr, value, &mut on_vic_write),
            // CIA1 address space
            0xDC00...0xDCFF => mem_write_ok = as_mut!(self.cia1_ref).write_register(addr, value, &mut on_cia_write),
            // CIA2 address space
            0xDD00...0xDD0F => mem_write_ok = as_mut!(self.cia2_ref).write_register(addr, value, &mut on_cia_write),
            _ => mem_write_ok = as_mut!(self.mem_ref).write_byte(addr, value),
        }

        // on VIC register write perform necessary action on the CPU
        match on_vic_write
        {
            vic::VICCallbackAction::TriggerVICIrq => self.trigger_vic_irq(),
            vic::VICCallbackAction::ClearVICIrq   => self.clear_vic_irq(),
            _ => (),
        }

        match on_cia_write
        {
            cia::CIACallbackAction::TriggerCIAIRQ => self.trigger_cia_irq(),
            cia::CIACallbackAction::ClearCIAIRQ   => self.clear_cia_irq(),
            cia::CIACallbackAction::TriggerNMI    => self.trigger_nmi(),
            cia::CIACallbackAction::ClearNMI      => self.clear_nmi(),
            _ => (),
        }

        mem_write_ok
    }

    pub fn read_byte(&mut self, addr: u16) -> u8
    {
        let byte: u8;
        let mut on_cia_read: cia::CIACallbackAction = cia::CIACallbackAction::None;

        match addr
        {
            // VIC-II address space
            0xD000...0xD400 => byte = as_mut!(self.vic_ref).read_register(addr),
            // CIA1 address space
            0xDC00...0xDCFF => byte = as_mut!(self.cia1_ref).read_register(addr, &mut on_cia_read),
            // CIA2 address space
            0xDD00...0xDD0F => byte = as_mut!(self.cia2_ref).read_register(addr, &mut on_cia_read),
            _ => byte = as_mut!(self.mem_ref).read_byte(addr)
        }

        match on_cia_read
        {
            cia::CIACallbackAction::TriggerCIAIRQ => self.trigger_cia_irq(),
            cia::CIACallbackAction::ClearCIAIRQ   => self.clear_cia_irq(),
            cia::CIACallbackAction::TriggerNMI    => self.trigger_nmi(),
            cia::CIACallbackAction::ClearNMI      => self.clear_nmi(),
            _ => (),
        }

        byte
    }

    pub fn read_word_le(&self, addr: u16) -> u16
    {
        as_ref!(self.mem_ref).read_word_le(addr)
    }

    pub fn read_word_be(&self, addr: u16) -> u16
    {
        as_ref!(self.mem_ref).read_word_be(addr)
    }

    pub fn write_word_le(&self, addr: u16, value: u16) -> bool
    {
        as_ref!(self.mem_ref).write_word_le(addr, value)
    }

    fn process_nmi(&mut self) -> bool
    {
        // 7 cycles
        if self.nmi
        {
            let curr_pc = self.PC;
            let curr_p = self.P;
            self.push_word(curr_pc);
            self.push_byte(curr_p);
            self.set_status_flag(StatusFlag::InterruptDisable, true);
            self.PC = as_ref!(self.mem_ref).read_word_le(NMI_VECTOR);
            self.nmi = false;
            true
        }
        else
        {
            false
        }
    }

    fn process_irq(&mut self) -> bool
    {
        // 7 cycles
        if (self.cia_irq || self.vic_irq) && !self.get_status_flag(StatusFlag::InterruptDisable)
        {
            self.set_status_flag(StatusFlag::Break, false);
            let curr_pc = self.PC;
            let curr_p = self.P;
            //println!("PC {} P {}", curr_pc, curr_p);
            self.push_word(curr_pc);
            self.push_byte(curr_p);
            self.set_status_flag(StatusFlag::InterruptDisable, true);
            self.PC = as_ref!(self.mem_ref).read_word_le(IRQ_VECTOR);
            self.cia_irq = false;
            self.vic_irq = false;
            true
        }
        else
        {
            false
        }
    }

    pub fn trigger_vic_irq(&mut self)
    {
        // TODO:
        //println!("VIC irq");
        self.vic_irq = true;
    }

    pub fn clear_vic_irq(&mut self)
    {
        // TODO
        self.vic_irq = false;
    }

    pub fn trigger_nmi(&mut self)
    {
        // TODO
        //println!("NMI irq");
        self.nmi = true;
    }

    pub fn clear_nmi(&mut self)
    {
        // TODO
        self.nmi = false;
    }

    pub fn trigger_cia_irq(&mut self)
    {
        // TODO
        //println!("CIA irq");
        self.cia_irq = true;
    }

    pub fn clear_cia_irq(&mut self)
    {
        // TODO
        self.cia_irq = false;
    }

    fn process_op(&mut self, opcode: u8) -> u8
    {
        //utils::debug_instruction(opcode, self);
        self.prev_PC = self.PC;
        match opcodes::get_instruction(opcode, self)
        {
            Some((instruction, num_cycles, addr_mode)) => {
                utils::debug_instruction(opcode, Some((&instruction, num_cycles, &addr_mode)), self);
                instruction.run(&addr_mode, self);
                num_cycles
            },
            None => panic!("No instruction - this should never happen! (0x{:02X} at ${:04X})", opcode, self.PC)
        }
    }
}
<commit_msg>wait specified amount of cycles depending on operation's duration<commit_after>// The CPU
#![allow(non_snake_case)]
extern crate sdl2;
use c64::opcodes;
use c64::memory;
use c64::vic;
use c64::cia;
use std::cell::RefCell;
use std::rc::Rc;

use utils;

pub type CPUShared = Rc<RefCell<CPU>>;

// status flags for P register
pub enum StatusFlag
{
    Carry            = 1 << 0,
    Zero             = 1 << 1,
    InterruptDisable = 1 << 2,
    DecimalMode      = 1 << 3,
    Break            = 1 << 4,
    Unused           = 1 << 5,
    Overflow         = 1 << 6,
    Negative         = 1 << 7,
}

pub static NMI_VECTOR:   u16 = 0xFFFA;
pub static RESET_VECTOR: u16 = 0xFFFC;
pub static IRQ_VECTOR:   u16 = 0xFFFE;

pub struct CPU
{
    pub PC: u16, // program counter
    pub SP: u8,  // stack pointer
    pub P: u8,   // processor status
    pub A: u8,   // accumulator
    pub X: u8,   // index register
    pub Y: u8,   // index register
    pub mem_ref: Option<memory::MemShared>, // reference to shared system memory
    pub vic_ref: Option<vic::VICShared>,
    pub cia1_ref: Option<cia::CIAShared>,
    pub cia2_ref: Option<cia::CIAShared>,
    pub ba_low: bool,  // is BA low?
    pub cia_irq: bool,
    pub vic_irq: bool,
    wait_cycles: u8,
    nmi: bool,
    pub prev_PC: u16, // previous program counter - for debugging
    pub op_debugger: utils::OpDebugger
}

impl CPU
{
    pub fn new_shared() -> CPUShared
    {
        Rc::new(RefCell::new(CPU
        {
            PC: 0,
            SP: 0xFF,
            P: 0,
            A: 0,
            X: 0,
            Y: 0,
            mem_ref: None,
            vic_ref: None,
            cia1_ref: None,
            cia2_ref: None,
            ba_low: false,
            cia_irq: false,
            vic_irq: false,
            wait_cycles: 0,
            nmi: false,
            prev_PC: 0,
            op_debugger: utils::OpDebugger::new()
        }))
    }

    pub fn set_references(&mut self, memref: memory::MemShared, vicref: vic::VICShared, cia1ref: cia::CIAShared, cia2ref: cia::CIAShared)
    {
        self.mem_ref = Some(memref);
        self.vic_ref = Some(vicref);
        self.cia1_ref = Some(cia1ref);
        self.cia2_ref = Some(cia2ref);
    }

    pub fn set_status_flag(&mut self, flag: StatusFlag, value: bool)
    {
        if value { self.P |=   flag as u8;  }
        else     { self.P &= !(flag as u8); }
    }

    pub fn get_status_flag(&mut self, flag: StatusFlag) -> bool
    {
        self.P & flag as u8 != 0x00
    }

    // these flags will be set in tandem quite often
    pub fn set_zn_flags(&mut self, value: u8)
    {
        self.set_status_flag(StatusFlag::Zero, value == 0x00);
        self.set_status_flag(StatusFlag::Negative, (value as i8) < 0);
    }

    pub fn reset(&mut self)
    {
        // reset program counter
        let pc = self.read_word_le(RESET_VECTOR);
        self.PC = pc;
        self.SP = 0xFF;
        self.ba_low = false;
        self.cia_irq = false;
        self.vic_irq = false;
        self.nmi = false;
    }

    pub fn update(&mut self)
    {
        if self.ba_low { return }
        if self.process_nmi() { return }
        if self.process_irq() { return }

        if self.wait_cycles == 0
        {
            let op = self.next_byte();
            self.wait_cycles += self.process_op(op);
        }
        else
        {
            self.wait_cycles -= 1;
        }
    }

    pub fn next_byte(&mut self) -> u8
    {
        let pc = self.PC;
        let op = self.read_byte(pc);
        self.PC += 1;
        op
    }

    pub fn next_word(&mut self) -> u16
    {
        let word = self.read_word_le(self.PC);
        self.PC += 2;
        word
    }

    // stack memory: $0100 - $01FF (256 byes)
    // TODO: some extra message if stack over/underflow occurs? (right now handled by Rust)
    pub fn push_byte(&mut self, value: u8)
    {
        self.SP -= 0x01;
        let newSP = (self.SP + 0x01) as u16;
        self.write_byte(0x0100 + newSP, value);
    }

    pub fn pop_byte(&mut self) -> u8
    {
        let addr = 0x0100 + (self.SP + 0x01) as u16;
        let value = self.read_byte(addr);
        self.SP += 0x01;
        value
    }

    pub fn push_word(&mut self, value: u16)
    {
        self.SP -= 0x02;
        self.write_word_le(0x0100 + (self.SP + 0x01) as u16, value);
    }

    pub fn pop_word(&mut self) -> u16
    {
        let value = self.read_word_le(0x0100 + (self.SP + 0x01) as u16);
        self.SP += 0x02;
        value
    }

    pub fn write_byte(&mut self, addr: u16, value: u8) -> bool
    {
        let mut on_vic_write: vic::VICCallbackAction = vic::VICCallbackAction::None;
        let mut on_cia_write: cia::CIACallbackAction = cia::CIACallbackAction::None;
        let mem_write_ok: bool;
        match addr
        {
            // VIC-II address space
            0xD000...0xD400 => mem_write_ok = as_mut!(self.vic_ref).write_register(addr, value, &mut on_vic_write),
            // CIA1 address space
            0xDC00...0xDCFF => mem_write_ok = as_mut!(self.cia1_ref).write_register(addr, value, &mut on_cia_write),
            // CIA2 address space
            0xDD00...0xDD0F => mem_write_ok = as_mut!(self.cia2_ref).write_register(addr, value, &mut on_cia_write),
            _ => mem_write_ok = as_mut!(self.mem_ref).write_byte(addr, value),
        }

        // on VIC register write perform necessary action on the CPU
        match on_vic_write
        {
            vic::VICCallbackAction::TriggerVICIrq => self.trigger_vic_irq(),
            vic::VICCallbackAction::ClearVICIrq   => self.clear_vic_irq(),
            _ => (),
        }

        match on_cia_write
        {
            cia::CIACallbackAction::TriggerCIAIRQ => self.trigger_cia_irq(),
            cia::CIACallbackAction::ClearCIAIRQ   => self.clear_cia_irq(),
            cia::CIACallbackAction::TriggerNMI    => self.trigger_nmi(),
            cia::CIACallbackAction::ClearNMI      => self.clear_nmi(),
            _ => (),
        }

        mem_write_ok
    }

    pub fn read_byte(&mut self, addr: u16) -> u8
    {
        let byte: u8;
        let mut on_cia_read: cia::CIACallbackAction = cia::CIACallbackAction::None;

        match addr
        {
            // VIC-II address space
            0xD000...0xD400 => byte = as_mut!(self.vic_ref).read_register(addr),
            // CIA1 address space
            0xDC00...0xDCFF => byte = as_mut!(self.cia1_ref).read_register(addr, &mut on_cia_read),
            // CIA2 address space
            0xDD00...0xDD0F => byte = as_mut!(self.cia2_ref).read_register(addr, &mut on_cia_read),
            _ => byte = as_mut!(self.mem_ref).read_byte(addr)
        }

        match on_cia_read
        {
            cia::CIACallbackAction::TriggerCIAIRQ => self.trigger_cia_irq(),
            cia::CIACallbackAction::ClearCIAIRQ   => self.clear_cia_irq(),
            cia::CIACallbackAction::TriggerNMI    => self.trigger_nmi(),
            cia::CIACallbackAction::ClearNMI      => self.clear_nmi(),
            _ => (),
        }

        byte
    }

    pub fn read_word_le(&self, addr: u16) -> u16
    {
        as_ref!(self.mem_ref).read_word_le(addr)
    }

    pub fn read_word_be(&self, addr: u16) -> u16
    {
        as_ref!(self.mem_ref).read_word_be(addr)
    }

    pub fn write_word_le(&self, addr: u16, value: u16) -> bool
    {
        as_ref!(self.mem_ref).write_word_le(addr, value)
    }

    fn process_nmi(&mut self) -> bool
    {
        // 7 cycles
        if self.nmi
        {
            let curr_pc = self.PC;
            let curr_p = self.P;
            self.push_word(curr_pc);
            self.push_byte(curr_p);
            self.set_status_flag(StatusFlag::InterruptDisable, true);
            self.PC = as_ref!(self.mem_ref).read_word_le(NMI_VECTOR);
            self.nmi = false;
            true
        }
        else
        {
            false
        }
    }

    fn process_irq(&mut self) -> bool
    {
        // 7 cycles
        if (self.cia_irq || self.vic_irq) && !self.get_status_flag(StatusFlag::InterruptDisable)
        {
            self.set_status_flag(StatusFlag::Break, false);
            let curr_pc = self.PC;
            let curr_p = self.P;
            //println!("PC {} P {}", curr_pc, curr_p);
            self.push_word(curr_pc);
            self.push_byte(curr_p);
            self.set_status_flag(StatusFlag::InterruptDisable, true);
            self.PC = as_ref!(self.mem_ref).read_word_le(IRQ_VECTOR);
            self.cia_irq = false;
            self.vic_irq = false;
            true
        }
        else
        {
            false
        }
    }

    pub fn trigger_vic_irq(&mut self)
    {
        // TODO:
        //println!("VIC irq");
        self.vic_irq = true;
    }

    pub fn clear_vic_irq(&mut self)
    {
        // TODO
        self.vic_irq = false;
    }

    pub fn trigger_nmi(&mut self)
    {
        // TODO
        //println!("NMI irq");
        self.nmi = true;
    }

    pub fn clear_nmi(&mut self)
    {
        // TODO
        self.nmi = false;
    }

    pub fn trigger_cia_irq(&mut self)
    {
        // TODO
        //println!("CIA irq");
        self.cia_irq = true;
    }

    pub fn clear_cia_irq(&mut self)
    {
        // TODO
        self.cia_irq = false;
    }

    fn process_op(&mut self, opcode: u8) -> u8
    {
        //utils::debug_instruction(opcode, self);
        self.prev_PC = self.PC;
        match opcodes::get_instruction(opcode, self)
        {
            Some((instruction, num_cycles, addr_mode)) => {
                //utils::debug_instruction(opcode, Some((&instruction, num_cycles, &addr_mode)), self);
                instruction.run(&addr_mode, self);
                num_cycles
            },
            None => panic!("No instruction - this should never happen! (0x{:02X} at ${:04X})", opcode, self.PC)
        }
    }
}
<|endoftext|>


<commit_before>#![crate_id="find_max"]
//! Test various syntaxes to find the maximum value of a vector using generic function.
//!
//! @license MIT license <http://www.opensource.org/licenses/mit-license.php>

#[cfg(test)]
extern crate test;

#[cfg(test)]
use test::Bencher;

/**
 * Code from Rust MeetUp (March, 31st 2014) at Mozilla Space, Paris.
 * https://reps.mozilla.org/e/meetup-rust-paris-02/
 */
fn find_max1<'a, T: Ord>(lst: &'a Vec<T>) -> Option<&'a T> {
	let mut max = None;

	for i in lst.iter() {
		max = match max {
			None => Some(i),
			Some(ref m) if i > *m => Some(i),
			_ => max
		}
	}
	max
}

/**
 * Using a closure.
 *
 * Inspired by tutorial "15 Closure"
 * http://doc.rust-lang.org/tutorial.html#closures
 */
fn find_max2<'a, T: Ord>(lst: &'a Vec<T>) -> Option<&'a T> {
	let mut max = None;

	let find_max = |i: &'a T| {
		max = match max {
			None => Some(i),
			Some(ref m) if i > *m => Some(i),
			_ => max
		}
	};
	for x in lst.iter() {
		find_max(x);
	}

	max
}

/**
 * Using a closure and .map().
 */
fn find_max3<'a, T: Ord>(lst: &'a Vec<T>) -> Option<&'a T> {
	let mut max = None;

	let find_max = |i: &'a T| {
		max = match max {
			None => Some(i),
			Some(ref m) if i > *m => Some(i),
			_ => max
		};
		max
	};
	lst.iter().map(find_max).last().unwrap()
}

/**
 * Using std lib
 */
fn find_maxstd<'a, T: Ord>(lst: &'a Vec<T>) -> Option<&'a T> {
	lst.iter().max_by(|x| *x)
}

#[test]
fn test_find_max1() {
	let v = vec!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
	let nine = 9;
	assert_eq!(Some(&nine), find_max1(&v));
}

#[test]
fn test_find_max2() {
	let v = vec!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
	let nine = 9;
	assert_eq!(Some(&nine), find_max2(&v));
}

#[test]
fn test_find_max3() {
	let v = vec!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
	let nine = 9;
	assert_eq!(Some(&nine), find_max3(&v));
}

#[test]
fn test_find_maxstd() {
	let v = vec!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
	let nine = 9;
	assert_eq!(Some(&nine), find_maxstd(&v));
}

#[bench]
fn bench_find_max1(b: &mut Bencher) {
	let v = vec!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
	b.iter(|| {
		find_max1(&v);
	});
}

#[bench]
fn bench_find_max2(b: &mut Bencher) {
	let v = vec!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
	b.iter(|| {
		find_max2(&v);
	});
}

#[bench]
fn bench_find_max3(b: &mut Bencher) {
	let v = vec!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
	b.iter(|| {
		find_max3(&v);
	});
}

#[bench]
fn bench_find_maxstd(b: &mut Bencher) {
	let v = vec!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
	b.iter(|| {
		find_maxstd(&v);
	});
}

#[cfg(not(test))]
fn main () {
	let int_v = vec!(5, 2, 0, 8, 2);
	println!("find_max1 -> {}", find_max1(&int_v));
	println!("find_max2 -> {}", find_max2(&int_v));
	println!("find_max3 -> {}", find_max3(&int_v));
	println!("find_maxstd -> {}", find_maxstd(&int_v));
	let v = vec!("qehgesrhsetha", "bqthst", "cthersth");
	let b = find_max3(&v);
	println!("{}", b);

	println!("{}", v);
	println!("{}", b);
}
<commit_msg>Changes to version 0.11-pre (dbd29ea 2014-06-14 08:46:48 +0000) (api-std-vec.rs not corrected)<commit_after>#![crate_id="find_max"]
//! Test various syntaxes to find the maximum value of a vector using generic function.
//!
//! @license MIT license <http://www.opensource.org/licenses/mit-license.php>

#[cfg(test)]
extern crate test;

#[cfg(test)]
use test::Bencher;

/**
 * Code from Rust MeetUp (March, 31st 2014) at Mozilla Space, Paris.
 * https://reps.mozilla.org/e/meetup-rust-paris-02/
 */
fn find_max1<'a, T: Ord>(lst: &'a Vec<T>) -> Option<&'a T> {
	let mut max = None;

	for i in lst.iter() {
		max = match max {
			None => Some(i),
			Some(ref m) if i > *m => Some(i),
			_ => max
		}
	}
	max
}

/**
 * Using a closure.
 *
 * Inspired by tutorial "15 Closure"
 * http://doc.rust-lang.org/tutorial.html#closures
 */
fn find_max2<'a, T: Ord>(lst: &'a Vec<T>) -> Option<&'a T> {
	let mut max = None;

	// huon said:
	// place the closure and the loop into its own scope
	// to constrain the borrow from the closure.
	// (to be able to modify `max` it has to take an `&mut` borrow to it)
	{
		let find_max = |i: &'a T| {
			max = match max {
				None => Some(i),
				Some(ref m) if i > *m => Some(i),
				_ => max
			}
		};
		for x in lst.iter() {
			find_max(x);
		}
	}

	max
}

/**
 * Using a closure and .map().
 */
fn find_max3<'a, T: Ord>(lst: &'a Vec<T>) -> Option<&'a T> {
	let mut max = None;

	let find_max = |i: &'a T| {
		max = match max {
			None => Some(i),
			Some(ref m) if i > *m => Some(i),
			_ => max
		};
		max
	};
	lst.iter().map(find_max).last().unwrap()
}

/**
 * Using std lib
 */
fn find_maxstd<'a, T: Ord>(lst: &'a Vec<T>) -> Option<&'a T> {
	lst.iter().max_by(|x| *x)
}

#[test]
fn test_find_max1() {
	let v = vec!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
	let nine = 9;
	assert_eq!(Some(&nine), find_max1(&v));
}

#[test]
fn test_find_max2() {
	let v = vec!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
	let nine = 9;
	assert_eq!(Some(&nine), find_max2(&v));
}

#[test]
fn test_find_max3() {
	let v = vec!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
	let nine = 9;
	assert_eq!(Some(&nine), find_max3(&v));
}

#[test]
fn test_find_maxstd() {
	let v = vec!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
	let nine = 9;
	assert_eq!(Some(&nine), find_maxstd(&v));
}

#[bench]
fn bench_find_max1(b: &mut Bencher) {
	let v = vec!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
	b.iter(|| {
		find_max1(&v);
	});
}

#[bench]
fn bench_find_max2(b: &mut Bencher) {
	let v = vec!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
	b.iter(|| {
		find_max2(&v);
	});
}

#[bench]
fn bench_find_max3(b: &mut Bencher) {
	let v = vec!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
	b.iter(|| {
		find_max3(&v);
	});
}

#[bench]
fn bench_find_maxstd(b: &mut Bencher) {
	let v = vec!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
	b.iter(|| {
		find_maxstd(&v);
	});
}

#[cfg(not(test))]
fn main () {
	let int_v = vec!(5, 2, 0, 8, 2);
	println!("find_max1 -> {}", find_max1(&int_v));
	println!("find_max2 -> {}", find_max2(&int_v));
	println!("find_max3 -> {}", find_max3(&int_v));
	println!("find_maxstd -> {}", find_maxstd(&int_v));
	let v = vec!("qehgesrhsetha", "bqthst", "cthersth");
	let b = find_max3(&v);
	println!("{}", b);

	println!("{}", v);
	println!("{}", b);
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementations of things like `Eq` for fixed-length arrays
//! up to a certain length. Eventually we should able to generalize
//! to all lengths.

#![unstable(feature = "core")] // not yet reviewed

#![doc(primitive = "array")]

use clone::Clone;
use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
use fmt;
use hash::{Hash, self};
use iter::IntoIterator;
use marker::{Copy, Sized};
use option::Option;
use slice::{Iter, IterMut, SliceExt};

/// Utility trait implemented only on arrays of fixed size
///
/// This trait can be used to implement other traits on fixed-size arrays
/// without causing much metadata bloat.
#[unstable(feature = "core")]
pub trait FixedSizeArray<T> {
    /// Converts the array to immutable slice
    fn as_slice(&self) -> &[T];
    /// Converts the array to mutable slice
    fn as_mut_slice(&mut self) -> &mut [T];
}

// macro for implementing n-ary tuple functions and operations
macro_rules! array_impls {
    ($($N:expr)+) => {
        $(
            #[unstable(feature = "core")]
            impl<T> FixedSizeArray<T> for [T; $N] {
                #[inline]
                fn as_slice(&self) -> &[T] {
                    &self[..]
                }
                #[inline]
                fn as_mut_slice(&mut self) -> &mut [T] {
                    &mut self[..]
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:Copy> Clone for [T; $N] {
                fn clone(&self) -> [T; $N] {
                    *self
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T: Hash> Hash for [T; $N] {
                fn hash<H: hash::Hasher>(&self, state: &mut H) {
                    Hash::hash(&self[..], state)
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T: fmt::Debug> fmt::Debug for [T; $N] {
                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                    fmt::Debug::fmt(&&self[..], f)
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<'a, T> IntoIterator for &'a [T; $N] {
                type Item = &'a T;
                type IntoIter = Iter<'a, T>;

                fn into_iter(self) -> Iter<'a, T> {
                    self.iter()
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<'a, T> IntoIterator for &'a mut [T; $N] {
                type Item = &'a mut T;
                type IntoIter = IterMut<'a, T>;

                fn into_iter(self) -> IterMut<'a, T> {
                    self.iter_mut()
                }
            }

            // NOTE: some less important impls are omitted to reduce code bloat
            __impl_slice_eq1! { [A; $N], [B; $N] }
            __impl_slice_eq2! { [A; $N], [B] }
            __impl_slice_eq2! { [A; $N], &'b [B] }
            __impl_slice_eq2! { [A; $N], &'b mut [B] }
            // __impl_slice_eq2! { [A; $N], &'b [B; $N] }
            // __impl_slice_eq2! { [A; $N], &'b mut [B; $N] }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:Eq> Eq for [T; $N] { }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:PartialOrd> PartialOrd for [T; $N] {
                #[inline]
                fn partial_cmp(&self, other: &[T; $N]) -> Option<Ordering> {
                    PartialOrd::partial_cmp(&&self[..], &&other[..])
                }
                #[inline]
                fn lt(&self, other: &[T; $N]) -> bool {
                    PartialOrd::lt(&&self[..], &&other[..])
                }
                #[inline]
                fn le(&self, other: &[T; $N]) -> bool {
                    PartialOrd::le(&&self[..], &&other[..])
                }
                #[inline]
                fn ge(&self, other: &[T; $N]) -> bool {
                    PartialOrd::ge(&&self[..], &&other[..])
                }
                #[inline]
                fn gt(&self, other: &[T; $N]) -> bool {
                    PartialOrd::gt(&&self[..], &&other[..])
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:Ord> Ord for [T; $N] {
                #[inline]
                fn cmp(&self, other: &[T; $N]) -> Ordering {
                    Ord::cmp(&&self[..], &&other[..])
                }
            }
        )+
    }
}

array_impls! {
     0  1  2  3  4  5  6  7  8  9
    10 11 12 13 14 15 16 17 18 19
    20 21 22 23 24 25 26 27 28 29
    30 31 32
}
<commit_msg>Implement AsRef and AsMut for fixed-sized arrays<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementations of things like `Eq` for fixed-length arrays
//! up to a certain length. Eventually we should able to generalize
//! to all lengths.

#![unstable(feature = "core")] // not yet reviewed

#![doc(primitive = "array")]

use clone::Clone;
use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
use convert::{AsRef, AsMut};
use fmt;
use hash::{Hash, self};
use iter::IntoIterator;
use marker::{Copy, Sized};
use option::Option;
use slice::{Iter, IterMut, SliceExt};

/// Utility trait implemented only on arrays of fixed size
///
/// This trait can be used to implement other traits on fixed-size arrays
/// without causing much metadata bloat.
#[unstable(feature = "core")]
pub trait FixedSizeArray<T> {
    /// Converts the array to immutable slice
    fn as_slice(&self) -> &[T];
    /// Converts the array to mutable slice
    fn as_mut_slice(&mut self) -> &mut [T];
}

// macro for implementing n-ary tuple functions and operations
macro_rules! array_impls {
    ($($N:expr)+) => {
        $(
            #[unstable(feature = "core")]
            impl<T> FixedSizeArray<T> for [T; $N] {
                #[inline]
                fn as_slice(&self) -> &[T] {
                    &self[..]
                }
                #[inline]
                fn as_mut_slice(&mut self) -> &mut [T] {
                    &mut self[..]
                }
            }

            #[unstable(feature = "array_as_ref",
                       reason = "should ideally be implemented for all fixed-sized arrays")]
            impl<T> AsRef<[T]> for [T; $N] {
                #[inline]
                fn as_ref(&self) -> &[T] {
                    &self[..]
                }
            }

            #[unstable(feature = "array_as_ref",
                       reason = "should ideally be implemented for all fixed-sized arrays")]
            impl<T> AsMut<[T]> for [T; $N] {
                #[inline]
                fn as_mut(&mut self) -> &mut [T] {
                    &mut self[..]
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:Copy> Clone for [T; $N] {
                fn clone(&self) -> [T; $N] {
                    *self
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T: Hash> Hash for [T; $N] {
                fn hash<H: hash::Hasher>(&self, state: &mut H) {
                    Hash::hash(&self[..], state)
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T: fmt::Debug> fmt::Debug for [T; $N] {
                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                    fmt::Debug::fmt(&&self[..], f)
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<'a, T> IntoIterator for &'a [T; $N] {
                type Item = &'a T;
                type IntoIter = Iter<'a, T>;

                fn into_iter(self) -> Iter<'a, T> {
                    self.iter()
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<'a, T> IntoIterator for &'a mut [T; $N] {
                type Item = &'a mut T;
                type IntoIter = IterMut<'a, T>;

                fn into_iter(self) -> IterMut<'a, T> {
                    self.iter_mut()
                }
            }

            // NOTE: some less important impls are omitted to reduce code bloat
            __impl_slice_eq1! { [A; $N], [B; $N] }
            __impl_slice_eq2! { [A; $N], [B] }
            __impl_slice_eq2! { [A; $N], &'b [B] }
            __impl_slice_eq2! { [A; $N], &'b mut [B] }
            // __impl_slice_eq2! { [A; $N], &'b [B; $N] }
            // __impl_slice_eq2! { [A; $N], &'b mut [B; $N] }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:Eq> Eq for [T; $N] { }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:PartialOrd> PartialOrd for [T; $N] {
                #[inline]
                fn partial_cmp(&self, other: &[T; $N]) -> Option<Ordering> {
                    PartialOrd::partial_cmp(&&self[..], &&other[..])
                }
                #[inline]
                fn lt(&self, other: &[T; $N]) -> bool {
                    PartialOrd::lt(&&self[..], &&other[..])
                }
                #[inline]
                fn le(&self, other: &[T; $N]) -> bool {
                    PartialOrd::le(&&self[..], &&other[..])
                }
                #[inline]
                fn ge(&self, other: &[T; $N]) -> bool {
                    PartialOrd::ge(&&self[..], &&other[..])
                }
                #[inline]
                fn gt(&self, other: &[T; $N]) -> bool {
                    PartialOrd::gt(&&self[..], &&other[..])
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:Ord> Ord for [T; $N] {
                #[inline]
                fn cmp(&self, other: &[T; $N]) -> Ordering {
                    Ord::cmp(&&self[..], &&other[..])
                }
            }
        )+
    }
}

array_impls! {
     0  1  2  3  4  5  6  7  8  9
    10 11 12 13 14 15 16 17 18 19
    20 21 22 23 24 25 26 27 28 29
    30 31 32
}
<|endoftext|>


<commit_before>//!
//! Raw communication channel to the FUSE kernel driver.
//!

use std::{ffi, os};
use std::ffi::CString;
use std::old_path::PosixPath;
use libc::{c_int, c_void, size_t};
use fuse::{fuse_args, fuse_mount_compat25, fuse_unmount_compat22};

// Libc provides iovec based I/O using readv and writev functions
#[allow(dead_code, non_camel_case_types)]
mod libc {
    use libc::{c_char, c_int, c_void, size_t, ssize_t};

    /// Iovec data structure for readv and writev calls.
    #[repr(C)]
    pub struct iovec {
        pub iov_base: *const c_void,
        pub iov_len: size_t,
    }

    extern "system" {
        /// Read data from fd into multiple buffers
        pub fn readv (fd: c_int, iov: *mut iovec, iovcnt: c_int) -> ssize_t;
        /// Write data from multiple buffers to fd
        pub fn writev (fd: c_int, iov: *const iovec, iovcnt: c_int) -> ssize_t;

        pub fn realpath (file_name: *const c_char, resolved_name: *mut c_char) -> *const c_char;

        pub fn unmount(dir: *const c_char, flags: c_int) -> c_int;
    }

    /// Max length for path names. 4096 should be reasonable safe (OS X uses 1024, Linux uses 4096)
    pub const PATH_MAX: usize = 4096;
}

/// Wrapper around libc's realpath.  Returns the errno value if the real path cannot be obtained.
/// FIXME: Use Rust's realpath method once available in std (see also https://github.com/mozilla/rust/issues/11857)
fn real_path (path: &PosixPath) -> Result<PosixPath, i32> {
    let cpath = CString::from_slice(path.as_vec());
    let mut resolved = [0; libc::PATH_MAX];
    unsafe {
        if libc::realpath(cpath.as_ptr(), resolved.as_mut_ptr()).is_null() {
            Err(os::errno())
        } else {
            Ok(PosixPath::new(ffi::c_str_to_bytes(&resolved.as_ptr())))
        }
    }
}

/// Helper function to provide options as a fuse_args struct
/// (which contains an argc count and an argv pointer)
fn with_fuse_args<T, F: FnOnce(&fuse_args) -> T> (options: &[&[u8]], f: F) -> T {
    let args: Vec<CString> = Some(b"rust-fuse").iter().chain(options.iter()).map(|s| CString::from_slice(s)).collect();
    let argptrs: Vec<*const i8> = args.iter().map(|s| s.as_ptr()).collect();
    f(&fuse_args { argc: argptrs.len() as i32, argv: argptrs.as_ptr(), allocated: 0 })
}

/// A raw communication channel to the FUSE kernel driver
pub struct Channel {
    mountpoint: Path,
    fd: c_int,
}

impl Channel {
    /// Create a new communication channel to the kernel driver by mounting the
    /// given path. The kernel driver will delegate filesystem operations of
    /// the given path to the channel. If the channel is dropped, the path is
    /// unmounted.
    pub fn new (mountpoint: &Path, options: &[&[u8]]) -> Result<Channel, i32> {
        real_path(mountpoint).and_then(|mountpoint| {
            with_fuse_args(options, |args| {
                let mnt = CString::from_slice(mountpoint.as_vec()).as_ptr();
                let fd = unsafe { fuse_mount_compat25(mnt, args) };
                if fd < 0 {
                    Err(os::errno())
                } else {
                    Ok(Channel { mountpoint: mountpoint.clone(), fd: fd })
                }
            })
        })
    }

    /// Receives data up to the capacity of the given buffer (can block).
    pub fn receive (&self, buffer: &mut Vec<u8>) -> Result<(), i32> {
        let rc = unsafe { ::libc::read(self.fd, buffer.as_ptr() as *mut c_void, buffer.capacity() as size_t) };
        if rc < 0 {
            Err(os::errno())
        } else {
            unsafe { buffer.set_len(rc as usize); }
            Ok(())
        }
    }

    /// Returns a sender object for this channel. The sender object can be
    /// used to send to the channel. Multiple sender objects can be used
    /// and they can safely be sent to other threads.
    pub fn sender (&self) -> ChannelSender {
        // Since write/writev syscalls are threadsafe, we can simply create
        // a sender by using the same fd and use it in other threads. Only
        // the channel closes the fd when dropped. If any sender is used after
        // dropping the channel, it'll return an EBADF error.
        ChannelSender { fd: self.fd }
    }
}

impl Drop for Channel {
    fn drop (&mut self) {
        // TODO: send ioctl FUSEDEVIOCSETDAEMONDEAD on OS X before closing the fd
        // Close the communication channel to the kernel driver
        // (closing it before unnmount prevents sync unmount deadlock)
        unsafe { ::libc::close(self.fd); }
        // Unmount this channel's mount point
        unmount(&self.mountpoint);
    }
}

#[derive(Copy)]
pub struct ChannelSender {
    fd: c_int,
}

impl ChannelSender {
    /// Send all data in the slice of slice of bytes in a single write (can block).
    pub fn send (&self, buffer: &[&[u8]]) -> Result<(), i32> {
        let iovecs: Vec<libc::iovec> = buffer.iter().map(|d| {
            libc::iovec { iov_base: d.as_ptr() as *const c_void, iov_len: d.len() as size_t }
        }).collect();
        let rc = unsafe { libc::writev(self.fd, iovecs.as_ptr(), iovecs.len() as c_int) };
        if rc < 0 {
            Err(os::errno())
        } else {
            Ok(())
        }
    }
}

/// Unmount an arbitrary mount point
pub fn unmount (mountpoint: &Path) {
    // On OS X, fuse_unmount_compat22 attempts to call realpath, which in turn calls into the filesystem.
    // If the filesystem returns an error, the unmount does not take place, with no indication of the error
    // available to the caller.  So we call unmount directly, which is what osxfuse does anyway, since
    // we already converted to the real path when we first mounted.
    let mnt = CString::from_slice(mountpoint.as_vec()).as_ptr();
    if cfg!(target_os = "macos") {
        unsafe { libc::unmount(mnt, 0); }
    } else {
        unsafe { fuse_unmount_compat22(mnt); }
    }
}

#[cfg(test)]
mod test {
    use super::with_fuse_args;
    use std::ffi;

    #[test]
    fn fuse_args () {
        with_fuse_args(&[b"foo", b"bar"], |args| {
            assert!(args.argc == 3);
            assert_eq!(unsafe { ffi::c_str_to_bytes(&*args.argv.offset(0)) }, b"rust-fuse");
            assert_eq!(unsafe { ffi::c_str_to_bytes(&*args.argv.offset(1)) }, b"foo");
            assert_eq!(unsafe { ffi::c_str_to_bytes(&*args.argv.offset(2)) }, b"bar");
        });
    }
}
<commit_msg>Use new CString/CStr<commit_after>//!
//! Raw communication channel to the FUSE kernel driver.
//!

use std::os;
use std::ffi::{CString, CStr};
use std::old_path::PosixPath;
use libc::{c_int, c_void, size_t};
use fuse::{fuse_args, fuse_mount_compat25, fuse_unmount_compat22};

// Libc provides iovec based I/O using readv and writev functions
#[allow(dead_code, non_camel_case_types)]
mod libc {
    use libc::{c_char, c_int, c_void, size_t, ssize_t};

    /// Iovec data structure for readv and writev calls.
    #[repr(C)]
    pub struct iovec {
        pub iov_base: *const c_void,
        pub iov_len: size_t,
    }

    extern "system" {
        /// Read data from fd into multiple buffers
        pub fn readv (fd: c_int, iov: *mut iovec, iovcnt: c_int) -> ssize_t;
        /// Write data from multiple buffers to fd
        pub fn writev (fd: c_int, iov: *const iovec, iovcnt: c_int) -> ssize_t;

        pub fn realpath (file_name: *const c_char, resolved_name: *mut c_char) -> *const c_char;

        pub fn unmount(dir: *const c_char, flags: c_int) -> c_int;
    }

    /// Max length for path names. 4096 should be reasonable safe (OS X uses 1024, Linux uses 4096)
    pub const PATH_MAX: usize = 4096;
}

/// Wrapper around libc's realpath.  Returns the errno value if the real path cannot be obtained.
/// FIXME: Use Rust's realpath method once available in std (see also https://github.com/mozilla/rust/issues/11857)
fn real_path (path: &PosixPath) -> Result<PosixPath, i32> {
    let cpath = CString::new(path.as_vec()).unwrap();
    let mut resolved = [0; libc::PATH_MAX];
    unsafe {
        if libc::realpath(cpath.as_ptr(), resolved.as_mut_ptr()).is_null() {
            Err(os::errno())
        } else {
            Ok(PosixPath::new(CStr::from_ptr(resolved.as_ptr()).to_bytes()))
        }
    }
}

/// Helper function to provide options as a fuse_args struct
/// (which contains an argc count and an argv pointer)
fn with_fuse_args<T, F: FnOnce(&fuse_args) -> T> (options: &[&[u8]], f: F) -> T {
    let args: Vec<CString> = Some(b"rust-fuse").iter().chain(options.iter()).map(|s| CString::new(*s).unwrap()).collect();
    let argptrs: Vec<*const i8> = args.iter().map(|s| s.as_ptr()).collect();
    f(&fuse_args { argc: argptrs.len() as i32, argv: argptrs.as_ptr(), allocated: 0 })
}

/// A raw communication channel to the FUSE kernel driver
pub struct Channel {
    mountpoint: Path,
    fd: c_int,
}

impl Channel {
    /// Create a new communication channel to the kernel driver by mounting the
    /// given path. The kernel driver will delegate filesystem operations of
    /// the given path to the channel. If the channel is dropped, the path is
    /// unmounted.
    pub fn new (mountpoint: &Path, options: &[&[u8]]) -> Result<Channel, i32> {
        real_path(mountpoint).and_then(|mountpoint| {
            with_fuse_args(options, |args| {
                let mnt = CString::new(mountpoint.as_vec()).unwrap().as_ptr();
                let fd = unsafe { fuse_mount_compat25(mnt, args) };
                if fd < 0 {
                    Err(os::errno())
                } else {
                    Ok(Channel { mountpoint: mountpoint.clone(), fd: fd })
                }
            })
        })
    }

    /// Receives data up to the capacity of the given buffer (can block).
    pub fn receive (&self, buffer: &mut Vec<u8>) -> Result<(), i32> {
        let rc = unsafe { ::libc::read(self.fd, buffer.as_ptr() as *mut c_void, buffer.capacity() as size_t) };
        if rc < 0 {
            Err(os::errno())
        } else {
            unsafe { buffer.set_len(rc as usize); }
            Ok(())
        }
    }

    /// Returns a sender object for this channel. The sender object can be
    /// used to send to the channel. Multiple sender objects can be used
    /// and they can safely be sent to other threads.
    pub fn sender (&self) -> ChannelSender {
        // Since write/writev syscalls are threadsafe, we can simply create
        // a sender by using the same fd and use it in other threads. Only
        // the channel closes the fd when dropped. If any sender is used after
        // dropping the channel, it'll return an EBADF error.
        ChannelSender { fd: self.fd }
    }
}

impl Drop for Channel {
    fn drop (&mut self) {
        // TODO: send ioctl FUSEDEVIOCSETDAEMONDEAD on OS X before closing the fd
        // Close the communication channel to the kernel driver
        // (closing it before unnmount prevents sync unmount deadlock)
        unsafe { ::libc::close(self.fd); }
        // Unmount this channel's mount point
        unmount(&self.mountpoint);
    }
}

#[derive(Copy)]
pub struct ChannelSender {
    fd: c_int,
}

impl ChannelSender {
    /// Send all data in the slice of slice of bytes in a single write (can block).
    pub fn send (&self, buffer: &[&[u8]]) -> Result<(), i32> {
        let iovecs: Vec<libc::iovec> = buffer.iter().map(|d| {
            libc::iovec { iov_base: d.as_ptr() as *const c_void, iov_len: d.len() as size_t }
        }).collect();
        let rc = unsafe { libc::writev(self.fd, iovecs.as_ptr(), iovecs.len() as c_int) };
        if rc < 0 {
            Err(os::errno())
        } else {
            Ok(())
        }
    }
}

/// Unmount an arbitrary mount point
pub fn unmount (mountpoint: &Path) {
    // On OS X, fuse_unmount_compat22 attempts to call realpath, which in turn calls into the filesystem.
    // If the filesystem returns an error, the unmount does not take place, with no indication of the error
    // available to the caller.  So we call unmount directly, which is what osxfuse does anyway, since
    // we already converted to the real path when we first mounted.
    let mnt = CString::new(mountpoint.as_vec()).unwrap().as_ptr();
    if cfg!(target_os = "macos") {
        unsafe { libc::unmount(mnt, 0); }
    } else {
        unsafe { fuse_unmount_compat22(mnt); }
    }
}

#[cfg(test)]
mod test {
    use super::with_fuse_args;
    use std::ffi::CStr;

    #[test]
    fn fuse_args () {
        with_fuse_args(&[b"foo", b"bar"], |args| {
            assert!(args.argc == 3);
            assert_eq!(unsafe { CStr::from_ptr(*args.argv.offset(0)).to_bytes() }, b"rust-fuse");
            assert_eq!(unsafe { CStr::from_ptr(*args.argv.offset(1)).to_bytes() }, b"foo");
            assert_eq!(unsafe { CStr::from_ptr(*args.argv.offset(2)).to_bytes() }, b"bar");
        });
    }
}
<|endoftext|>


<commit_before>//! Agent memory representation module.

use Parameter;
use ndarray::Array1;

pub enum Trace {
    Accumulating {
        lambda: Parameter,
        eligibility: Array1<f64>,
    },
    Replacing {
        lambda: Parameter,
        eligibility: Array1<f64>,
    },
    Null {
        eligibility: Array1<f64>
    }
    // TODO: Dutch traces (need to be able to share alpha parameter)
}

impl Trace {
    pub fn get(&self) -> Array1<f64> {
        match self {
            &Trace::Accumulating { ref eligibility, .. } |
            &Trace::Replacing { ref eligibility, .. } |
            &Trace::Null { ref eligibility } => eligibility.clone(),
        }
    }

    pub fn decay(&mut self, rate: f64) {
        match self {
            &mut Trace::Accumulating { ref mut eligibility, lambda } |
            &mut Trace::Replacing { ref mut eligibility, lambda } => {
                *eligibility *= rate * lambda;
            },
            &mut Trace::Null { ref mut eligibility } => *eligibility *= rate,
        }
    }

    pub fn update(&mut self, phi: &Array1<f64>) {
        match self {
            &mut Trace::Accumulating { ref mut eligibility, .. } => {
                *eligibility += phi;
            }
            &mut Trace::Replacing { ref mut eligibility, .. } => {
                eligibility.zip_mut_with(phi, |val, &p| { *val = f64::min(1.0, *val + p); });
            },
            &mut Trace::Null { ref mut eligibility } => *eligibility = phi.to_owned(),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::Trace;
    use ndarray::{ArrayBase, arr1};

    #[test]
    fn test_accumulating() {
        let mut trace = Trace::Accumulating {
            lambda: 0.95.into(),
            eligibility: arr1(&[0.0f64; 10]),
        };

        assert_eq!(trace.get(), arr1(&[0.0f64; 10]));

        trace.decay(1.0);
        assert_eq!(trace.get(), arr1(&[0.0f64; 10]));

        trace.update(&arr1(&[1.0f64; 10]));
        assert_eq!(trace.get(), arr1(&[1.0f64; 10]));

        trace.decay(1.0);
        assert_eq!(trace.get(), arr1(&[0.95f64; 10]));

        trace.update(&arr1(&[1.0f64; 10]));
        assert_eq!(trace.get(), arr1(&[1.95f64; 10]));
    }

    #[test]
    fn test_replacing() {
        let mut trace = Trace::Replacing {
            lambda: 0.95.into(),
            eligibility: arr1(&[0.0f64; 10]),
        };

        assert_eq!(trace.get(), arr1(&[0.0f64; 10]));

        trace.decay(1.0);
        assert_eq!(trace.get(), arr1(&[0.0f64; 10]));

        trace.update(&arr1(&[1.0f64; 10]));
        assert_eq!(trace.get(), arr1(&[1.0f64; 10]));

        trace.decay(1.0);
        assert_eq!(trace.get(), arr1(&[0.95f64; 10]));

        trace.update(&arr1(&[1.0f64; 10]));
        assert_eq!(trace.get(), arr1(&[1.0f64; 10]));
    }
}
<commit_msg>feat(agents): add factory methods to `fa::memory::Trace` enum<commit_after>//! Agent memory representation module.

use Parameter;
use ndarray::Array1;

pub enum Trace {
    Accumulating {
        lambda: Parameter,
        eligibility: Array1<f64>,
    },
    Replacing {
        lambda: Parameter,
        eligibility: Array1<f64>,
    },
    Null {
        eligibility: Array1<f64>
    }
    // TODO: Dutch traces (need to be able to share alpha parameter)
}

impl Trace {
    pub fn accumulating<T: Into<Parameter>>(lambda: T, activation: usize) -> Trace {
        Trace::Accumulating {
            lambda: lambda.into(),
            eligibility: Array1::zeros((activation,)),
        }
    }

    pub fn replacing<T: Into<Parameter>>(lambda: T, activation: usize) -> Trace {
        Trace::Replacing {
            lambda: lambda.into(),
            eligibility: Array1::zeros((activation,)),
        }
    }

    pub fn null(activation: usize) -> Trace {
        Trace::Null {
            eligibility: Array1::zeros((activation,)),
        }
    }

    pub fn get(&self) -> Array1<f64> {
        match self {
            &Trace::Accumulating { ref eligibility, .. } |
            &Trace::Replacing { ref eligibility, .. } |
            &Trace::Null { ref eligibility } => eligibility.clone(),
        }
    }

    pub fn decay(&mut self, rate: f64) {
        match self {
            &mut Trace::Accumulating { ref mut eligibility, lambda } |
            &mut Trace::Replacing { ref mut eligibility, lambda } => {
                *eligibility *= rate*lambda;
            },
            &mut Trace::Null { ref mut eligibility } => *eligibility *= rate,
        }
    }

    pub fn update(&mut self, phi: &Array1<f64>) {
        match self {
            &mut Trace::Accumulating { ref mut eligibility, .. } => {
                *eligibility += phi;
            }
            &mut Trace::Replacing { ref mut eligibility, .. } => {
                eligibility.zip_mut_with(phi, |val, &p| {
                    *val = f64::max(-1.0, f64::min(1.0, *val + p));
                });
            },
            &mut Trace::Null { ref mut eligibility } => *eligibility = phi.to_owned(),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::Trace;
    use ndarray::{ArrayBase, arr1};

    #[test]
    fn test_accumulating() {
        let mut trace = Trace::Accumulating {
            lambda: 0.95.into(),
            eligibility: arr1(&[0.0f64; 10]),
        };

        assert_eq!(trace.get(), arr1(&[0.0f64; 10]));

        trace.decay(1.0);
        assert_eq!(trace.get(), arr1(&[0.0f64; 10]));

        trace.update(&arr1(&[1.0f64; 10]));
        assert_eq!(trace.get(), arr1(&[1.0f64; 10]));

        trace.decay(1.0);
        assert_eq!(trace.get(), arr1(&[0.95f64; 10]));

        trace.update(&arr1(&[1.0f64; 10]));
        assert_eq!(trace.get(), arr1(&[1.95f64; 10]));
    }

    #[test]
    fn test_replacing() {
        let mut trace = Trace::Replacing {
            lambda: 0.95.into(),
            eligibility: arr1(&[0.0f64; 10]),
        };

        assert_eq!(trace.get(), arr1(&[0.0f64; 10]));

        trace.decay(1.0);
        assert_eq!(trace.get(), arr1(&[0.0f64; 10]));

        trace.update(&arr1(&[1.0f64; 10]));
        assert_eq!(trace.get(), arr1(&[1.0f64; 10]));

        trace.decay(1.0);
        assert_eq!(trace.get(), arr1(&[0.95f64; 10]));

        trace.update(&arr1(&[1.0f64; 10]));
        assert_eq!(trace.get(), arr1(&[1.0f64; 10]));
    }
}
<|endoftext|>


<commit_before>// P_1_2_2_01
//
// Generative Gestaltung – Creative Coding im Web
// ISBN: 978-3-87439-902-9, First Edition, Hermann Schmidt, Mainz, 2018
// Benedikt Groß, Hartmut Bohnacker, Julia Laub, Claudius Lazzeroni
// with contributions by Joey Lee and Niels Poldervaart
// Copyright 2018
//
// http://www.generative-gestaltung.de
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * extract and sort the color palette of an image
 *
 * MOUSE
 * position x          : resolution
 *
 * KEYS
 * Q/W/E/R             : load different images
 * 1                   : no color sorting
 * 2                   : sort colors on hue
 * 3                   : sort colors on saturation
 * 4                   : sort colors on brightness
 * 5                   : sort colors on greyscale (luminance)
 * 6                   : sort colors on red
 * 7                   : sort colors on green
 * 8                   : sort colors on blue
 * 9                   : sort colors on alpha
 * s                   : save png
 * c                   : save color palette
 */
use nannou::image;
use nannou::image::GenericImageView;
use nannou::prelude::*;
use nannou::ui::color::rgb_to_hsl;

fn main() {
    nannou::app(model).run();
}

enum SortMode {
    Red,
    Green,
    Blue,
    Hue,
    Saturation,
    Brightness,
    Grayscale,
    Alpha,
}

struct Model {
    image: image::DynamicImage,
    sort_mode: Option<SortMode>,
}

fn model(app: &App) -> Model {
    app.new_window()
        .size(600, 600)
        .view(view)
        .key_released(key_released)
        .build()
        .unwrap();

    let assets = app.assets_path().unwrap();
    let img_path = assets
        .join("images")
        .join("generative_examples")
        .join("pic1.jpg");

    let image = image::open(img_path).unwrap();
    Model {
        image,
        sort_mode: None,
    }
}

fn view(app: &App, model: &Model, frame: Frame) {
    let draw = app.draw();
    let win = app.window_rect();
    let tile_count = clamp(
        map_range(app.mouse.x, win.left(), win.right(), 120, 1),
        120,
        1,
    );
    let rect_size = win.w() / tile_count as f32;

    let mut colors = Vec::new();

    for grid_y in 0..tile_count as usize {
        for grid_x in 0..tile_count as usize {
            let px = grid_x as f32 * rect_size + (rect_size / 2.0);
            let py = grid_y as f32 * rect_size + (rect_size / 2.0);
            // get current color
            let c = model.image.get_pixel(px as u32, py as u32);
            let red = c[0] as f32 / 255.0;
            let green = c[1] as f32 / 255.0;
            let blue = c[2] as f32 / 255.0;
            let alpha = c[3] as f32 / 255.0;

            colors.push(rgba(red, green, blue, alpha));
        }
    }

    // sort
    if let Some(ref mode) = model.sort_mode {
        sort_colors(&mut colors, mode);
    }

    let mut i = 0;
    for grid_y in 0..tile_count as usize {
        for grid_x in 0..tile_count as usize {
            let pos_x = win.left() + grid_x as f32 * rect_size + (rect_size / 2.0);
            let pos_y = win.top() - grid_y as f32 * rect_size - (rect_size / 2.0);
            draw.rect()
                .x_y(pos_x, pos_y)
                .w_h(rect_size, rect_size)
                .color(colors[i]);
            i += 1;
        }
    }
    draw.to_frame(app, &frame).unwrap();
}

fn key_released(app: &App, model: &mut Model, key: Key) {
    let assets = app.assets_path().unwrap();
    let img_path = assets.join("images").join("generative_examples");

    match key {
        Key::Q => {
            model.image = image::open(img_path.join("pic1.jpg")).unwrap();
        }
        Key::W => {
            model.image = image::open(img_path.join("pic2.jpg")).unwrap();
        }
        Key::E => {
            model.image = image::open(img_path.join("pic3.jpg")).unwrap();
        }
        Key::R => {
            model.image = image::open(img_path.join("pic4.jpg")).unwrap();
        }
        Key::Key1 => {
            model.sort_mode = None;
        }
        Key::Key2 => {
            model.sort_mode = Some(SortMode::Hue);
        }
        Key::Key3 => {
            model.sort_mode = Some(SortMode::Saturation);
        }
        Key::Key4 => {
            model.sort_mode = Some(SortMode::Brightness);
        }
        Key::Key5 => {
            model.sort_mode = Some(SortMode::Grayscale);
        }
        Key::Key6 => {
            model.sort_mode = Some(SortMode::Red);
        }
        Key::Key7 => {
            model.sort_mode = Some(SortMode::Green);
        }
        Key::Key8 => {
            model.sort_mode = Some(SortMode::Blue);
        }
        Key::Key9 => {
            model.sort_mode = Some(SortMode::Alpha);
        }
        Key::S => {
            app.main_window()
                .capture_frame(app.exe_name().unwrap() + ".png");
        }
        _otherkey => (),
    }
}

fn sort_colors(colors: &mut Vec<Rgba>, mode: &SortMode) {
    match mode {
        SortMode::Red => {
            colors.sort_by(|a, b| a.red.partial_cmp(&b.red).unwrap());
        }
        SortMode::Green => {
            colors.sort_by(|a, b| a.green.partial_cmp(&b.green).unwrap());
        }
        SortMode::Blue => {
            colors.sort_by(|a, b| a.blue.partial_cmp(&b.blue).unwrap());
        }
        SortMode::Hue => {
            colors.sort_by(|a, b| {
                let (a_hue, _, _) = rgb_to_hsl(a.red, a.green, a.blue);
                let (b_hue, _, _) = rgb_to_hsl(b.red, b.green, b.blue);
                a_hue.partial_cmp(&b_hue).unwrap()
            });
        }
        SortMode::Saturation => {
            colors.sort_by(|a, b| {
                let (_, a_sat, _) = rgb_to_hsl(a.red, a.green, a.blue);
                let (_, b_sat, _) = rgb_to_hsl(b.red, b.green, b.blue);
                a_sat.partial_cmp(&b_sat).unwrap()
            });
        }
        SortMode::Brightness => {
            colors.sort_by(|a, b| {
                let (_, _, a_bright) = rgb_to_hsl(a.red, a.green, a.blue);
                let (_, _, b_bright) = rgb_to_hsl(b.red, b.green, b.blue);
                a_bright.partial_cmp(&b_bright).unwrap()
            });
        }
        SortMode::Alpha => {
            colors.sort_by(|a, b| a.alpha.partial_cmp(&b.alpha).unwrap());
        }
        _ => (),
    }
}
<commit_msg>Prevent the default pink background from mixing with the image<commit_after>// P_1_2_2_01
//
// Generative Gestaltung – Creative Coding im Web
// ISBN: 978-3-87439-902-9, First Edition, Hermann Schmidt, Mainz, 2018
// Benedikt Groß, Hartmut Bohnacker, Julia Laub, Claudius Lazzeroni
// with contributions by Joey Lee and Niels Poldervaart
// Copyright 2018
//
// http://www.generative-gestaltung.de
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * extract and sort the color palette of an image
 *
 * MOUSE
 * position x          : resolution
 *
 * KEYS
 * Q/W/E/R             : load different images
 * 1                   : no color sorting
 * 2                   : sort colors on hue
 * 3                   : sort colors on saturation
 * 4                   : sort colors on brightness
 * 5                   : sort colors on greyscale (luminance)
 * 6                   : sort colors on red
 * 7                   : sort colors on green
 * 8                   : sort colors on blue
 * 9                   : sort colors on alpha
 * s                   : save png
 * c                   : save color palette
 */
use nannou::image;
use nannou::image::GenericImageView;
use nannou::prelude::*;
use nannou::ui::color::rgb_to_hsl;

fn main() {
    nannou::app(model).run();
}

enum SortMode {
    Red,
    Green,
    Blue,
    Hue,
    Saturation,
    Brightness,
    Grayscale,
    Alpha,
}

struct Model {
    image: image::DynamicImage,
    sort_mode: Option<SortMode>,
}

fn model(app: &App) -> Model {
    app.new_window()
        .size(600, 600)
        .view(view)
        .key_released(key_released)
        .build()
        .unwrap();

    let assets = app.assets_path().unwrap();
    let img_path = assets
        .join("images")
        .join("generative_examples")
        .join("pic1.jpg");

    let image = image::open(img_path).unwrap();
    Model {
        image,
        sort_mode: None,
    }
}

fn view(app: &App, model: &Model, frame: Frame) {
    let draw = app.draw();
    draw.background().color(WHITE);
    let win = app.window_rect();
    let tile_count = clamp(
        map_range(app.mouse.x, win.left(), win.right(), 120, 1),
        120,
        1,
    );
    let rect_size = win.w() / tile_count as f32;

    let mut colors = Vec::new();

    for grid_y in 0..tile_count as usize {
        for grid_x in 0..tile_count as usize {
            let px = grid_x as f32 * rect_size + (rect_size / 2.0);
            let py = grid_y as f32 * rect_size + (rect_size / 2.0);
            // get current color
            let c = model.image.get_pixel(px as u32, py as u32);
            let red = c[0] as f32 / 255.0;
            let green = c[1] as f32 / 255.0;
            let blue = c[2] as f32 / 255.0;
            let alpha = c[3] as f32 / 255.0;

            colors.push(rgba(red, green, blue, alpha));
        }
    }

    // sort
    if let Some(ref mode) = model.sort_mode {
        sort_colors(&mut colors, mode);
    }

    let mut i = 0;
    for grid_y in 0..tile_count as usize {
        for grid_x in 0..tile_count as usize {
            let pos_x = win.left() + grid_x as f32 * rect_size + (rect_size / 2.0);
            let pos_y = win.top() - grid_y as f32 * rect_size - (rect_size / 2.0);
            draw.rect()
                .x_y(pos_x, pos_y)
                .w_h(rect_size, rect_size)
                .color(colors[i]);
            i += 1;
        }
    }
    draw.to_frame(app, &frame).unwrap();
}

fn key_released(app: &App, model: &mut Model, key: Key) {
    let assets = app.assets_path().unwrap();
    let img_path = assets.join("images").join("generative_examples");

    match key {
        Key::Q => {
            model.image = image::open(img_path.join("pic1.jpg")).unwrap();
        }
        Key::W => {
            model.image = image::open(img_path.join("pic2.jpg")).unwrap();
        }
        Key::E => {
            model.image = image::open(img_path.join("pic3.jpg")).unwrap();
        }
        Key::R => {
            model.image = image::open(img_path.join("pic4.jpg")).unwrap();
        }
        Key::Key1 => {
            model.sort_mode = None;
        }
        Key::Key2 => {
            model.sort_mode = Some(SortMode::Hue);
        }
        Key::Key3 => {
            model.sort_mode = Some(SortMode::Saturation);
        }
        Key::Key4 => {
            model.sort_mode = Some(SortMode::Brightness);
        }
        Key::Key5 => {
            model.sort_mode = Some(SortMode::Grayscale);
        }
        Key::Key6 => {
            model.sort_mode = Some(SortMode::Red);
        }
        Key::Key7 => {
            model.sort_mode = Some(SortMode::Green);
        }
        Key::Key8 => {
            model.sort_mode = Some(SortMode::Blue);
        }
        Key::Key9 => {
            model.sort_mode = Some(SortMode::Alpha);
        }
        Key::S => {
            app.main_window()
                .capture_frame(app.exe_name().unwrap() + ".png");
        }
        _otherkey => (),
    }
}

fn sort_colors(colors: &mut Vec<Rgba>, mode: &SortMode) {
    match mode {
        SortMode::Red => {
            colors.sort_by(|a, b| a.red.partial_cmp(&b.red).unwrap());
        }
        SortMode::Green => {
            colors.sort_by(|a, b| a.green.partial_cmp(&b.green).unwrap());
        }
        SortMode::Blue => {
            colors.sort_by(|a, b| a.blue.partial_cmp(&b.blue).unwrap());
        }
        SortMode::Hue => {
            colors.sort_by(|a, b| {
                let (a_hue, _, _) = rgb_to_hsl(a.red, a.green, a.blue);
                let (b_hue, _, _) = rgb_to_hsl(b.red, b.green, b.blue);
                a_hue.partial_cmp(&b_hue).unwrap()
            });
        }
        SortMode::Saturation => {
            colors.sort_by(|a, b| {
                let (_, a_sat, _) = rgb_to_hsl(a.red, a.green, a.blue);
                let (_, b_sat, _) = rgb_to_hsl(b.red, b.green, b.blue);
                a_sat.partial_cmp(&b_sat).unwrap()
            });
        }
        SortMode::Brightness => {
            colors.sort_by(|a, b| {
                let (_, _, a_bright) = rgb_to_hsl(a.red, a.green, a.blue);
                let (_, _, b_bright) = rgb_to_hsl(b.red, b.green, b.blue);
                a_bright.partial_cmp(&b_bright).unwrap()
            });
        }
        SortMode::Alpha => {
            colors.sort_by(|a, b| a.alpha.partial_cmp(&b.alpha).unwrap());
        }
        _ => (),
    }
}
<|endoftext|>


<commit_before>extern crate num;
extern crate rand;

use self::num::FromPrimitive;
use self::rand::{Rng, thread_rng};

///enum for the pokemon/attack types.
///Can be assigned from i32 value.
enum_from_primitive! {
    #[derive(Debug, RustcDecodable, Clone, Eq, PartialEq, Hash)]
    pub enum types {
        normal = 1,
        fighting = 2,
        flying = 3,
        poison = 4,
        ground = 5,
        rock = 6,
        bug = 7,
        ghost = 8,
        steel = 9,
        fire = 10,
        water = 11,
        grass = 12,
        electric = 13,
        psychic = 14,
        ice = 15,
        dragon = 16,
        dark = 17,
        fairy = 18,
        undefined = 19,
    }
}

///Enum for the Categories a move can have. They are used to get smaller samples of moves when
///resolve their effects.
enum_from_primitive! {
    #[derive(Debug, Clone, PartialEq)]
    pub enum Move_Category {
        Damage = 0,
        Ailment = 1,
        Net_Good_Stats = 2,
        Heal = 3,
        Damage_And_Ailment = 4,
        Swagger = 5,
        Damage_And_Lower = 6,
        Damage_And_Raise = 7,
        Damage_And_Heal = 8,
        Ohko = 9,
        Whole_Field_Effect = 10,
        Field_Effect = 11,
        Force_Switch = 12,
        Unique = 13,
    }
}

///All ailments that are known and can be caused by one or more moves.
#[derive(Debug, Clone)]
pub enum Ailment {
    Unknown,
    Undefined,
    Paralysis,
    Sleep,
    Freeze,
    Burn,
    Poison,
    Confusion,
    Infatuation,
    Trap,
    Nightmare,
    Torment,
    Disable,
    Yawn,
    Heal_Block,
    No_Type_Immunity,
    Leech_Seed,
    Embargo,
    Perish_Song,
    Ingrain,
}

///All the major status Changes that can not be caused at the same time.
#[derive(Debug, Clone, PartialEq)]
pub enum Non_Volatile {
    Undefined,
    Paralysis,
    Sleep,
    Freeze,
    Burn,
    Poison,
    Bad_Poison,
}

///Flags that have a influence at the end of each turn.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum End_Of_Turn {
    //absorbs some HP at the End of every Turn
    Leech_Seed,
    //Counts from 0 to 4, one step each round, even in the turn it was initially used.
    //When 4 is reached the Pokemon faints. Counting only continues when the Pokemon is part of
    //the battle, but the counter will not be resetted if the Pokemon is changed.
    Perish_Song,
    //Changes the Non_Volatile Status of the Pokemon to Sleep after one round if possible.
    Yawn,
    //Is set after a flying type uses roost. This changes the flying type either to undefined, if
    //the Pokemon has two types, or to Normal if it has only one. Because of the possible
    //combination of normal and flying it is needed to have two indicators to determine which type
    //must be changed back.
    Roost_Type_One,
    Roost_Type_Two,
    //Attacks that deal damage at the end of every turn and binds the Pokemon -> It can not be
    //changed out. Lasts at least 2 and at most 5 turns.
    Trap,
}

///Print method for non volatile status changes.
pub fn print_non_volatile(status: Non_Volatile) -> String {
    match status {
        Non_Volatile::Undefined => String::from(""),
        Non_Volatile::Paralysis => String::from("paralysed"),
        Non_Volatile::Sleep => String::from("asleep"),
        Non_Volatile::Freeze => String::from("freezed"),
        Non_Volatile::Burn => String::from("burned"),
        _ => String::from("poisoned")
    }
}

///Enum for Genders
#[derive(Debug, Clone)]
pub enum Gender {
    Male,
    Female,
    Genderless,
}

///Makes it easier to acces the Stats directly
enum_from_primitive! {
    #[derive(Debug, Clone)]
    pub enum Stats {
        Undefined = 0,
        Hp = 1,
        Attack = 2,
        Defense = 3,
        Special_Attack = 4,
        Special_Defense = 5,
        Speed = 6,
        Accuracy = 7,
        Evasion = 8,
    }
}

///Weather enum for the arena.
#[derive(Debug, Clone)]
pub enum Weather {
    Clear_Sky,
    Sunlight,
    //no need to handle it right now, only caused by abilities
    Harsh_Sunlight,
    Rain,
    //no need to handle it right now, only caused by abilities
    Heavy_Rain,
    Sandstorm,
    Hail,
    //no need to handle it right now, only caused by abilities
    Air_Current,
}

///enum for the Damage Class of a attack.
///Can be assigned from a i32 value.
enum_from_primitive! {
    #[derive(Debug, RustcDecodable, Clone)]
    pub enum DamageClass {
        Physical = 1,
        Special = 2,
        Status = 3,
    }
}

///Enum that contains the valid target(s) of a move.
///Can be assigned from a i32 value.
enum_from_primitive! {
    #[derive(Debug, RustcDecodable, Clone)]
    pub enum Target {
        SpecificMove = 1,
        SelectedPokemonMeFirst = 2,
        Ally = 3,
        UsersField = 4,
        UserOrAlly = 5,
        OpponentsField = 6,
        User = 7,
        RandomOpponent = 8,
        AllOtherPokemon = 9,
        SelectedPokemon = 10,
        AllOpponents = 11,
        EntireField = 12,
        UserAndAllies = 13,
        AllPokemon = 14,
    }
}

///All Flags that can be important for a move. Contains for example if a move is influenced by
///another move or condition the pokemon or arena is in.
enum_from_primitive! {
    #[derive(Debug, RustcDecodable, Clone)]
    pub enum MoveFlags {
        Contact = 1,
        Charge = 2,
        Recharge = 3,
        Protect = 4,
        Reflectable = 5,
        Snatch = 6,
        Mirror = 7,
        Punch = 8,
        Sound = 9,
        Gravity = 10,
        Defrost = 11,
        Distance = 12,
        Heal = 13,
        Authentic = 14,
        Powder = 15,
        Bite = 16,
        Pulse = 17,
        Balistic = 18,
        Mental = 19,
        Non_Sky_Battle = 20,
    }
}

///More or less randomly provides a gender for a pokemon given the distribution for the species.
pub fn get_gender(gender_rate: i8) -> Gender {
    let mut rng = thread_rng();
    let probability = rng.gen_range(1, 101);
    match gender_rate {
        -1 => Gender::Genderless,
        0 => Gender::Male,
        1 => {
            if probability < 87 {
            return Gender::Male
            }
        Gender::Female
        },
        2 => {
            if probability < 75 {
            return Gender::Male
            }
        Gender::Female
        },
        4 => {
            if probability < 50 {
            return Gender::Male
            }
        Gender::Female
        },
        6 => {
            if probability < 25 {
            return Gender::Male
            }
        Gender::Female
        },
        7 => {
            if probability < 13 {
            return Gender::Male
            }
        Gender::Female
        },
        8 => Gender::Female,
        _ => Gender::Genderless,
    }
}
<commit_msg>Implemented Display for types<commit_after>extern crate num;
extern crate rand;

use self::num::FromPrimitive;
use self::rand::{Rng, thread_rng};

/// enum for the pokemon/attack types.
/// Can be assigned from i32 value.
enum_from_primitive! {
    #[derive(Debug, RustcDecodable, Clone, Eq, PartialEq, Hash)]
    pub enum types {
        normal = 1,
        fighting = 2,
        flying = 3,
        poison = 4,
        ground = 5,
        rock = 6,
        bug = 7,
        ghost = 8,
        steel = 9,
        fire = 10,
        water = 11,
        grass = 12,
        electric = 13,
        psychic = 14,
        ice = 15,
        dragon = 16,
        dark = 17,
        fairy = 18,
        undefined = 19,
    }
}

impl ::std::fmt::Display for types {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        let x = match *self {
            types::normal => "Normal",
            types::fighting => "Fighting",
            types::flying => "Flying",
            types::poison => "Poison",
            types::ground => "Ground",
            types::rock => "Rock",
            types::bug => "Bug",
            types::ghost => "Ghost",
            types::steel => "Steel",
            types::fire => "Fire",
            types::water => "Water",
            types::grass => "Grass",
            types::electric => "Electric",
            types::psychic => "Psychic",
            types::ice => "Ice",
            types::dragon => "Dragon",
            types::dark => "Dark",
            types::fairy => "Fairy",
            types::undefined => "Undefined",
        };

        write!(f, "{}", x)
    }
}

/// Enum for the Categories a move can have. They are used to get smaller samples of moves when
/// resolve their effects.
enum_from_primitive! {
    #[derive(Debug, Clone, PartialEq)]
    pub enum Move_Category {
        Damage = 0,
        Ailment = 1,
        Net_Good_Stats = 2,
        Heal = 3,
        Damage_And_Ailment = 4,
        Swagger = 5,
        Damage_And_Lower = 6,
        Damage_And_Raise = 7,
        Damage_And_Heal = 8,
        Ohko = 9,
        Whole_Field_Effect = 10,
        Field_Effect = 11,
        Force_Switch = 12,
        Unique = 13,
    }
}

/// All ailments that are known and can be caused by one or more moves.
#[derive(Debug, Clone)]
pub enum Ailment {
    Unknown,
    Undefined,
    Paralysis,
    Sleep,
    Freeze,
    Burn,
    Poison,
    Confusion,
    Infatuation,
    Trap,
    Nightmare,
    Torment,
    Disable,
    Yawn,
    Heal_Block,
    No_Type_Immunity,
    Leech_Seed,
    Embargo,
    Perish_Song,
    Ingrain,
}

/// All the major status Changes that can not be caused at the same time.
#[derive(Debug, Clone, PartialEq)]
pub enum Non_Volatile {
    Undefined,
    Paralysis,
    Sleep,
    Freeze,
    Burn,
    Poison,
    Bad_Poison,
}

/// Flags that have a influence at the end of each turn.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum End_Of_Turn {
    // absorbs some HP at the End of every Turn
    Leech_Seed,
    // Counts from 0 to 4, one step each round, even in the turn it was initially used.
    // When 4 is reached the Pokemon faints. Counting only continues when the Pokemon is part of
    // the battle, but the counter will not be resetted if the Pokemon is changed.
    Perish_Song,
    // Changes the Non_Volatile Status of the Pokemon to Sleep after one round if possible.
    Yawn,
    // Is set after a flying type uses roost. This changes the flying type either to undefined, if
    // the Pokemon has two types, or to Normal if it has only one. Because of the possible
    // combination of normal and flying it is needed to have two indicators to determine which type
    // must be changed back.
    Roost_Type_One,
    Roost_Type_Two,
    // Attacks that deal damage at the end of every turn and binds the Pokemon -> It can not be
    // changed out. Lasts at least 2 and at most 5 turns.
    Trap,
}

/// Print method for non volatile status changes.
pub fn print_non_volatile(status: Non_Volatile) -> String {
    match status {
        Non_Volatile::Undefined => String::from(""),
        Non_Volatile::Paralysis => String::from("paralysed"),
        Non_Volatile::Sleep => String::from("asleep"),
        Non_Volatile::Freeze => String::from("freezed"),
        Non_Volatile::Burn => String::from("burned"),
        _ => String::from("poisoned"),
    }
}

/// Enum for Genders
#[derive(Debug, Clone)]
pub enum Gender {
    Male,
    Female,
    Genderless,
}

/// Makes it easier to acces the Stats directly
enum_from_primitive! {
    #[derive(Debug, Clone)]
    pub enum Stats {
        Undefined = 0,
        Hp = 1,
        Attack = 2,
        Defense = 3,
        Special_Attack = 4,
        Special_Defense = 5,
        Speed = 6,
        Accuracy = 7,
        Evasion = 8,
    }
}

/// Weather enum for the arena.
#[derive(Debug, Clone)]
pub enum Weather {
    Clear_Sky,
    Sunlight,
    // no need to handle it right now, only caused by abilities
    Harsh_Sunlight,
    Rain,
    // no need to handle it right now, only caused by abilities
    Heavy_Rain,
    Sandstorm,
    Hail,
    // no need to handle it right now, only caused by abilities
    Air_Current,
}

/// enum for the Damage Class of a attack.
/// Can be assigned from a i32 value.
enum_from_primitive! {
    #[derive(Debug, RustcDecodable, Clone)]
    pub enum DamageClass {
        Physical = 1,
        Special = 2,
        Status = 3,
    }
}

/// Enum that contains the valid target(s) of a move.
/// Can be assigned from a i32 value.
enum_from_primitive! {
    #[derive(Debug, RustcDecodable, Clone)]
    pub enum Target {
        SpecificMove = 1,
        SelectedPokemonMeFirst = 2,
        Ally = 3,
        UsersField = 4,
        UserOrAlly = 5,
        OpponentsField = 6,
        User = 7,
        RandomOpponent = 8,
        AllOtherPokemon = 9,
        SelectedPokemon = 10,
        AllOpponents = 11,
        EntireField = 12,
        UserAndAllies = 13,
        AllPokemon = 14,
    }
}

/// All Flags that can be important for a move. Contains for example if a move is influenced by
/// another move or condition the pokemon or arena is in.
enum_from_primitive! {
    #[derive(Debug, RustcDecodable, Clone)]
    pub enum MoveFlags {
        Contact = 1,
        Charge = 2,
        Recharge = 3,
        Protect = 4,
        Reflectable = 5,
        Snatch = 6,
        Mirror = 7,
        Punch = 8,
        Sound = 9,
        Gravity = 10,
        Defrost = 11,
        Distance = 12,
        Heal = 13,
        Authentic = 14,
        Powder = 15,
        Bite = 16,
        Pulse = 17,
        Balistic = 18,
        Mental = 19,
        Non_Sky_Battle = 20,
    }
}

/// More or less randomly provides a gender for a pokemon given the distribution for the species.
pub fn get_gender(gender_rate: i8) -> Gender {
    let mut rng = thread_rng();
    let probability = rng.gen_range(1, 101);
    match gender_rate {
        -1 => Gender::Genderless,
        0 => Gender::Male,
        1 => {
            if probability < 87 {
                return Gender::Male;
            }
            Gender::Female
        }
        2 => {
            if probability < 75 {
                return Gender::Male;
            }
            Gender::Female
        }
        4 => {
            if probability < 50 {
                return Gender::Male;
            }
            Gender::Female
        }
        6 => {
            if probability < 25 {
                return Gender::Male;
            }
            Gender::Female
        }
        7 => {
            if probability < 13 {
                return Gender::Male;
            }
            Gender::Female
        }
        8 => Gender::Female,
        _ => Gender::Genderless,
    }
}
<|endoftext|>


<commit_before>//! Fundamental definitions for mapping to the V8 memory space.

use std::os::raw::c_void;
use std::mem;

/// A V8 `Local` handle.
///
/// `Local` handles get associated to a V8 `HandleScope` container. Note: Node.js creates a
/// `HandleScope` right before calling functions in native addons.
#[repr(C)]
#[derive(Clone, Copy)]
pub struct Local {
    pub handle: *mut c_void
}

/// Represents the details of how the function was called from JavaScript.
///
/// It contains the arguments used to invoke the function, the isolate reference, the `this` object
/// the function is bound to and a mechanism to return a value to the caller.
pub type FunctionCallbackInfo = c_void;

/// Represents an instance of the V8 runtime.
pub type Isolate = c_void;

const HANDLE_SCOPE_SIZE: usize = 24;

/// A V8 `HandleScope`.
///
/// A `HandleScope` contains `Local` handles. `HandleScope`s are used by V8 to help the garbage
/// collector do it's bookkeeping. Once a new `HandleScope` is created all subsequently created
/// `Local` handles will be contained in it.
#[repr(C)]
#[derive(Clone, Copy)]
pub struct HandleScope {
    pub align_to_pointer: [*mut c_void; 0],
    pub fields: [u8; HANDLE_SCOPE_SIZE]
}

impl HandleScope {
    pub fn new() -> HandleScope { unsafe { mem::zeroed() } }
}

const ESCAPABLE_HANDLE_SCOPE_SIZE: usize = 32;

/// A V8 `EscapableHandleScope`.
///
/// A `EscapableHandleScope` is like `HandleScope` but also allows us to push `Local` handles out
/// to the previous `HandleScope`, preventing the `Local` value from being garbage collected when
/// the `EscapableHandleScope`'s resources are freed.
#[repr(C)]
#[derive(Clone, Copy)]
pub struct EscapableHandleScope {
    pub align_to_pointer: [*mut c_void; 0],
    pub fields: [u8; ESCAPABLE_HANDLE_SCOPE_SIZE]
}

impl EscapableHandleScope {
    pub fn new() -> EscapableHandleScope { unsafe { mem::zeroed() } }
}
<commit_msg>copy changes from review<commit_after>//! Fundamental definitions for mapping to the V8 memory space.

use std::os::raw::c_void;
use std::mem;

/// A V8 `Local` handle.
///
/// `Local` handles get associated to a V8 `HandleScope` container. Note: Node.js creates a
/// `HandleScope` right before calling functions in native addons.
#[repr(C)]
#[derive(Clone, Copy)]
pub struct Local {
    pub handle: *mut c_void
}

/// Represents the details of how the function was called from JavaScript.
///
/// It contains the arguments used to invoke the function, the isolate reference, the `this` object
/// the function is bound to and a mechanism to return a value to the caller.
pub type FunctionCallbackInfo = c_void;

/// Represents an instance of the V8 runtime.
pub type Isolate = c_void;

const HANDLE_SCOPE_SIZE: usize = 24;

/// A V8 `HandleScope`.
///
/// A `HandleScope` contains `Local` handles. `HandleScope`s are used by V8 to help the garbage
/// collector do its bookkeeping. Once a new `HandleScope` is created all subsequently created
/// `Local` handles will be contained in it.
#[repr(C)]
#[derive(Clone, Copy)]
pub struct HandleScope {
    pub align_to_pointer: [*mut c_void; 0],
    pub fields: [u8; HANDLE_SCOPE_SIZE]
}

impl HandleScope {
    pub fn new() -> HandleScope { unsafe { mem::zeroed() } }
}

const ESCAPABLE_HANDLE_SCOPE_SIZE: usize = 32;

/// A V8 `EscapableHandleScope`.
///
/// A `EscapableHandleScope` is like `HandleScope` but also allows us to push `Local` handles out
/// to the previous `HandleScope`, permitting the `Local` value to remain rooted longer than the
/// the `EscapableHandleScope` where it was intially rooted.
#[repr(C)]
#[derive(Clone, Copy)]
pub struct EscapableHandleScope {
    pub align_to_pointer: [*mut c_void; 0],
    pub fields: [u8; ESCAPABLE_HANDLE_SCOPE_SIZE]
}

impl EscapableHandleScope {
    pub fn new() -> EscapableHandleScope { unsafe { mem::zeroed() } }
}
<|endoftext|>