<commit_before>use libc;
use std::ptr;
use std::rc::Rc;

use glib::translate::*;
use glib_sys;

use handle::{self, RsvgHandle};
use load::{rsvg_load_new_node, rsvg_load_set_node_atts};
use node::{box_node, Node, RsvgNode};
use property_bag::PropertyBag;
use tree::{RsvgTree, Tree};
use util::utf8_cstr;

// A *const RsvgXmlState is just the type that we export to C
pub enum RsvgXmlState {}

struct XmlState {
    tree: Option<Box<Tree>>,
    current_node: Option<Rc<Node>>,

    // Stack of element names while parsing; used to know when to stop
    // parsing the current element.
    element_name_stack: Vec<String>,
}

impl XmlState {
    fn new() -> XmlState {
        XmlState {
            tree: None,
            current_node: None,
            element_name_stack: Vec::new(),
        }
    }

    pub fn set_root(&mut self, root: &Rc<Node>) {
        if self.tree.is_some() {
            panic!("The tree root has already been set");
        }

        self.tree = Some(Box::new(Tree::new(root)));
    }

    pub fn steal_tree(&mut self) -> Option<Box<Tree>> {
        self.tree.take()
    }

    pub fn get_current_node(&self) -> Option<Rc<Node>> {
        self.current_node.clone()
    }

    pub fn set_current_node(&mut self, node: Option<Rc<Node>>) {
        self.current_node = node;
    }

    pub fn push_element_name(&mut self, name: &str) {
        self.element_name_stack.push(name.to_string());
    }

    pub fn pop_element_name(&mut self) {
        self.element_name_stack.pop();
    }

    pub fn topmost_element_name_is(&mut self, name: &str) -> bool {
        let len = self.element_name_stack.len();

        if len > 0 {
            self.element_name_stack[len - 1] == name
        } else {
            false
        }
    }

    pub fn free_element_name_stack(&mut self) {
        self.element_name_stack.clear();
    }

    pub fn standard_element_start(
        &mut self,
        handle: *const RsvgHandle,
        name: &str,
        pbag: &PropertyBag,
    ) {
        let mut defs = handle::get_defs(handle);
        let mut is_svg = false;

        let new_node = rsvg_load_new_node(
            name,
            self.current_node.as_ref(),
            pbag,
            &mut defs,
            &mut is_svg,
        );

        self.push_element_name(name);

        if let Some(ref current_node) = self.current_node {
            current_node.add_child(&new_node);
        } else if is_svg {
            self.set_root(&new_node);
        }

        self.set_current_node(Some(new_node.clone()));

        rsvg_load_set_node_atts(handle, &new_node, name, pbag);
    }
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_new() -> *mut RsvgXmlState {
    Box::into_raw(Box::new(XmlState::new())) as *mut RsvgXmlState
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_free(xml: *mut RsvgXmlState) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };
    unsafe {
        Box::from_raw(xml);
    }
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_set_root(xml: *mut RsvgXmlState, root: *const RsvgNode) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    assert!(!root.is_null());
    let root = unsafe { &*root };

    xml.set_root(root);
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_steal_tree(xml: *mut RsvgXmlState) -> *mut RsvgTree {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    if let Some(tree) = xml.steal_tree() {
        Box::into_raw(tree) as *mut RsvgTree
    } else {
        ptr::null_mut()
    }
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_get_current_node(xml: *const RsvgXmlState) -> *mut RsvgNode {
    assert!(!xml.is_null());
    let xml = unsafe { &*(xml as *const XmlState) };

    if let Some(ref node) = xml.get_current_node() {
        box_node(node.clone())
    } else {
        ptr::null_mut()
    }
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_set_current_node(
    xml: *mut RsvgXmlState,
    raw_node: *const RsvgNode,
) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    let node = if raw_node.is_null() {
        None
    } else {
        let n = unsafe { &*raw_node };
        Some(n.clone())
    };

    xml.set_current_node(node);
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_push_element_name(
    xml: *mut RsvgXmlState,
    name: *const libc::c_char,
) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    assert!(!name.is_null());

    let name = unsafe { utf8_cstr(name) };
    xml.push_element_name(name);
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_pop_element_name(xml: *mut RsvgXmlState) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    xml.pop_element_name();
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_topmost_element_name_is(
    xml: *mut RsvgXmlState,
    name: *const libc::c_char,
) -> glib_sys::gboolean {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    assert!(!name.is_null());

    let name = unsafe { utf8_cstr(name) };
    xml.topmost_element_name_is(name).to_glib()
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_free_element_name_stack(xml: *mut RsvgXmlState) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    xml.free_element_name_stack();
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_standard_element_start(
    xml: *mut RsvgXmlState,
    handle: *const RsvgHandle,
    name: *const libc::c_char,
    pbag: *const PropertyBag,
) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    assert!(!name.is_null());
    let name = unsafe { utf8_cstr(name) };

    assert!(!pbag.is_null());
    let pbag = unsafe { &*pbag };

    xml.standard_element_start(handle, name, pbag);
}
<commit_msg>Inline rsvg_load_set_node_atts() in its only caller<commit_after>use libc;
use std::ptr;
use std::rc::Rc;

use glib::translate::*;
use glib_sys;

use handle::{self, RsvgHandle};
use load::rsvg_load_new_node;
use node::{box_node, Node, NodeType, RsvgNode};
use property_bag::PropertyBag;
use tree::{RsvgTree, Tree};
use util::utf8_cstr;

// A *const RsvgXmlState is just the type that we export to C
pub enum RsvgXmlState {}

struct XmlState {
    tree: Option<Box<Tree>>,
    current_node: Option<Rc<Node>>,

    // Stack of element names while parsing; used to know when to stop
    // parsing the current element.
    element_name_stack: Vec<String>,
}

impl XmlState {
    fn new() -> XmlState {
        XmlState {
            tree: None,
            current_node: None,
            element_name_stack: Vec::new(),
        }
    }

    pub fn set_root(&mut self, root: &Rc<Node>) {
        if self.tree.is_some() {
            panic!("The tree root has already been set");
        }

        self.tree = Some(Box::new(Tree::new(root)));
    }

    pub fn steal_tree(&mut self) -> Option<Box<Tree>> {
        self.tree.take()
    }

    pub fn get_current_node(&self) -> Option<Rc<Node>> {
        self.current_node.clone()
    }

    pub fn set_current_node(&mut self, node: Option<Rc<Node>>) {
        self.current_node = node;
    }

    pub fn push_element_name(&mut self, name: &str) {
        self.element_name_stack.push(name.to_string());
    }

    pub fn pop_element_name(&mut self) {
        self.element_name_stack.pop();
    }

    pub fn topmost_element_name_is(&mut self, name: &str) -> bool {
        let len = self.element_name_stack.len();

        if len > 0 {
            self.element_name_stack[len - 1] == name
        } else {
            false
        }
    }

    pub fn free_element_name_stack(&mut self) {
        self.element_name_stack.clear();
    }

    pub fn standard_element_start(
        &mut self,
        handle: *const RsvgHandle,
        name: &str,
        pbag: &PropertyBag,
    ) {
        let mut defs = handle::get_defs(handle);
        let mut is_svg = false;

        let new_node = rsvg_load_new_node(
            name,
            self.current_node.as_ref(),
            pbag,
            &mut defs,
            &mut is_svg,
        );

        self.push_element_name(name);

        if let Some(ref current_node) = self.current_node {
            current_node.add_child(&new_node);
        } else if is_svg {
            self.set_root(&new_node);
        }

        self.set_current_node(Some(new_node.clone()));

        new_node.set_atts(&new_node, handle, pbag);

        // The "svg" node is special; it will load its id/class
        // attributes until the end, when sax_end_element_cb() calls
        // rsvg_node_svg_apply_atts()
        if new_node.get_type() != NodeType::Svg {
            new_node.parse_style_attributes(handle, name, pbag);
        }

        new_node.set_overridden_properties();
    }
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_new() -> *mut RsvgXmlState {
    Box::into_raw(Box::new(XmlState::new())) as *mut RsvgXmlState
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_free(xml: *mut RsvgXmlState) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };
    unsafe {
        Box::from_raw(xml);
    }
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_set_root(xml: *mut RsvgXmlState, root: *const RsvgNode) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    assert!(!root.is_null());
    let root = unsafe { &*root };

    xml.set_root(root);
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_steal_tree(xml: *mut RsvgXmlState) -> *mut RsvgTree {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    if let Some(tree) = xml.steal_tree() {
        Box::into_raw(tree) as *mut RsvgTree
    } else {
        ptr::null_mut()
    }
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_get_current_node(xml: *const RsvgXmlState) -> *mut RsvgNode {
    assert!(!xml.is_null());
    let xml = unsafe { &*(xml as *const XmlState) };

    if let Some(ref node) = xml.get_current_node() {
        box_node(node.clone())
    } else {
        ptr::null_mut()
    }
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_set_current_node(
    xml: *mut RsvgXmlState,
    raw_node: *const RsvgNode,
) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    let node = if raw_node.is_null() {
        None
    } else {
        let n = unsafe { &*raw_node };
        Some(n.clone())
    };

    xml.set_current_node(node);
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_push_element_name(
    xml: *mut RsvgXmlState,
    name: *const libc::c_char,
) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    assert!(!name.is_null());

    let name = unsafe { utf8_cstr(name) };
    xml.push_element_name(name);
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_pop_element_name(xml: *mut RsvgXmlState) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    xml.pop_element_name();
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_topmost_element_name_is(
    xml: *mut RsvgXmlState,
    name: *const libc::c_char,
) -> glib_sys::gboolean {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    assert!(!name.is_null());

    let name = unsafe { utf8_cstr(name) };
    xml.topmost_element_name_is(name).to_glib()
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_free_element_name_stack(xml: *mut RsvgXmlState) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    xml.free_element_name_stack();
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_standard_element_start(
    xml: *mut RsvgXmlState,
    handle: *const RsvgHandle,
    name: *const libc::c_char,
    pbag: *const PropertyBag,
) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    assert!(!name.is_null());
    let name = unsafe { utf8_cstr(name) };

    assert!(!pbag.is_null());
    let pbag = unsafe { &*pbag };

    xml.standard_element_start(handle, name, pbag);
}
<|endoftext|>


<commit_before>use consts::*;
use std::uint::range;
use reference;

#[packed]
pub struct SpongeState {
    state: [u8, ..PERM_SIZE_IN_BYTES],
    data_queue: [u8, ..MAX_RATE_IN_BYTES],
    rate: uint,
    capacity: uint,
    bits_in_queue: uint,
    fixed_out_len: uint,
    squeezing: bool,
    bits_for_squeezing: uint,
}

#[deriving(Eq,TotalEq,ToStr,Clone)]
pub enum SpongeError {
    Success,
    Failure,
}

impl SpongeState {
    pub fn new(rate: uint, capacity: uint) -> SpongeState {
        assert!(rate + capacity == 1600);
        assert!(rate % 64 == 0);

        debug!(fmt!("Rate = %u", rate));

        SpongeState {
            state: [0u8, ..PERM_SIZE_IN_BYTES],
            data_queue: [0u8, ..MAX_RATE_IN_BYTES],
            rate: rate,
            capacity: capacity,
            fixed_out_len: 0,
            bits_in_queue: 0,
            bits_for_squeezing: 0,
            squeezing: false
        }
    }

    pub fn absorb(&mut self, data: &[u8], data_bit_len: uint) -> SpongeError {
        use std::vec::raw::*;
        use std::vec::*;

        if self.bits_in_queue % 8 != 0 {
            return Failure;
        }
        if self.squeezing {
            return Failure;
        }

        let mut whole_blocks;
        let mut cur_data;
        let mut part_block;
        let mut part_byte;
        let mut i = 0u;

        while i < data_bit_len {
            debug!(fmt!("data_bit_len = %u : self.rate = %u", data_bit_len, self.rate));
            if (self.bits_in_queue == 0) && (data_bit_len >= self.rate)
                && (i <=  (data_bit_len - self.rate)) {
                whole_blocks = (data_bit_len - i) / self.rate;
                cur_data = to_ptr(data) + i/8;

                unsafe {
                    match self.rate {
                        576 => {
                            for range(0, whole_blocks) |_| {
                                do buf_as_slice(cur_data, 576/8) |buf| {
                                    debug!(fmt!("Block to be absorbed: %?", buf));
                                    reference::absorb_576_bits(self.state, buf);
                                }
                                cur_data = cur_data + 576/8;
                            }
                        }
                        832 => {
                            for range(0, whole_blocks) |_| {
                                do buf_as_slice(cur_data, 832/8) |buf| {
                                    debug!(fmt!("Block to be absorbed: %?", buf));
                                    reference::absorb_832_bits(self.state, buf);
                                }
                                cur_data = cur_data + 832/8;
                            }
                        }
                        1024 => {
                            for range(0, whole_blocks) |_| {
                                do buf_as_slice(cur_data, 1024/8) |buf| {
                                    debug!(fmt!("Block to be absorbed: %?", buf));
                                    reference::absorb_1024_bits(self.state, buf);
                                }
                                cur_data = cur_data + 1024/8;
                            }
                        }
                        1088 => {
                            for range(0, whole_blocks) |_| {
                                do buf_as_slice(cur_data, 1088/8) |buf| {
                                    debug!(fmt!("Block to be absorbed: %?", buf));
                                    reference::absorb_1088_bits(self.state, buf);
                                }
                                cur_data = cur_data + 1088/8;
                            }
                        }
                        1152 => {
                            for range(0, whole_blocks) |_| {
                                do buf_as_slice(cur_data, 1152/8) |buf| {
                                    debug!(fmt!("Block to be absorbed: %?", buf));
                                    reference::absorb_1152_bits(self.state, buf);
                                }
                                cur_data = cur_data + 1152/8;
                            }
                        }
                        1344 => {
                            for range(0, whole_blocks) |_| {
                                do buf_as_slice(cur_data, 1344/8) |buf| {
                                    debug!(fmt!("Block to be absorbed: %?", buf));
                                    reference::absorb_1344_bits(self.state, buf);
                                }
                                cur_data = cur_data + 1344/8;
                            }
                        }
                        n => {
                            for range(0, whole_blocks) |_| {
                                do buf_as_slice(cur_data, n/8) |buf| {
                                    debug!(fmt!("Block to be absorbed: %?", buf));
                                    reference::absorb(self.state, buf, self.rate / 64);
                                }
                                cur_data = cur_data + self.rate/8;
                            }
                        }
                    }
                }
                i += whole_blocks * self.rate;
            } else {
                part_block = (data_bit_len - i);
                if part_block + self.bits_in_queue > self.rate {
                    part_block = self.rate - self.bits_in_queue;
                }
                part_byte = part_block % 8;
                part_block -= part_byte;
                unsafe {
                    let dq: &mut[u8] = self.data_queue;
                    copy_memory(dq
                        .mut_slice_from(self.bits_in_queue/8),
                        data.slice_from(i/8),
                        part_block/8);
                }
                self.bits_in_queue += part_block;
                i += part_block;

                if self.bits_in_queue == self.rate {
                    self.absorb_queue();
                }
                if part_byte > 0 {
                    let mask: u8 = (1 << part_byte) - 1;
                    self.data_queue[self.bits_in_queue/8] = data[i/8] & mask;
                    self.bits_in_queue += part_byte;
                    i += part_byte;
                }
            }

            debug!(fmt!("i = %u",i));
        }

        Success
    }

    priv fn pad_and_switch_to_squeeze(&mut self) {
        debug!(fmt!("Bits in queue: %u %?",self.bits_in_queue, self.data_queue));
        if self.bits_in_queue + 1 == self.rate {
            self.data_queue[self.bits_in_queue/8] |= 1 << (self.bits_in_queue % 8);
            self.absorb_queue();
            self.data_queue.mut_iter().take_(self.rate/8).advance(|n| {*n = 0; true});
        } else {
            debug!(fmt!("(self.bits_in_queue + 7)/8: %u | self.rate/8 - (self.bits_in_queue + 7)/8: %u ",
                (self.bits_in_queue + 7)/8, self.rate/8 - (self.bits_in_queue + 7)/8 ));
            self.data_queue.mut_slice_from((self.bits_in_queue + 7)/8).mut_iter()
                .take_(self.rate/8 - (self.bits_in_queue + 7)/8 )
                .advance(|n| {*n = 0; true});
            self.data_queue[self.bits_in_queue/8] |= 1 << (self.bits_in_queue % 8);
        }
        self.data_queue[(self.rate-1)/8] |= 1 << ((self.rate-1) % 8) - 7;
        self.absorb_queue();

        debug!("--- Switching to squeezing phase ---");

        if self.rate == 1024 {
            debug!("Fast 1024");
            reference::extract_1024_bits(self.state, self.data_queue);
            self.bits_for_squeezing = 1024;
        } else {
            debug!("Other rate");
            reference::extract(self.state, self.data_queue, self.rate/64);
            self.bits_for_squeezing = self.rate;
        }

        debug!(fmt!("Block available for squeezing: %?", self.data_queue.slice_to(self.bits_for_squeezing / 8)));
        self.squeezing = true;
    }

    pub fn squeeze(&mut self, out: &mut[u8], out_len: uint) -> SpongeError {
        use std::vec::raw::copy_memory;

        if !self.squeezing {
            self.pad_and_switch_to_squeeze();
        }
        if out_len % 8 != 0 {
            return Failure;
        }

        let mut i = 0;
        let mut part_block;

        while i < out_len {
            if self.bits_for_squeezing == 0 {
                reference::permute(self.state);

                if self.rate == 1024 {
                    reference::extract_1024_bits(self.state, self.data_queue);
                    self.bits_for_squeezing = 1024;
                } else {
                    reference::extract(self.state, self.data_queue, self.rate / 64);
                    self.bits_for_squeezing = self.rate;
                }

                debug!(fmt!("Blocks available for squeezing: %?", self.data_queue.slice_to(self.bits_for_squeezing / 8)));
            }

            part_block = self.bits_for_squeezing;
            if part_block > out_len - 1 {
                part_block = out_len - i;
            }

            unsafe {
                copy_memory(out.mut_slice_from(i/8),
                    self.data_queue.slice_from((self.rate - self.bits_for_squeezing) / 8),
                    part_block/8);
            }
            self.bits_for_squeezing -= part_block;
            i += part_block;
        }

        Success
    }

    priv fn absorb_queue(&mut self) {
        debug!("Absorbing Queue");
        debug!(fmt!("Block to be absorbed: %?", self.data_queue.slice_to(self.rate/8)));
        match self.rate {
            576 => reference::absorb_576_bits(self.state, self.data_queue),
            832 => reference::absorb_832_bits(self.state, self.data_queue),
            1024 => reference::absorb_1024_bits(self.state, self.data_queue),
            1088 => reference::absorb_1088_bits(self.state, self.data_queue),
            1152 => reference::absorb_1152_bits(self.state, self.data_queue),
            1344 => reference::absorb_1344_bits(self.state, self.data_queue),
            _ => reference::absorb(self.state, self.data_queue, self.rate / 64)
        }

        self.bits_in_queue = 0;
    }
}
<commit_msg>fixed minor error<commit_after>use consts::*;
use std::uint::range;
use reference;

#[packed]
pub struct SpongeState {
    state: [u8, ..PERM_SIZE_IN_BYTES],
    data_queue: [u8, ..MAX_RATE_IN_BYTES],
    rate: uint,
    capacity: uint,
    bits_in_queue: uint,
    fixed_out_len: uint,
    squeezing: bool,
    bits_for_squeezing: uint,
}

#[deriving(Eq,TotalEq,ToStr,Clone)]
pub enum SpongeError {
    Success,
    Failure,
}

impl SpongeState {
    pub fn new(rate: uint, capacity: uint) -> SpongeState {
        assert!(rate + capacity == 1600);
        assert!(rate % 64 == 0);

        debug!(fmt!("Rate = %u", rate));

        SpongeState {
            state: [0u8, ..PERM_SIZE_IN_BYTES],
            data_queue: [0u8, ..MAX_RATE_IN_BYTES],
            rate: rate,
            capacity: capacity,
            fixed_out_len: 0,
            bits_in_queue: 0,
            bits_for_squeezing: 0,
            squeezing: false
        }
    }

    pub fn absorb(&mut self, data: &[u8], data_bit_len: uint) -> SpongeError {
        use std::vec::raw::*;
        use std::vec::*;

        if self.bits_in_queue % 8 != 0 {
            return Failure;
        }
        if self.squeezing {
            return Failure;
        }

        let mut whole_blocks;
        let mut cur_data;
        let mut part_block;
        let mut part_byte;
        let mut i = 0u;

        while i < data_bit_len {
            debug!(fmt!("data_bit_len = %u : self.rate = %u", data_bit_len, self.rate));
            if (self.bits_in_queue == 0) && (data_bit_len >= self.rate)
                && (i <=  (data_bit_len - self.rate)) {
                whole_blocks = (data_bit_len - i) / self.rate;
                cur_data = to_ptr(data) + i/8;

                unsafe {
                    match self.rate {
                        576 => {
                            for range(0, whole_blocks) |_| {
                                do buf_as_slice(cur_data, 576/8) |buf| {
                                    debug!(fmt!("Block to be absorbed: %?", buf));
                                    reference::absorb_576_bits(self.state, buf);
                                }
                                cur_data = cur_data + 576/8;
                            }
                        }
                        832 => {
                            for range(0, whole_blocks) |_| {
                                do buf_as_slice(cur_data, 832/8) |buf| {
                                    debug!(fmt!("Block to be absorbed: %?", buf));
                                    reference::absorb_832_bits(self.state, buf);
                                }
                                cur_data = cur_data + 832/8;
                            }
                        }
                        1024 => {
                            for range(0, whole_blocks) |_| {
                                do buf_as_slice(cur_data, 1024/8) |buf| {
                                    debug!(fmt!("Block to be absorbed: %?", buf));
                                    reference::absorb_1024_bits(self.state, buf);
                                }
                                cur_data = cur_data + 1024/8;
                            }
                        }
                        1088 => {
                            for range(0, whole_blocks) |_| {
                                do buf_as_slice(cur_data, 1088/8) |buf| {
                                    debug!(fmt!("Block to be absorbed: %?", buf));
                                    reference::absorb_1088_bits(self.state, buf);
                                }
                                cur_data = cur_data + 1088/8;
                            }
                        }
                        1152 => {
                            for range(0, whole_blocks) |_| {
                                do buf_as_slice(cur_data, 1152/8) |buf| {
                                    debug!(fmt!("Block to be absorbed: %?", buf));
                                    reference::absorb_1152_bits(self.state, buf);
                                }
                                cur_data = cur_data + 1152/8;
                            }
                        }
                        1344 => {
                            for range(0, whole_blocks) |_| {
                                do buf_as_slice(cur_data, 1344/8) |buf| {
                                    debug!(fmt!("Block to be absorbed: %?", buf));
                                    reference::absorb_1344_bits(self.state, buf);
                                }
                                cur_data = cur_data + 1344/8;
                            }
                        }
                        n => {
                            for range(0, whole_blocks) |_| {
                                do buf_as_slice(cur_data, n/8) |buf| {
                                    debug!(fmt!("Block to be absorbed: %?", buf));
                                    reference::absorb(self.state, buf, self.rate / 64);
                                }
                                cur_data = cur_data + self.rate/8;
                            }
                        }
                    }
                }
                i += whole_blocks * self.rate;
            } else {
                part_block = (data_bit_len - i);
                if part_block + self.bits_in_queue > self.rate {
                    part_block = self.rate - self.bits_in_queue;
                }
                part_byte = part_block % 8;
                part_block -= part_byte;
                unsafe {
                    let dq: &mut[u8] = self.data_queue;
                    copy_memory(dq
                        .mut_slice_from(self.bits_in_queue/8),
                        data.slice_from(i/8),
                        part_block/8);
                }
                self.bits_in_queue += part_block;
                i += part_block;

                if self.bits_in_queue == self.rate {
                    self.absorb_queue();
                }
                if part_byte > 0 {
                    let mask: u8 = (1 << part_byte) - 1;
                    self.data_queue[self.bits_in_queue/8] = data[i/8] & mask;
                    self.bits_in_queue += part_byte;
                    i += part_byte;
                }
            }

            debug!(fmt!("i = %u",i));
        }

        Success
    }

    priv fn pad_and_switch_to_squeeze(&mut self) {
        debug!(fmt!("Bits in queue: %u %?",self.bits_in_queue, self.data_queue));
        if self.bits_in_queue + 1 == self.rate {
            self.data_queue[self.bits_in_queue/8] |= 1 << (self.bits_in_queue % 8);
            self.absorb_queue();
            self.data_queue.mut_iter().take_(self.rate/8).advance(|n| {*n = 0; true});
        } else {
            debug!(fmt!("(self.bits_in_queue + 7)/8: %u | self.rate/8 - (self.bits_in_queue + 7)/8: %u ",
                (self.bits_in_queue + 7)/8, self.rate/8 - (self.bits_in_queue + 7)/8 ));
            self.data_queue.mut_slice_from((self.bits_in_queue + 7)/8).mut_iter()
                .take_(self.rate/8 - (self.bits_in_queue + 7)/8 )
                .advance(|n| {*n = 0; true});
            self.data_queue[self.bits_in_queue/8] |= 1 << (self.bits_in_queue % 8);
        }
        self.data_queue[(self.rate-1)/8] |= 1 << ((self.rate-1) % 8);
        self.absorb_queue();

        debug!("--- Switching to squeezing phase ---");

        if self.rate == 1024 {
            debug!("Fast 1024");
            reference::extract_1024_bits(self.state, self.data_queue);
            self.bits_for_squeezing = 1024;
        } else {
            debug!("Other rate");
            reference::extract(self.state, self.data_queue, self.rate/64);
            self.bits_for_squeezing = self.rate;
        }

        debug!(fmt!("Block available for squeezing: %?", self.data_queue.slice_to(self.bits_for_squeezing / 8)));
        self.squeezing = true;
    }

    pub fn squeeze(&mut self, out: &mut[u8], out_len: uint) -> SpongeError {
        use std::vec::raw::copy_memory;

        if !self.squeezing {
            self.pad_and_switch_to_squeeze();
        }
        if out_len % 8 != 0 {
            return Failure;
        }

        let mut i = 0;
        let mut part_block;

        while i < out_len {
            if self.bits_for_squeezing == 0 {
                reference::permute(self.state);

                if self.rate == 1024 {
                    reference::extract_1024_bits(self.state, self.data_queue);
                    self.bits_for_squeezing = 1024;
                } else {
                    reference::extract(self.state, self.data_queue, self.rate / 64);
                    self.bits_for_squeezing = self.rate;
                }

                debug!(fmt!("Blocks available for squeezing: %?", self.data_queue.slice_to(self.bits_for_squeezing / 8)));
            }

            part_block = self.bits_for_squeezing;
            if part_block > out_len - 1 {
                part_block = out_len - i;
            }

            unsafe {
                copy_memory(out.mut_slice_from(i/8),
                    self.data_queue.slice_from((self.rate - self.bits_for_squeezing) / 8),
                    part_block/8);
            }
            self.bits_for_squeezing -= part_block;
            i += part_block;
        }

        Success
    }

    priv fn absorb_queue(&mut self) {
        debug!("Absorbing Queue");
        debug!(fmt!("Block to be absorbed: %?", self.data_queue.slice_to(self.rate/8)));
        match self.rate {
            576 => reference::absorb_576_bits(self.state, self.data_queue),
            832 => reference::absorb_832_bits(self.state, self.data_queue),
            1024 => reference::absorb_1024_bits(self.state, self.data_queue),
            1088 => reference::absorb_1088_bits(self.state, self.data_queue),
            1152 => reference::absorb_1152_bits(self.state, self.data_queue),
            1344 => reference::absorb_1344_bits(self.state, self.data_queue),
            _ => reference::absorb(self.state, self.data_queue, self.rate / 64)
        }

        self.bits_in_queue = 0;
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate ndarray;

use ndarray::{
    RcArray,
    Ix,
};

type Ix2 = (Ix, Ix);

const INPUT: &'static [u8] = include_bytes!("life.txt");
//const INPUT: &'static [u8] = include_bytes!("lifelite.txt");

const N: usize = 100;
//const N: usize = 8;

type Board = RcArray<u8, Ix2>;

fn parse(x: &[u8]) -> Board {
    // make a border of 0 cells
    let mut map = RcArray::from_elem(((N + 2) as Ix, (N + 2) as Ix), 0);
    let a: RcArray<u8, Ix> = x.iter().filter_map(|&b| match b {
        b'#' => Some(1),
        b'.' => Some(0),
        _ => None,
    }).collect();

    let a = a.reshape((N as Ix, N as Ix));
    map.slice_mut(s![1..-1, 1..-1]).assign(&a);
    map
}

// Rules
//
// 2 or 3 neighbors: stay alive
// 3 neighbors: birth
// otherwise: death

fn iterate(z: &mut Board, scratch: &mut Board) {
    // compute number of neighbors
    let mut neigh = scratch.view_mut();
    neigh.assign_scalar(&0);
    neigh.iadd(&z.slice(s![0..-2, 0..-2]));
    neigh.iadd(&z.slice(s![0..-2, 1..-1]));
    neigh.iadd(&z.slice(s![0..-2, 2..  ]));

    neigh.iadd(&z.slice(s![1..-1, 0..-2]));
    neigh.iadd(&z.slice(s![1..-1, 2..  ]));

    neigh.iadd(&z.slice(s![2..  , 0..-2]));
    neigh.iadd(&z.slice(s![2..  , 1..-1]));
    neigh.iadd(&z.slice(s![2..  , 2..  ]));

    // birth where n = 3 and z[i] = 0,
    // survive where n = 2 || n = 3 and z[i] = 1
    let mut zv = z.slice_mut(s![1..-1, 1..-1]);

    // this is autovectorized amazingly well!
    zv.zip_mut_with(&neigh, |y, &n| {
        *y = ((n == 3) || (n == 2 && *y > 0)) as u8
    });
}

fn turn_on_corners(z: &mut Board) {
    let (n, m) = z.dim();
    z[[1    , 1    ]] = 1;
    z[[1    , m - 2]] = 1;
    z[[n - 2, 1    ]] = 1;
    z[[n - 2, m - 2]] = 1;
}

fn render(a: &Board) {
    for row in a.inner_iter() {
        for &x in row {
            if x > 0 {
                print!("#");
            } else {
                print!(".");
            }
        }
        println!("");
    }
}

fn main() {
    let mut a = parse(INPUT);
    let mut scratch = Board::zeros((N as Ix, N as Ix));
    let steps = 100;
    turn_on_corners(&mut a);
    for _ in 0..steps {
        iterate(&mut a, &mut scratch);
        turn_on_corners(&mut a);
        //render(&a);
    }
    render(&a);
    let alive = a.iter().filter(|&&x| x > 0).count();
    println!("After {} steps there are {} cells alive", steps, alive);
}
<commit_msg>Use += in examples/life.rs<commit_after>#![cfg_attr(feature = "assign_ops", feature(augmented_assignments))]
#[macro_use]
extern crate ndarray;

use ndarray::{
    RcArray,
    Ix,
};

type Ix2 = (Ix, Ix);

const INPUT: &'static [u8] = include_bytes!("life.txt");
//const INPUT: &'static [u8] = include_bytes!("lifelite.txt");

const N: usize = 100;
//const N: usize = 8;

type Board = RcArray<u8, Ix2>;

fn parse(x: &[u8]) -> Board {
    // make a border of 0 cells
    let mut map = RcArray::from_elem(((N + 2) as Ix, (N + 2) as Ix), 0);
    let a: RcArray<u8, Ix> = x.iter().filter_map(|&b| match b {
        b'#' => Some(1),
        b'.' => Some(0),
        _ => None,
    }).collect();

    let a = a.reshape((N as Ix, N as Ix));
    map.slice_mut(s![1..-1, 1..-1]).assign(&a);
    map
}

// Rules
//
// 2 or 3 neighbors: stay alive
// 3 neighbors: birth
// otherwise: death

#[cfg(feature = "assign_ops")]
fn iterate(z: &mut Board, scratch: &mut Board) {
    // compute number of neighbors
    let mut neigh = scratch.view_mut();
    neigh.assign_scalar(&0);
    neigh += &z.slice(s![0..-2, 0..-2]);
    neigh += &z.slice(s![0..-2, 1..-1]);
    neigh += &z.slice(s![0..-2, 2..  ]);

    neigh += &z.slice(s![1..-1, 0..-2]);
    neigh += &z.slice(s![1..-1, 2..  ]);

    neigh += &z.slice(s![2..  , 0..-2]);
    neigh += &z.slice(s![2..  , 1..-1]);
    neigh += &z.slice(s![2..  , 2..  ]);

    // birth where n = 3 and z[i] = 0,
    // survive where n = 2 || n = 3 and z[i] = 1
    let mut zv = z.slice_mut(s![1..-1, 1..-1]);

    // this is autovectorized amazingly well!
    zv.zip_mut_with(&neigh, |y, &n| {
        *y = ((n == 3) || (n == 2 && *y > 0)) as u8
    });
}

#[cfg(not(feature = "assign_ops"))]
fn iterate(z: &mut Board, scratch: &mut Board) {
    // compute number of neighbors
    let mut neigh = scratch.view_mut();
    neigh.assign_scalar(&0);
    neigh.iadd(&z.slice(s![0..-2, 0..-2]));
    neigh.iadd(&z.slice(s![0..-2, 1..-1]));
    neigh.iadd(&z.slice(s![0..-2, 2..  ]));

    neigh.iadd(&z.slice(s![1..-1, 0..-2]));
    neigh.iadd(&z.slice(s![1..-1, 2..  ]));

    neigh.iadd(&z.slice(s![2..  , 0..-2]));
    neigh.iadd(&z.slice(s![2..  , 1..-1]));
    neigh.iadd(&z.slice(s![2..  , 2..  ]));

    // birth where n = 3 and z[i] = 0,
    // survive where n = 2 || n = 3 and z[i] = 1
    let mut zv = z.slice_mut(s![1..-1, 1..-1]);

    // this is autovectorized amazingly well!
    zv.zip_mut_with(&neigh, |y, &n| {
        *y = ((n == 3) || (n == 2 && *y > 0)) as u8
    });
}

fn turn_on_corners(z: &mut Board) {
    let (n, m) = z.dim();
    z[[1    , 1    ]] = 1;
    z[[1    , m - 2]] = 1;
    z[[n - 2, 1    ]] = 1;
    z[[n - 2, m - 2]] = 1;
}

fn render(a: &Board) {
    for row in a.inner_iter() {
        for &x in row {
            if x > 0 {
                print!("#");
            } else {
                print!(".");
            }
        }
        println!("");
    }
}

fn main() {
    let mut a = parse(INPUT);
    let mut scratch = Board::zeros((N as Ix, N as Ix));
    let steps = 100;
    turn_on_corners(&mut a);
    for _ in 0..steps {
        iterate(&mut a, &mut scratch);
        turn_on_corners(&mut a);
        //render(&a);
    }
    render(&a);
    let alive = a.iter().filter(|&&x| x > 0).count();
    println!("After {} steps there are {} cells alive", steps, alive);
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate ndarray;

use ndarray::{
    Array,
    Ix,
};

type Ix2 = (Ix, Ix);

const INPUT: &'static [u8] = include_bytes!("life.txt");
//const INPUT: &'static [u8] = include_bytes!("lifelite.txt");

const N: usize = 100;
//const N: usize = 8;

type Board = Array<u8, Ix2>;

fn parse(x: &[u8]) -> Board {
    // make a border of 0 cells
    let mut map = Array::from_elem(((N + 2) as Ix, (N + 2) as Ix), 0);
    let a: Array<u8, Ix> = x.iter().filter_map(|&b| match b {
        b'#' => Some(1),
        b'.' => Some(0),
        _ => None,
    }).collect();

    let a = a.reshape((N as Ix, N as Ix));
    map.slice_mut(s![1..-1, 1..-1]).assign(&a);
    map
}

// Rules
//
// 2 or 3 neighbors: stay alive
// 3 neighbors: birth
// otherwise: death

fn iterate(z: &mut Board, scratch: &mut Board) {
    // compute number of neighbors
    let mut neigh = scratch.view_mut();
    neigh.assign_scalar(&0);
    let neigh = neigh
    + z.slice(s![0..-2, 0..-2])
    + z.slice(s![0..-2, 1..-1])
    + z.slice(s![0..-2, 2..  ])

    + z.slice(s![1..-1, 0..-2])
    + z.slice(s![1..-1, 2..  ])

    + z.slice(s![2..  , 0..-2])
    + z.slice(s![2..  , 1..-1])
    + z.slice(s![2..  , 2..  ]);

    // birth where n = 3 and z[i] = 0,
    // survive where n = 2 || n = 3 and z[i] = 1
    {
        let mut zv = z.slice_mut(s![1..-1, 1..-1]);

        zv.zip_mut_with(&neigh, |y, &n| {
            if n == 3 {
                *y = 1;
            } else if n == 2 {
            } else {
                *y = 0;
            }
        });
    }
}

fn turn_on_corners(z: &mut Board) {
    z.slice_mut(s![1..2, 1..2]).assign_scalar(&1);
    z.slice_mut(s![1..2, -2..-1]).assign_scalar(&1);
    z.slice_mut(s![-2..-1, 1..2]).assign_scalar(&1);
    z.slice_mut(s![-2..-1, -2..-1]).assign_scalar(&1);
}

fn render(a: &Board) {
    for row in 0..a.shape()[0] {
        for &x in a.row_iter(row) {
            if x > 0 {
                print!("#");
            } else {
                print!(".");
            }
        }
        println!("");
    }
}

fn main() {
    let mut a = parse(INPUT);
    let mut scratch = Board::zeros((N as Ix, N as Ix));
    let steps = 100;
    turn_on_corners(&mut a);
    for _ in 0..steps {
        iterate(&mut a, &mut scratch);
        turn_on_corners(&mut a);
        //render(&a);
    }
    render(&a);
    let alive = a.iter().filter(|&&x| x > 0).count();
    println!("After {} steps there are {} cells alive", steps, alive);
}
<commit_msg>Improve Game of Life example -- the neighbor update loop vectorizes amazingly<commit_after>#[macro_use]
extern crate ndarray;

use ndarray::{
    Array,
    Ix,
};

type Ix2 = (Ix, Ix);

const INPUT: &'static [u8] = include_bytes!("life.txt");
//const INPUT: &'static [u8] = include_bytes!("lifelite.txt");

const N: usize = 100;
//const N: usize = 8;

type Board = Array<u8, Ix2>;

fn parse(x: &[u8]) -> Board {
    // make a border of 0 cells
    let mut map = Array::from_elem(((N + 2) as Ix, (N + 2) as Ix), 0);
    let a: Array<u8, Ix> = x.iter().filter_map(|&b| match b {
        b'#' => Some(1),
        b'.' => Some(0),
        _ => None,
    }).collect();

    let a = a.reshape((N as Ix, N as Ix));
    map.slice_mut(s![1..-1, 1..-1]).assign(&a);
    map
}

// Rules
//
// 2 or 3 neighbors: stay alive
// 3 neighbors: birth
// otherwise: death

fn iterate(z: &mut Board, scratch: &mut Board) {
    // compute number of neighbors
    let mut neigh = scratch.view_mut();
    neigh.assign_scalar(&0);
    let neigh = neigh
    + z.slice(s![0..-2, 0..-2])
    + z.slice(s![0..-2, 1..-1])
    + z.slice(s![0..-2, 2..  ])

    + z.slice(s![1..-1, 0..-2])
    + z.slice(s![1..-1, 2..  ])

    + z.slice(s![2..  , 0..-2])
    + z.slice(s![2..  , 1..-1])
    + z.slice(s![2..  , 2..  ]);

    // birth where n = 3 and z[i] = 0,
    // survive where n = 2 || n = 3 and z[i] = 1
    let mut zv = z.slice_mut(s![1..-1, 1..-1]);

    // this is autovectorized amazingly well!
    zv.zip_mut_with(&neigh, |y, &n| {
        *y = ((n == 3) || (n == 2 && *y > 0)) as u8
    });
}

fn turn_on_corners(z: &mut Board) {
    z.slice_mut(s![1..2, 1..2]).assign_scalar(&1);
    z.slice_mut(s![1..2, -2..-1]).assign_scalar(&1);
    z.slice_mut(s![-2..-1, 1..2]).assign_scalar(&1);
    z.slice_mut(s![-2..-1, -2..-1]).assign_scalar(&1);
}

fn render(a: &Board) {
    for row in 0..a.shape()[0] {
        for &x in a.row_iter(row) {
            if x > 0 {
                print!("#");
            } else {
                print!(".");
            }
        }
        println!("");
    }
}

fn main() {
    let mut a = parse(INPUT);
    let mut scratch = Board::zeros((N as Ix, N as Ix));
    let steps = 100;
    turn_on_corners(&mut a);
    for _ in 0..steps {
        iterate(&mut a, &mut scratch);
        turn_on_corners(&mut a);
        //render(&a);
    }
    render(&a);
    let alive = a.iter().filter(|&&x| x > 0).count();
    println!("After {} steps there are {} cells alive", steps, alive);
}
<|endoftext|>


<commit_before>//HACK: This is how we're splitting the maze example into multiple files since
// cargo doesn't properly support examples with multiple files yet
#[path = "maze/wall.rs"]
mod wall;
#[path = "maze/cell.rs"]
mod cell;
#[path = "maze/maze.rs"]
mod maze;
#[path = "maze/grid.rs"]
mod grid;

extern crate turtle;

use turtle::Turtle;

pub use maze::Maze;
use grid::{GridCellIter};
use cell::Cell;

// Dimensions of the maze in turtle steps (pixels)
const WIDTH: f64 = 600.0; // px
const HEIGHT: f64 = 600.0; // px

fn main() {
    let maze = Maze::generate();

    let mut turtle = Turtle::new();
    turtle.set_speed(9);
    turtle.set_background_color("#A5D6A7");
    turtle.set_pen_color("#03A9F4");
    turtle.set_pen_size(5.0);

    // Get to the top left corner
    turtle.pen_up();
    turtle.forward(HEIGHT / 2.0);
    turtle.right(90.0);
    turtle.backward(WIDTH / 2.0);
    turtle.pen_down();

    let cell_width = WIDTH/(maze.row_size() as f64);
    let cell_height = HEIGHT/(maze.col_size() as f64);

    // Draw rows
    draw_rows(
        &mut turtle,
        cell_width,
        cell_height,
        maze.first_row().map(|cell| cell.north.is_closed()),
        maze.rows(),
        |cell| cell.south.is_closed(),
        false,
    );

    // Draw columns
    turtle.left(90.0);
    draw_rows(
        &mut turtle,
        cell_height,
        cell_width,
        maze.last_col().map(|cell| cell.east.is_closed()),
        maze.cols().rev(),
        |cell| cell.west.is_closed(),
        true,
    );
}

fn draw_rows<'a, R: Iterator<Item=bool>, G: Iterator<Item=GridCellIter<'a>>, F: Fn(&Cell) -> bool>(
    turtle: &mut Turtle,
    // size of each cell in the row
    cell_size: f64,
    // gap between rows
    cell_gap: f64,
    first_row: R,
    rows: G,
    row_walls: F,
    rotate_left: bool,
) {
    draw_row(turtle, cell_size, first_row);

    // Direction of rotation for all turns
    let rotation = if rotate_left { -1.0 } else { 1.0 };
    for (i, row) in rows.enumerate() {
        turtle.pen_up();

        // Direction of rotation for these turns
        let direction = rotation * if i % 2 == 0 {
            1.0
        } else {
            -1.0
        };
        turtle.right(direction * 90.0);
        turtle.forward(cell_gap);
        turtle.right(direction * 90.0);
        turtle.pen_down();

        let walls = row.map(&row_walls);

        // Every second row needs to be reversed so the turtle can zig-zag back and
        // forth instead of wasting too much time moving all the way to the left of
        // each row
        if i % 2 == 0 {
            draw_row(turtle, cell_size, walls.rev());
        }
        else {
            draw_row(turtle, cell_size, walls);
        }
    }
}

fn draw_row<I: Iterator<Item=bool>>(turtle: &mut Turtle, wall_size: f64, walls: I) {
    for should_draw in walls {
        if !should_draw {
            turtle.pen_up();
        }
        turtle.forward(wall_size);
        turtle.pen_down();
    }
}
<commit_msg>Fixing bugs in the rendering code<commit_after>//HACK: This is how we're splitting the maze example into multiple files since
// cargo doesn't properly support examples with multiple files yet
#[path = "maze/wall.rs"]
mod wall;
#[path = "maze/cell.rs"]
mod cell;
#[path = "maze/maze.rs"]
mod maze;
#[path = "maze/grid.rs"]
mod grid;

extern crate turtle;

use turtle::Turtle;

pub use maze::Maze;
use grid::{GridCellIter};
use cell::Cell;

// Dimensions of the maze in turtle steps (pixels)
const WIDTH: f64 = 600.0; // px
const HEIGHT: f64 = 600.0; // px

fn main() {
    let maze = Maze::generate();

    let mut turtle = Turtle::new();
    turtle.set_speed(10);
    turtle.set_background_color("#A5D6A7");
    turtle.set_pen_color("#03A9F4");
    turtle.set_pen_size(2.0);

    // Get to the top left corner
    turtle.pen_up();
    turtle.forward(HEIGHT / 2.0);
    turtle.right(90.0);
    turtle.backward(WIDTH / 2.0);
    turtle.pen_down();

    let cell_width = WIDTH/(maze.row_size() as f64);
    let cell_height = HEIGHT/(maze.col_size() as f64);

    // Draw rows
    draw_rows(
        &mut turtle,
        cell_width,
        cell_height,
        maze.first_row().map(|cell| cell.north.is_closed()),
        maze.rows(),
        |row| row.map(|cell| cell.south.is_closed()),
        false,
    );

    // Draw columns
    turtle.left(90.0);
    draw_rows(
        &mut turtle,
        cell_height,
        cell_width,
        maze.last_col().rev().map(|cell| cell.east.is_closed()),
        maze.cols().rev(),
        |col| col.map(|cell| cell.west.is_closed()).rev(),
        true,
    );
}

fn draw_rows<
    'a,
    R: Iterator<Item=bool>,
    G: Iterator<Item=GridCellIter<'a>>,
    F: Fn(GridCellIter<'a>) -> X,
    X: Iterator<Item=bool> + DoubleEndedIterator
>(
    turtle: &mut Turtle,
    // size of each cell in the row
    cell_size: f64,
    // gap between rows
    cell_gap: f64,
    first_row: R,
    rows: G,
    row_walls: F,
    rotate_left: bool,
) {
    draw_row(turtle, cell_size, first_row);

    // Direction of rotation for all turns
    let rotation = if rotate_left { -1.0 } else { 1.0 };
    for (i, row) in rows.enumerate() {
        turtle.pen_up();

        // Direction of rotation for these turns
        let direction = rotation * if i % 2 == 0 { 1.0 } else { -1.0 };
        turtle.right(direction * 90.0);
        turtle.forward(cell_gap);
        turtle.right(direction * 90.0);
        turtle.pen_down();

        let walls = row_walls(row);

        // Every second row needs to be reversed so the turtle can zig-zag back and
        // forth instead of wasting too much time moving all the way to the left of
        // each row
        if i % 2 == 0 {
            draw_row(turtle, cell_size, walls.rev());
        }
        else {
            draw_row(turtle, cell_size, walls);
        }
    }
}

fn draw_row<I: Iterator<Item=bool>>(turtle: &mut Turtle, wall_size: f64, walls: I) {
    for should_draw in walls {
        if !should_draw {
            turtle.pen_up();
        }
        turtle.forward(wall_size);
        turtle.pen_down();
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Nikita Pekin and the xkcd_rs contributors
// See the README.md file at the top-level directory of this distribution.
//
// 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.

extern crate hyper;
extern crate xkcd;

fn main() {
    let client = hyper::Client::new();

    // Retrieve the latest comic ID.
    let latest_id = xkcd::comics::latest(&client).unwrap().num;

    // Retrieve all the comics.
    let mut all_comics = Vec::new();
    for i in 1..latest_id + 1 {
        // Skip 404 because that's the 404 page and not a comic.
        if i == 404 {
            continue;
        }

        all_comics.push(xkcd::comics::get(&client, i).unwrap());
    }
}
<commit_msg>impr(examples): "all" example output more verbose<commit_after>// Copyright (c) 2016 Nikita Pekin and the xkcd_rs contributors
// See the README.md file at the top-level directory of this distribution.
//
// 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.

extern crate hyper;
extern crate xkcd;

fn main() {
    let client = hyper::Client::new();

    // Retrieve the latest comic ID.
    let latest_id = xkcd::comics::latest(&client).unwrap().num;

    // Retrieve all the comics.
    let mut all_comics = Vec::new();
    let start = 1;
    let end = latest_id + 1;
    println!("Retrieving comics from {} to {}", start, end);
    for i in start..end {
        // Skip 404 because that's the 404 page and not a comic.
        if i == 404 {
            continue;
        }

        all_comics.push(xkcd::comics::get(&client, i).unwrap());
        println!("Read comic: {}", i);
    }
}
<|endoftext|>


<commit_before>use std::io::Read;
use std::io::Write;
use std::path::Path;
use std::fs::File;

use tomson::Toml;
use handlebars::Handlebars;
use rustc_serialize::json::Json;

fn generate_code(mut toml: String) -> String {
    // turn the toml string into json for compatibility with handlebars
    let mut json = Toml::as_json(&mut toml).unwrap();

    for (id, field) in json.as_object_mut().unwrap().get_mut("field").unwrap().as_object_mut().unwrap().iter_mut() {
        let field_obj = field.as_object_mut().unwrap();
        let field_type = field_obj.get("type").unwrap().as_string().unwrap().to_string();
        let field_name = id.clone();
        let component_name = if let Some(component_json) = field_obj.get("component") {
            component_json.as_string().unwrap().to_string()
        } else {
            id.clone()
        };

        let component_has_type = if let Some(component_has_type_json) = field_obj.get("component_has_type") {
            component_has_type_json.as_boolean().unwrap()
        } else {
            false
        };

        field_obj.insert("struct_field_name".to_string(), Json::String(field_name.clone()));
        field_obj.insert("getter_name".to_string(), Json::String(id.clone()));
        field_obj.insert("component_name".to_string(), Json::String(component_name.clone()));
        field_obj.insert(field_type.clone(), Json::Boolean(true));

        if component_has_type {
            field_obj.insert("component_has_type".to_string(), Json::Boolean(true));
        }

        match field_type.as_ref() {
            "sum_f64" => {
                field_obj.insert("struct_field_type".to_string(), Json::String("f64".to_string()));
                field_obj.insert("struct_field_cons".to_string(), Json::String("0.0".to_string()));
                field_obj.insert("getter_type".to_string(), Json::String("f64".to_string()));
                field_obj.insert("getter_expr".to_string(), Json::String(format!("self.{}", field_name)));
                field_obj.insert("remove_entity".to_string(), Json::String(format!("if let Some(v) = entity.{}() {{ cell.{} -= v; }}",
                                                                                component_name, field_name)));
                field_obj.insert("insert_entity".to_string(), Json::String(format!("if let Some(v) = entity.{}() {{ cell.{} += v; }}",
                                                                                component_name, field_name)));
            }
            "count_bool" => {
                field_obj.insert("struct_field_type".to_string(), Json::String("usize".to_string()));
                field_obj.insert("struct_field_cons".to_string(), Json::String("0".to_string()));
                field_obj.insert("getter_type".to_string(), Json::String("bool".to_string()));
                field_obj.insert("getter_expr".to_string(), Json::String(format!("self.{} != 0", field_name)));
                field_obj.insert("remove_entity".to_string(), Json::String(format!("if entity.contains_{}() {{ cell.{} -= 1; }}",
                                                                                component_name, field_name)));
                field_obj.insert("insert_entity".to_string(), Json::String(format!("if entity.contains_{}() {{ cell.{} += 1; }}",
                                                                                component_name, field_name)));
            }
            "any" => {
                field_obj.insert("struct_field_type".to_string(), Json::String("AnySet<EntityId>".to_string()));
                field_obj.insert("struct_field_cons".to_string(), Json::String("AnySet::new()".to_string()));
                field_obj.insert("getter_type".to_string(), Json::String("bool".to_string()));
                field_obj.insert("getter_expr".to_string(), Json::String(format!("!self.{}.is_empty()", field_name)));
                field_obj.insert("any_name".to_string(), Json::String(format!("any_{}", field_name)));
                field_obj.insert("any_type".to_string(), Json::String("Option<EntityId>".to_string()));
                field_obj.insert("any_expr".to_string(), Json::String(format!("self.{}.any()", field_name)));
                field_obj.insert("remove_entity".to_string(), Json::String(format!("if entity.contains_{}() {{ cell.{}.remove(entity.id()); }}",
                                                                                component_name, field_name)));
                field_obj.insert("insert_entity".to_string(), Json::String(format!("if entity.contains_{}() {{ cell.{}.insert(entity.id()); }}",
                                                                                component_name, field_name)));
                field_obj.insert("is_set_type".to_string(), Json::Boolean(true));
            }
            "set" => {
                field_obj.insert("struct_field_type".to_string(), Json::String("EntitySet".to_string()));
                field_obj.insert("struct_field_cons".to_string(), Json::String("EntitySet::new()".to_string()));
                field_obj.insert("getter_type".to_string(), Json::String("bool".to_string()));
                field_obj.insert("getter_expr".to_string(), Json::String(format!("!self.{}.is_empty()", field_name)));
                field_obj.insert("iter_name".to_string(), Json::String(format!("{}_iter", field_name)));
                field_obj.insert("iter_type".to_string(), Json::String("EntitySetIter".to_string()));
                field_obj.insert("iter_expr".to_string(), Json::String(format!("self.{}.iter()", field_name)));
                field_obj.insert("remove_entity".to_string(), Json::String(format!("if entity.contains_{}() {{ cell.{}.remove(entity.id()); }}",
                                                                                component_name, field_name)));
                field_obj.insert("insert_entity".to_string(), Json::String(format!("if entity.contains_{}() {{ cell.{}.insert(entity.id()); }}",
                                                                                component_name, field_name)));
                field_obj.insert("is_set_type".to_string(), Json::Boolean(true));
            }
            other => panic!("unknown field type {}", other),
        }
    }

    let mut handlebars = Handlebars::new();

    // prevent xml escaping
    handlebars.register_escape_fn(|input| input.to_string());
    handlebars.template_render(TEMPLATE, &json).unwrap()

}

fn read_file_to_string<P: AsRef<Path>>(path: P) -> String {
    let mut file = File::open(path).unwrap();
    let mut string = String::new();
    file.read_to_string(&mut string).unwrap();

    string
}

pub fn generate_spatial_hash<P: AsRef<Path>, Q: AsRef<Path>>(in_path: P, out_path: Q) {
    let string = read_file_to_string(in_path);

    let output_string = generate_code(string);

    let mut outfile = File::create(out_path).unwrap();
    write!(outfile, "{}", output_string).unwrap();
}

const TEMPLATE: &'static str = r#"// Automatically generated. Do not edit.
#![allow(unused_imports)]
use ecs::*;
use coord::Coord;
use grid::{Grid, StaticGrid, DefaultGrid, IterGrid, CoordIterGrid};
use util::AnySet;

pub type SpatialHashCellIter<'a> = <StaticGrid<SpatialHashCell> as IterGrid<'a>>::Iter;
pub type SpatialHashCoordIter = <StaticGrid<SpatialHashCell> as CoordIterGrid>::CoordIter;

pub struct SpatialHashCell {

{{#each field}}
    {{ struct_field_name }}: {{ struct_field_type }},
{{/each}}

    // set of entities currently in this cell
    entities: EntitySet,

    // action on which this cell was last updated
    last_updated: u64,
}

impl SpatialHashCell {
    pub fn new() -> Self {
        SpatialHashCell {
{{#each field}}
            {{ struct_field_name }}: {{ struct_field_cons }},
{{/each}}

            entities: EntitySet::new(),
            last_updated: 0,
        }
    }

    pub fn last_updated(&self) -> u64 {
        self.last_updated
    }

    pub fn entity_ids(&self) -> &EntitySet {
        &self.entities
    }

    pub fn entity_id_iter(&self) -> EntitySetIter {
        self.entities.iter()
    }

{{#each field}}
    pub fn {{ getter_name }}(&self) -> {{ getter_type }} {
        {{ getter_expr }}
    }
    {{#if iter_name}}
    pub fn {{ iter_name }}(&self) -> {{ iter_type }} {
        {{ iter_expr }}
    }
    {{/if}}
    {{#if any_name}}
    pub fn {{ any_name }}(&self) -> {{ any_type }} {
        {{ any_expr }}
    }
    {{/if}}
{{/each}}
}

impl Default for SpatialHashCell {
    fn default() -> Self {
        Self::new()
    }
}

pub struct SpatialHashTable {
    grid: StaticGrid<SpatialHashCell>,
    empty: SpatialHashCell,
}

impl SpatialHashTable {
    pub fn new(width: usize, height: usize) -> Self {
        SpatialHashTable {
            grid: StaticGrid::new_default(width, height),
            empty: SpatialHashCell::new(),
        }
    }

    pub fn cell_iter(&self) -> SpatialHashCellIter {
        self.grid.iter()
    }

    pub fn coord_iter(&self) -> SpatialHashCoordIter {
        self.grid.coord_iter()
    }

    pub fn get(&self, coord: Coord) -> &SpatialHashCell {
        self.grid.get(coord).unwrap_or(&self.empty)
    }

    pub fn limits_min(&self) -> Coord {
        self.grid.limits_min()
    }

    pub fn limits_max(&self) -> Coord {
        self.grid.limits_max()
    }

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

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

    fn get_mut(&mut self, coord: Coord) -> &mut SpatialHashCell {
        unsafe { self.grid.get_unchecked_mut(coord) }
    }

    fn change_entity_position(&mut self, entity: EntityRef, current_position: Coord, new_position: Coord, action_id: u64) {
        self.remove_entity_position(entity, current_position, action_id);
        self.add_entity_position(entity, new_position, action_id);
    }

    fn remove_entity_position(&mut self, entity: EntityRef, position: Coord, action_id: u64) {
        let mut cell = self.get_mut(position);

{{#each field}}
        {{ remove_entity }}
{{/each}}

        cell.entities.remove(entity.id());
        cell.last_updated = action_id;
    }

    fn add_entity_position(&mut self, entity: EntityRef, position: Coord, action_id: u64) {
        let mut cell = self.get_mut(position);

{{#each field}}
        {{ insert_entity }}
{{/each}}

        cell.entities.insert(entity.id());
        cell.last_updated = action_id;
    }

    pub fn update(&mut self, ecs: &EcsCtx, action: &EcsAction, action_id: u64) {

        for (entity_id, new_position) in action.position_positive_iter(ecs) {
            let entity = ecs.entity(entity_id);
            // Add and remove tracked components based on the current data stored about the
            // entity, ignoring any component changes in the current action. These will be
            // applied later.
            if let Some(current_position) = entity.position() {
                // the entity is changing position
                self.change_entity_position(entity, current_position, *new_position, action_id);
            } else {
                // the entity is gaining a position
                self.add_entity_position(entity, *new_position, action_id);
            }
        }

        for entity_id in action.position_negative_iter(ecs) {
            let entity = ecs.entity(entity_id);
            if let Some(position) = entity.position() {
                self.remove_entity_position(entity, position, action_id);
            }
        }

{{#each field}}
        self.update_{{ struct_field_name }}(ecs, action, action_id);
{{/each}}
    }

{{#each field}}
    fn update_{{ struct_field_name }}(&mut self, ecs: &EcsCtx, action: &EcsAction, action_id: u64) {
    {{#if count_bool}}
        for entity_id in action.{{ component_name }}_positive_iter(ecs) {
            let entity = ecs.post_action_entity(entity_id, action);
            if let Some(position) = entity.position() {
                if !entity.current_contains_{{ component_name }}() {
                    let cell = self.get_mut(position);
                    cell.{{ struct_field_name }} += 1;
                    cell.last_updated = action_id;
                }
            }
        }

        for entity_id in action.{{ component_name }}_negative_iter(ecs) {
            let entity = ecs.post_action_entity(entity_id, action);
            if let Some(position) = entity.position() {
                if entity.contains_{{ component_name }}() {
                    let cell = self.get_mut(position);
                    cell.{{ struct_field_name }} -= 1;
                    cell.last_updated = action_id;
                }
            }
        }
    {{/if}}
    {{#if sum_f64}}
        for (entity_id, new) in action.{{ component_name }}_positive_iter(ecs) {
            let entity = ecs.post_action_entity(entity_id, action);
            if let Some(position) = entity.position() {
                let current = entity.current_{{ component_name }}().unwrap_or(0.0);
                let increase = new - current;
                let cell = self.get_mut(position);
                cell.{{ struct_field_name }} += increase;
                cell.last_updated = action_id;
            }
        }
        for entity_id in action.{{ component_name }}_negative_iter(ecs) {
            let entity = ecs.post_action_entity(entity_id, action);
            if let Some(position) = entity.position() {
                if let Some(value) = entity.{{ component_name }}() {
                    let cell = self.get_mut(position);
                    cell.{{ struct_field_name }} -= value;
                    cell.last_updated = action_id;
                }
            }
        }
    {{/if}}
    {{#if is_set_type}}
        {{#if component_has_type}}
        for (entity_id, _) in action.{{ component_name }}_positive_iter(ecs) {
        {{else}}
        for entity_id in action.{{ component_name }}_positive_iter(ecs) {
        {{/if}}
            let entity = ecs.post_action_entity(entity_id, action);
            if let Some(position) = entity.position() {
        {{#if component_has_type}}
                if entity.current_{{ component_name }}().is_none() {
        {{else}}
                if !entity.current_contains_{{ component_name }}() {
        {{/if}}
                    let cell = self.get_mut(position);
                    cell.{{ struct_field_name }}.insert(entity_id);
                    cell.last_updated = action_id;
                }
            }
        }
        for entity_id in action.{{ component_name }}_negative_iter(ecs) {
            let entity = ecs.post_action_entity(entity_id, action);
            if let Some(position) = entity.position() {
        {{#if component_has_type}}
                if entity.current_{{ component_name }}().is_some() {
        {{else}}
                if entity.current_contains_{{ component_name }}() {
        {{/if}}
                    let cell = self.get_mut(position);
                    cell.{{ struct_field_name }}.remove(entity_id);
                    cell.last_updated = action_id;
                }
            }
        }
    {{/if}}
    }
{{/each}}
}
"#;

<commit_msg>Fix spatial hash component removal bug<commit_after>use std::io::Read;
use std::io::Write;
use std::path::Path;
use std::fs::File;

use tomson::Toml;
use handlebars::Handlebars;
use rustc_serialize::json::Json;

fn generate_code(mut toml: String) -> String {
    // turn the toml string into json for compatibility with handlebars
    let mut json = Toml::as_json(&mut toml).unwrap();

    for (id, field) in json.as_object_mut().unwrap().get_mut("field").unwrap().as_object_mut().unwrap().iter_mut() {
        let field_obj = field.as_object_mut().unwrap();
        let field_type = field_obj.get("type").unwrap().as_string().unwrap().to_string();
        let field_name = id.clone();
        let component_name = if let Some(component_json) = field_obj.get("component") {
            component_json.as_string().unwrap().to_string()
        } else {
            id.clone()
        };

        let component_has_type = if let Some(component_has_type_json) = field_obj.get("component_has_type") {
            component_has_type_json.as_boolean().unwrap()
        } else {
            false
        };

        field_obj.insert("struct_field_name".to_string(), Json::String(field_name.clone()));
        field_obj.insert("getter_name".to_string(), Json::String(id.clone()));
        field_obj.insert("component_name".to_string(), Json::String(component_name.clone()));
        field_obj.insert(field_type.clone(), Json::Boolean(true));

        if component_has_type {
            field_obj.insert("component_has_type".to_string(), Json::Boolean(true));
        }

        match field_type.as_ref() {
            "sum_f64" => {
                field_obj.insert("struct_field_type".to_string(), Json::String("f64".to_string()));
                field_obj.insert("struct_field_cons".to_string(), Json::String("0.0".to_string()));
                field_obj.insert("getter_type".to_string(), Json::String("f64".to_string()));
                field_obj.insert("getter_expr".to_string(), Json::String(format!("self.{}", field_name)));
                field_obj.insert("remove_entity".to_string(), Json::String(format!("if let Some(v) = entity.{}() {{ cell.{} -= v; }}",
                                                                                component_name, field_name)));
                field_obj.insert("insert_entity".to_string(), Json::String(format!("if let Some(v) = entity.{}() {{ cell.{} += v; }}",
                                                                                component_name, field_name)));
            }
            "count_bool" => {
                field_obj.insert("struct_field_type".to_string(), Json::String("usize".to_string()));
                field_obj.insert("struct_field_cons".to_string(), Json::String("0".to_string()));
                field_obj.insert("getter_type".to_string(), Json::String("bool".to_string()));
                field_obj.insert("getter_expr".to_string(), Json::String(format!("self.{} != 0", field_name)));
                field_obj.insert("remove_entity".to_string(), Json::String(format!("if entity.contains_{}() {{ cell.{} -= 1; }}",
                                                                                component_name, field_name)));
                field_obj.insert("insert_entity".to_string(), Json::String(format!("if entity.contains_{}() {{ cell.{} += 1; }}",
                                                                                component_name, field_name)));
            }
            "any" => {
                field_obj.insert("struct_field_type".to_string(), Json::String("AnySet<EntityId>".to_string()));
                field_obj.insert("struct_field_cons".to_string(), Json::String("AnySet::new()".to_string()));
                field_obj.insert("getter_type".to_string(), Json::String("bool".to_string()));
                field_obj.insert("getter_expr".to_string(), Json::String(format!("!self.{}.is_empty()", field_name)));
                field_obj.insert("any_name".to_string(), Json::String(format!("any_{}", field_name)));
                field_obj.insert("any_type".to_string(), Json::String("Option<EntityId>".to_string()));
                field_obj.insert("any_expr".to_string(), Json::String(format!("self.{}.any()", field_name)));
                field_obj.insert("remove_entity".to_string(), Json::String(format!("if entity.contains_{}() {{ cell.{}.remove(entity.id()); }}",
                                                                                component_name, field_name)));
                field_obj.insert("insert_entity".to_string(), Json::String(format!("if entity.contains_{}() {{ cell.{}.insert(entity.id()); }}",
                                                                                component_name, field_name)));
                field_obj.insert("is_set_type".to_string(), Json::Boolean(true));
            }
            "set" => {
                field_obj.insert("struct_field_type".to_string(), Json::String("EntitySet".to_string()));
                field_obj.insert("struct_field_cons".to_string(), Json::String("EntitySet::new()".to_string()));
                field_obj.insert("getter_type".to_string(), Json::String("bool".to_string()));
                field_obj.insert("getter_expr".to_string(), Json::String(format!("!self.{}.is_empty()", field_name)));
                field_obj.insert("iter_name".to_string(), Json::String(format!("{}_iter", field_name)));
                field_obj.insert("iter_type".to_string(), Json::String("EntitySetIter".to_string()));
                field_obj.insert("iter_expr".to_string(), Json::String(format!("self.{}.iter()", field_name)));
                field_obj.insert("remove_entity".to_string(), Json::String(format!("if entity.contains_{}() {{ cell.{}.remove(entity.id()); }}",
                                                                                component_name, field_name)));
                field_obj.insert("insert_entity".to_string(), Json::String(format!("if entity.contains_{}() {{ cell.{}.insert(entity.id()); }}",
                                                                                component_name, field_name)));
                field_obj.insert("is_set_type".to_string(), Json::Boolean(true));
            }
            other => panic!("unknown field type {}", other),
        }
    }

    let mut handlebars = Handlebars::new();

    // prevent xml escaping
    handlebars.register_escape_fn(|input| input.to_string());
    handlebars.template_render(TEMPLATE, &json).unwrap()

}

fn read_file_to_string<P: AsRef<Path>>(path: P) -> String {
    let mut file = File::open(path).unwrap();
    let mut string = String::new();
    file.read_to_string(&mut string).unwrap();

    string
}

pub fn generate_spatial_hash<P: AsRef<Path>, Q: AsRef<Path>>(in_path: P, out_path: Q) {
    let string = read_file_to_string(in_path);

    let output_string = generate_code(string);

    let mut outfile = File::create(out_path).unwrap();
    write!(outfile, "{}", output_string).unwrap();
}

const TEMPLATE: &'static str = r#"// Automatically generated. Do not edit.
#![allow(unused_imports)]
use ecs::*;
use coord::Coord;
use grid::{Grid, StaticGrid, DefaultGrid, IterGrid, CoordIterGrid};
use util::AnySet;

pub type SpatialHashCellIter<'a> = <StaticGrid<SpatialHashCell> as IterGrid<'a>>::Iter;
pub type SpatialHashCoordIter = <StaticGrid<SpatialHashCell> as CoordIterGrid>::CoordIter;

pub struct SpatialHashCell {

{{#each field}}
    {{ struct_field_name }}: {{ struct_field_type }},
{{/each}}

    // set of entities currently in this cell
    entities: EntitySet,

    // action on which this cell was last updated
    last_updated: u64,
}

impl SpatialHashCell {
    pub fn new() -> Self {
        SpatialHashCell {
{{#each field}}
            {{ struct_field_name }}: {{ struct_field_cons }},
{{/each}}

            entities: EntitySet::new(),
            last_updated: 0,
        }
    }

    pub fn last_updated(&self) -> u64 {
        self.last_updated
    }

    pub fn entity_ids(&self) -> &EntitySet {
        &self.entities
    }

    pub fn entity_id_iter(&self) -> EntitySetIter {
        self.entities.iter()
    }

{{#each field}}
    pub fn {{ getter_name }}(&self) -> {{ getter_type }} {
        {{ getter_expr }}
    }
    {{#if iter_name}}
    pub fn {{ iter_name }}(&self) -> {{ iter_type }} {
        {{ iter_expr }}
    }
    {{/if}}
    {{#if any_name}}
    pub fn {{ any_name }}(&self) -> {{ any_type }} {
        {{ any_expr }}
    }
    {{/if}}
{{/each}}
}

impl Default for SpatialHashCell {
    fn default() -> Self {
        Self::new()
    }
}

pub struct SpatialHashTable {
    grid: StaticGrid<SpatialHashCell>,
    empty: SpatialHashCell,
}

impl SpatialHashTable {
    pub fn new(width: usize, height: usize) -> Self {
        SpatialHashTable {
            grid: StaticGrid::new_default(width, height),
            empty: SpatialHashCell::new(),
        }
    }

    pub fn cell_iter(&self) -> SpatialHashCellIter {
        self.grid.iter()
    }

    pub fn coord_iter(&self) -> SpatialHashCoordIter {
        self.grid.coord_iter()
    }

    pub fn get(&self, coord: Coord) -> &SpatialHashCell {
        self.grid.get(coord).unwrap_or(&self.empty)
    }

    pub fn limits_min(&self) -> Coord {
        self.grid.limits_min()
    }

    pub fn limits_max(&self) -> Coord {
        self.grid.limits_max()
    }

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

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

    fn get_mut(&mut self, coord: Coord) -> &mut SpatialHashCell {
        unsafe { self.grid.get_unchecked_mut(coord) }
    }

    fn change_entity_position(&mut self, entity: EntityRef, current_position: Coord, new_position: Coord, action_id: u64) {
        self.remove_entity_position(entity, current_position, action_id);
        self.add_entity_position(entity, new_position, action_id);
    }

    fn remove_entity_position(&mut self, entity: EntityRef, position: Coord, action_id: u64) {
        let mut cell = self.get_mut(position);

{{#each field}}
        {{ remove_entity }}
{{/each}}

        cell.entities.remove(entity.id());
        cell.last_updated = action_id;
    }

    fn add_entity_position(&mut self, entity: EntityRef, position: Coord, action_id: u64) {
        let mut cell = self.get_mut(position);

{{#each field}}
        {{ insert_entity }}
{{/each}}

        cell.entities.insert(entity.id());
        cell.last_updated = action_id;
    }

    pub fn update(&mut self, ecs: &EcsCtx, action: &EcsAction, action_id: u64) {

        for (entity_id, new_position) in action.position_positive_iter(ecs) {
            let entity = ecs.entity(entity_id);
            // Add and remove tracked components based on the current data stored about the
            // entity, ignoring any component changes in the current action. These will be
            // applied later.
            if let Some(current_position) = entity.position() {
                // the entity is changing position
                self.change_entity_position(entity, current_position, *new_position, action_id);
            } else {
                // the entity is gaining a position
                self.add_entity_position(entity, *new_position, action_id);
            }
        }

        for entity_id in action.position_negative_iter(ecs) {
            let entity = ecs.entity(entity_id);
            if let Some(position) = entity.position() {
                self.remove_entity_position(entity, position, action_id);
            }
        }

{{#each field}}
        self.update_{{ struct_field_name }}(ecs, action, action_id);
{{/each}}
    }

{{#each field}}
    fn update_{{ struct_field_name }}(&mut self, ecs: &EcsCtx, action: &EcsAction, action_id: u64) {
    {{#if count_bool}}
        for entity_id in action.{{ component_name }}_positive_iter(ecs) {
            let entity = ecs.post_action_entity(entity_id, action);
            if let Some(position) = entity.position() {
                if !entity.current_contains_{{ component_name }}() {
                    let cell = self.get_mut(position);
                    cell.{{ struct_field_name }} += 1;
                    cell.last_updated = action_id;
                }
            }
        }

        for entity_id in action.{{ component_name }}_negative_iter(ecs) {
            let entity = ecs.post_action_entity(entity_id, action);
            if let Some(position) = entity.position() {
                if entity.current_contains_{{ component_name }}() {
                    let cell = self.get_mut(position);
                    cell.{{ struct_field_name }} -= 1;
                    cell.last_updated = action_id;
                }
            }
        }
    {{/if}}
    {{#if sum_f64}}
        for (entity_id, new) in action.{{ component_name }}_positive_iter(ecs) {
            let entity = ecs.post_action_entity(entity_id, action);
            if let Some(position) = entity.position() {
                let current = entity.current_{{ component_name }}().unwrap_or(0.0);
                let increase = new - current;
                let cell = self.get_mut(position);
                cell.{{ struct_field_name }} += increase;
                cell.last_updated = action_id;
            }
        }
        for entity_id in action.{{ component_name }}_negative_iter(ecs) {
            let entity = ecs.post_action_entity(entity_id, action);
            if let Some(position) = entity.position() {
                if let Some(value) = entity.current_{{ component_name }}() {
                    let cell = self.get_mut(position);
                    cell.{{ struct_field_name }} -= value;
                    cell.last_updated = action_id;
                }
            }
        }
    {{/if}}
    {{#if is_set_type}}
        {{#if component_has_type}}
        for (entity_id, _) in action.{{ component_name }}_positive_iter(ecs) {
        {{else}}
        for entity_id in action.{{ component_name }}_positive_iter(ecs) {
        {{/if}}
            let entity = ecs.post_action_entity(entity_id, action);
            if let Some(position) = entity.position() {
        {{#if component_has_type}}
                if entity.current_{{ component_name }}().is_none() {
        {{else}}
                if !entity.current_contains_{{ component_name }}() {
        {{/if}}
                    let cell = self.get_mut(position);
                    cell.{{ struct_field_name }}.insert(entity_id);
                    cell.last_updated = action_id;
                }
            }
        }
        for entity_id in action.{{ component_name }}_negative_iter(ecs) {
            let entity = ecs.post_action_entity(entity_id, action);
            if let Some(position) = entity.position() {
        {{#if component_has_type}}
                if entity.current_{{ component_name }}().is_some() {
        {{else}}
                if entity.current_contains_{{ component_name }}() {
        {{/if}}
                    let cell = self.get_mut(position);
                    cell.{{ struct_field_name }}.remove(entity_id);
                    cell.last_updated = action_id;
                }
            }
        }
    {{/if}}
    }
{{/each}}
}
"#;

<|endoftext|>


<commit_before>use ffi;
use std::os::raw::c_int;
use std::ptr;
use types::*;
use ffi::MaybeError;
use device::DeviceInfo;

/// Represents the input port of a PortMidi device.
pub struct InputPort {
    stream: *const ffi::PortMidiStream,
    device: ffi::PmDeviceId,
    buffer_size: usize,
}
impl InputPort {
    /// Construct a new `InputPort` for the given device and buffer size.
    ///
    /// If the `device` is not an input device an `Error::NotAnInputDevice` is returned.
    pub fn new(device: DeviceInfo, buffer_size: usize) -> Result<InputPort> {
        if device.is_output() {
            return Err(Error::NotAnInputDevice);
        }
        let raw_stream: *const ffi::PortMidiStream = ptr::null();
        try!(Result::from(unsafe {
            ffi::Pm_OpenInput(&raw_stream as *const *const _,
                              device.id(),
                              ptr::null(), // *inputDriverInfo, not needed for normal operation
                              buffer_size as c_int,
                              ptr::null(), // PmTimeProcPtr, a procedure that returns time in ms
                              ptr::null()) // time_info, a pointer passed to the time procedure
        }));

        Ok(InputPort {
            stream: raw_stream,
            device: device.id(),
            buffer_size: buffer_size,
        })
    }

    /// Returns a `Vec<MidiEvent>` with at most `cnt` elements.
    /// If there was no Midi event available, `None` is returned.
    /// If PortMidi fails to read from the device an `Error::PortMidi(_)` is returned.
    pub fn read_n(&self, cnt: usize) -> Result<Option<Vec<MidiEvent>>> {
        let read_cnt = if cnt > self.buffer_size {
            self.buffer_size as c_int
        } else {
            cnt as c_int
        };
        let mut event_buffer = vec![ffi::PmEvent::default(); self.buffer_size];
        let res = unsafe { ffi::Pm_Read(self.stream, event_buffer.as_mut_ptr(), read_cnt) };
        match ffi::PmError::try_from(res) {
            Ok(event_cnt) => {
                let events = (0..event_cnt as usize)
                                 .map(|i| MidiEvent::from(event_buffer[i].clone()))
                                 .collect::<Vec<MidiEvent>>();
                Ok(Some(events))
            }
            err @ Err(ffi::PmError::PmNoError) => Ok(None),
            Err(err) => return Err(Error::PortMidi(err)),
        }
    }

    /// Reads a single `MidiEvent` if one is avaible.
    ///
    /// A `Result` of `None` means no event was available.
    pub fn read(&mut self) -> Result<Option<MidiEvent>> {
        match self.read_n(1) {
            Ok(Some(mut vec)) => Ok(vec.pop()),
            Ok(_) => Ok(None),
            Err(e) => Err(e),
        }
    }

    /// Polls for available Midi events.
    /// Returns `true` if there are events available, otherwise `false` is returned.
    /// If the polling fails an `Error::PortMidi(_)` is returned.
    pub fn poll(&self) -> Result<bool> {
        let pm_error = unsafe { ffi::Pm_Poll(self.stream) };
        match pm_error {
            ffi::PmError::PmNoError => Ok(false),
            ffi::PmError::PmGotData => Ok(true),
            err @ _ => Err(Error::PortMidi(err)),
        }
    }
}
impl Drop for InputPort {
    fn drop(&mut self) {
        if let Err(err) = Result::from(unsafe { ffi::Pm_Close(self.stream) }) {
            println!("{}", err);
        }
    }
}

/// Represents the output port of a PortMidi device.
pub struct OutputPort {
    stream: *const ffi::PortMidiStream,
    device: ffi::PmDeviceId,
    buffer_size: usize,
}
impl OutputPort {
    /// Construct a new `OutputPort` for the given device and buffer size.
    ///
    /// If the `device` is not an output device an `Error::NotAnOutputDevice` is returned.
    pub fn new(device: DeviceInfo, buffer_size: usize) -> Result<OutputPort> {
        if device.is_input() {
            return Err(Error::NotAnOutputDevice);
        }
        let raw_stream: *const ffi::PortMidiStream = ptr::null();
        try!(Result::from(unsafe {
            ffi::Pm_OpenOutput(&raw_stream as *const *const _,
                               device.id(),
                               ptr::null(), // *inputDriverInfo, not needed for normal operation
                               buffer_size as c_int,
                               ptr::null(), // PmTimeProcPtr, a procedure that returns time in ms,
                               ptr::null(), // time_info, a pointer passed to the time procedure
                               0) //latency
        }));

        Ok(OutputPort {
            stream: raw_stream,
            device: device.id(),
            buffer_size: buffer_size,
        })
    }

    /// Write a single `MidiEvent`.
    /// Returns an `Error::PortMidi(_)` if something went wrong.
    pub fn write_event<T: Into<MidiEvent>>(&mut self, midi_event: T) -> Result<()> {
        self.write_events(vec![midi_event])
    }

    /// Write a buffer of midi events to the output port.
    /// Returns an `Error::PortMidi(_)` if something went wrong.
    pub fn write_events<T: Into<MidiEvent>>(&mut self, midi_events: Vec<T>) -> Result<()> {
        let events: Vec<ffi::PmEvent> = midi_events.into_iter()
                                                   .map(|event| event.into().into())
                                                   .collect();
        Result::from(unsafe { ffi::Pm_Write(self.stream, events.as_ptr(), events.len() as c_int) })
    }

    /// Write a single `MidiMessage`.
    /// Returns an `Error::PortMidi(_)` if something went wrong.
    pub fn write_message(&mut self, midi_message: MidiMessage) -> Result<()> {
        Result::from(unsafe { ffi::Pm_WriteShort(self.stream, 0, midi_message.into()) })
    }
}
impl Drop for OutputPort {
    fn drop(&mut self) {
        if let Err(err) = Result::from(unsafe { ffi::Pm_Close(self.stream) }) {
            println!("{}", err);
        }
    }
}
<commit_msg>Remove unused fields/variables<commit_after>use ffi;
use std::os::raw::c_int;
use std::ptr;
use types::*;
use ffi::MaybeError;
use device::DeviceInfo;

/// Represents the input port of a PortMidi device.
pub struct InputPort {
    stream: *const ffi::PortMidiStream,
    buffer_size: usize,
}
impl InputPort {
    /// Construct a new `InputPort` for the given device and buffer size.
    ///
    /// If the `device` is not an input device an `Error::NotAnInputDevice` is returned.
    pub fn new(device: DeviceInfo, buffer_size: usize) -> Result<InputPort> {
        if device.is_output() {
            return Err(Error::NotAnInputDevice);
        }
        let raw_stream: *const ffi::PortMidiStream = ptr::null();
        try!(Result::from(unsafe {
            ffi::Pm_OpenInput(&raw_stream as *const *const _,
                              device.id(),
                              ptr::null(), // *inputDriverInfo, not needed for normal operation
                              buffer_size as c_int,
                              ptr::null(), // PmTimeProcPtr, a procedure that returns time in ms
                              ptr::null()) // time_info, a pointer passed to the time procedure
        }));

        Ok(InputPort {
            stream: raw_stream,
            buffer_size: buffer_size,
        })
    }

    /// Returns a `Vec<MidiEvent>` with at most `cnt` elements.
    /// If there was no Midi event available, `None` is returned.
    /// If PortMidi fails to read from the device an `Error::PortMidi(_)` is returned.
    pub fn read_n(&self, cnt: usize) -> Result<Option<Vec<MidiEvent>>> {
        let read_cnt = if cnt > self.buffer_size {
            self.buffer_size as c_int
        } else {
            cnt as c_int
        };
        let mut event_buffer = vec![ffi::PmEvent::default(); self.buffer_size];
        let res = unsafe { ffi::Pm_Read(self.stream, event_buffer.as_mut_ptr(), read_cnt) };
        match ffi::PmError::try_from(res) {
            Ok(event_cnt) => {
                let events = (0..event_cnt as usize)
                                 .map(|i| MidiEvent::from(event_buffer[i].clone()))
                                 .collect::<Vec<MidiEvent>>();
                Ok(Some(events))
            }
            Err(ffi::PmError::PmNoError) => Ok(None),
            Err(err) => return Err(Error::PortMidi(err)),
        }
    }

    /// Reads a single `MidiEvent` if one is avaible.
    ///
    /// A `Result` of `None` means no event was available.
    pub fn read(&mut self) -> Result<Option<MidiEvent>> {
        match self.read_n(1) {
            Ok(Some(mut vec)) => Ok(vec.pop()),
            Ok(_) => Ok(None),
            Err(e) => Err(e),
        }
    }

    /// Polls for available Midi events.
    /// Returns `true` if there are events available, otherwise `false` is returned.
    /// If the polling fails an `Error::PortMidi(_)` is returned.
    pub fn poll(&self) -> Result<bool> {
        let pm_error = unsafe { ffi::Pm_Poll(self.stream) };
        match pm_error {
            ffi::PmError::PmNoError => Ok(false),
            ffi::PmError::PmGotData => Ok(true),
            err @ _ => Err(Error::PortMidi(err)),
        }
    }
}
impl Drop for InputPort {
    fn drop(&mut self) {
        if let Err(err) = Result::from(unsafe { ffi::Pm_Close(self.stream) }) {
            println!("{}", err);
        }
    }
}

/// Represents the output port of a PortMidi device.
pub struct OutputPort {
    stream: *const ffi::PortMidiStream,
}
impl OutputPort {
    /// Construct a new `OutputPort` for the given device and buffer size.
    ///
    /// If the `device` is not an output device an `Error::NotAnOutputDevice` is returned.
    pub fn new(device: DeviceInfo, buffer_size: usize) -> Result<OutputPort> {
        if device.is_input() {
            return Err(Error::NotAnOutputDevice);
        }
        let raw_stream: *const ffi::PortMidiStream = ptr::null();
        try!(Result::from(unsafe {
            ffi::Pm_OpenOutput(&raw_stream as *const *const _,
                               device.id(),
                               ptr::null(), // *inputDriverInfo, not needed for normal operation
                               buffer_size as c_int,
                               ptr::null(), // PmTimeProcPtr, a procedure that returns time in ms,
                               ptr::null(), // time_info, a pointer passed to the time procedure
                               0) //latency
        }));

        Ok(OutputPort {
            stream: raw_stream,
        })
    }

    /// Write a single `MidiEvent`.
    /// Returns an `Error::PortMidi(_)` if something went wrong.
    pub fn write_event<T: Into<MidiEvent>>(&mut self, midi_event: T) -> Result<()> {
        self.write_events(vec![midi_event])
    }

    /// Write a buffer of midi events to the output port.
    /// Returns an `Error::PortMidi(_)` if something went wrong.
    pub fn write_events<T: Into<MidiEvent>>(&mut self, midi_events: Vec<T>) -> Result<()> {
        let events: Vec<ffi::PmEvent> = midi_events.into_iter()
                                                   .map(|event| event.into().into())
                                                   .collect();
        Result::from(unsafe { ffi::Pm_Write(self.stream, events.as_ptr(), events.len() as c_int) })
    }

    /// Write a single `MidiMessage`.
    /// Returns an `Error::PortMidi(_)` if something went wrong.
    pub fn write_message(&mut self, midi_message: MidiMessage) -> Result<()> {
        Result::from(unsafe { ffi::Pm_WriteShort(self.stream, 0, midi_message.into()) })
    }
}
impl Drop for OutputPort {
    fn drop(&mut self) {
        if let Err(err) = Result::from(unsafe { ffi::Pm_Close(self.stream) }) {
            println!("{}", err);
        }
    }
}
<|endoftext|>


<commit_before>

extern crate waves;

use waves::*;

wave!(SineWave);

use std::f64::consts::PI;
pub const TAU : f64 = PI * 2.0;

struct SineWave();
impl Wave for SineWave {
    type Input = ();
    type Output = f32;

    fn new() -> Self { // .... and a param definition
        SineWave {}
    }

    fn process(time:TimeSpan) -> Vec<f32> {
        let freq = 440.0;
        time.time_iter().map(|t| {
            (t * freq * TAU).sin() as f32
        }).collect()
    }
}
<commit_msg>Cleaned up sine<commit_after>extern crate waves;

use waves::*;

wave!(SineWave);

pub const TAU : f64 = std::f64::consts::PI * 2.0;

struct SineWave();
impl Wave for SineWave {
    type Input = ();
    type Output = f32;

    fn new() -> Self { // .... and a param definition
        SineWave {}
    }

    fn process(time:TimeSpan) -> Vec<f32> {
        let freq = 440.0;
        time.time_iter().map(|t| {
            (t * freq * TAU).sin() as f32
        }).collect()
    }
}
<|endoftext|>