<commit_before>//! An element-tree style XML library

extern crate xml;

use std::collections::HashMap;
use std::io::Read;
use std::iter::Filter;
use std::slice::{Iter, IterMut};

use xml::reader::{EventReader, XmlEvent, Error};

/// An XML element
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Element {
    pub prefix: Option<String>,
    pub name: String,
    pub attributes: HashMap<String, String>,
    pub children: Vec<Element>,
    pub contents: Option<String>,
}

/// An XML document
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Document {
    pub version: XmlVersion,
    pub encoding: String,
    pub root: Option<Element>,
}

/// Enumeration of XML versions
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum XmlVersion {
    Version10,
    Version11,
}

impl Default for Element {
    fn default() -> Self {
        Element{
            prefix: None,
            name: "tag".to_owned(),
            attributes: HashMap::new(),
            children: Vec::new(),
            contents: None,
        }
    }
}

impl Element {

    /// Create a new element with the tag name `name`
    pub fn new<S>(name: S) -> Element where S: Into<String> {
        Element{name: name.into(), .. Element::default()}
    }

    /// Find a single child of the current element, given a predicate
    pub fn find_child<P>(&self, predicate: P) -> Option<&Element>
        where P: for<'r> Fn(&'r &Element) -> bool
    {
        self.children.iter().find(predicate)
    }

    /// Find a single child of the current element, given a predicate; returns a mutable borrow
    pub fn find_child_mut<P>(&mut self, predicate: P) -> Option<&mut Element>
        where P: for<'r> FnMut(&'r &mut Element) -> bool
    {
        self.children.iter_mut().find(predicate)
    }

    /// Filters the children of the current element, given a predicate
    pub fn filter_children<P>(&self, predicate: P) -> Filter<Iter<Element>, P>
        where P: for<'r> Fn(&'r &Element) -> bool
    {
        self.children.iter().filter(predicate)
    }

    /// Filters the children of the current element, given a predicate; returns a mutable iterator
    pub fn filter_children_mut<P>(&mut self, predicate: P) -> Filter<IterMut<Element>, P>
        where P: for<'r> FnMut(&'r &mut Element) -> bool
    {
        self.children.iter_mut().filter(predicate)
    }

}

impl Default for Document {
    fn default() -> Self {
        Document{
            version: XmlVersion::Version10,
            encoding: "UTF-8".to_owned(),
            root: None,
        }
    }
}

impl Document {

    /// Create a new `Document` with default values
    pub fn new() -> Document {
        Document{.. Document::default()}
    }

    /// Parse data from a reader to construct an XML document
    ///
    /// # Errors
    ///
    /// Passes any errors that the `xml-rs` library returns up the stack
    pub fn parse<R: Read>(r: R) -> Result<Document, Error> {

        let mut reader = EventReader::new(r);
        let mut doc = Document::new();

        loop {
            let ev = try!(reader.next());
            match ev {
                XmlEvent::StartDocument{version, encoding, ..} => {

                    // xml-rs's XmlVersion doesn't derive Debug *sadface*
                    doc.version = match version {
                        xml::common::XmlVersion::Version10 => XmlVersion::Version10,
                        xml::common::XmlVersion::Version11 => XmlVersion::Version11,
                    };
                    doc.encoding = encoding;

                },
                XmlEvent::StartElement{name, attributes, ..} => {

                    // Start of the root element

                    let mut attr_map = HashMap::new();
                    for attr in attributes {
                        let attr_name = match attr.name.prefix {
                            Some(prefix) => format!("{}:{}", prefix, attr.name.local_name),
                            None => attr.name.local_name,
                        };
                        attr_map.insert(attr_name, attr.value);
                    }

                    let root = Element{
                        prefix: name.prefix,
                        name: name.local_name,
                        attributes: attr_map,
                        children: Vec::new(),
                        contents: None,
                    };
                    doc.root = Some(try!(Document::parse_children(&mut reader, root)));

                },
                XmlEvent::EndDocument => break,
                _ => {},
            }
        }

        Ok(doc)

    }

    /// Internal recursive function to parse children of `element`
    fn parse_children<R: Read>(mut reader: &mut EventReader<R>, element: Element) -> Result<Element, Error> {

        let mut me = element.clone();

        loop {
            let ev = try!(reader.next());
            match ev {
                XmlEvent::StartElement{name, attributes, ..} => {

                    let mut attr_map = HashMap::new();
                    for attr in attributes {
                        let attr_name = match attr.name.prefix {
                            Some(prefix) => format!("{}:{}", prefix, attr.name.local_name),
                            None => attr.name.local_name,
                        };
                        attr_map.insert(attr_name, attr.value);
                    }

                    let child = Element{
                        prefix: name.prefix,
                        name: name.local_name,
                        attributes: attr_map,
                        children: Vec::new(),
                        contents: None
                    };
                    me.children.push(try!(Document::parse_children(&mut reader, child)));

                },
                XmlEvent::EndElement{name} => {

                    if name.prefix == me.prefix && name.local_name == me.name {
                        return Ok(me);
                    } else {
                        // This should never happen, since the base xml library will panic first
                        panic!("Unexpected closing tag: {}, expected {}", name, element.name);
                    }

                },
                XmlEvent::Characters(s) => {

                    let contents = match me.contents {
                        Some(v) => v,
                        None => String::new(),
                    };
                    me.contents = Some(contents + &s)

                },
                XmlEvent::CData(s) => {

                    let contents = match me.contents {
                        Some(v) => v,
                        None => String::new(),
                    };
                    me.contents = Some(contents + "<![CDATA[" + &s + "]]>");

                },
                XmlEvent::Whitespace(_) => {},
                XmlEvent::Comment(_) => {},
                _ => {},
            }
        }
    }

}
<commit_msg>improve documentation, add module-level example<commit_after>//! An element-tree style XML library
//!
//! # Examples
//!
//! ```
//! use treexml::Document;
//!
//! let doc_raw = r#"
//! <?xml version="1.1" encoding="UTF-8"?>
//! <table>
//!     <fruit type="apple">worm</fruit>
//!     <vegetable />
//! </table>
//! "#;
//!
//! let doc = Document::parse(doc_raw.as_bytes()).unwrap();
//! let root = doc.root.unwrap();
//!
//! let fruit = root.find_child(|tag| tag.name == "fruit").unwrap().clone();
//! println!("{}", fruit.contents.unwrap());
//! ```

extern crate xml;

use std::collections::HashMap;
use std::io::Read;
use std::iter::Filter;
use std::slice::{Iter, IterMut};

use xml::reader::{EventReader, XmlEvent, Error};

/// An XML element
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Element {
    pub prefix: Option<String>,
    pub name: String,
    pub attributes: HashMap<String, String>,
    pub children: Vec<Element>,
    pub contents: Option<String>,
}

/// An XML document
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Document {
    pub version: XmlVersion,
    pub encoding: String,
    pub root: Option<Element>,
}

/// Enumeration of XML versions
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum XmlVersion {
    /// XML Version 1.0
    Version10,
    /// XML Version 1.1
    Version11,
}

impl Default for Element {
    fn default() -> Self {
        Element{
            prefix: None,
            name: "tag".to_owned(),
            attributes: HashMap::new(),
            children: Vec::new(),
            contents: None,
        }
    }
}

impl Element {

    /// Create a new `Element` with the tag name `name`
    pub fn new<S>(name: S) -> Element where S: Into<String> {
        Element{name: name.into(), .. Element::default()}
    }

    /// Find a single child of the current `Element`, given a predicate
    pub fn find_child<P>(&self, predicate: P) -> Option<&Element>
        where P: for<'r> Fn(&'r &Element) -> bool
    {
        self.children.iter().find(predicate)
    }

    /// Find a single child of the current `Element`, given a predicate; returns a mutable borrow
    pub fn find_child_mut<P>(&mut self, predicate: P) -> Option<&mut Element>
        where P: for<'r> FnMut(&'r &mut Element) -> bool
    {
        self.children.iter_mut().find(predicate)
    }

    /// Filters the children of the current `Element`, given a predicate
    pub fn filter_children<P>(&self, predicate: P) -> Filter<Iter<Element>, P>
        where P: for<'r> Fn(&'r &Element) -> bool
    {
        self.children.iter().filter(predicate)
    }

    /// Filters the children of the current `Element`, given a predicate; returns a mutable iterator
    pub fn filter_children_mut<P>(&mut self, predicate: P) -> Filter<IterMut<Element>, P>
        where P: for<'r> FnMut(&'r &mut Element) -> bool
    {
        self.children.iter_mut().filter(predicate)
    }

}

impl Default for Document {
    fn default() -> Self {
        Document{
            version: XmlVersion::Version10,
            encoding: "UTF-8".to_owned(),
            root: None,
        }
    }
}

impl Document {

    /// Create a new `Document` with default values
    pub fn new() -> Document {
        Document{.. Document::default()}
    }

    /// Parse data from a reader to construct an XML document
    ///
    /// # Failures
    ///
    /// Passes any errors that the `xml-rs` library returns up the stack
    pub fn parse<R: Read>(r: R) -> Result<Document, Error> {

        let mut reader = EventReader::new(r);
        let mut doc = Document::new();

        loop {
            let ev = try!(reader.next());
            match ev {
                XmlEvent::StartDocument{version, encoding, ..} => {

                    // xml-rs's XmlVersion doesn't derive Debug *sadface*
                    doc.version = match version {
                        xml::common::XmlVersion::Version10 => XmlVersion::Version10,
                        xml::common::XmlVersion::Version11 => XmlVersion::Version11,
                    };
                    doc.encoding = encoding;

                },
                XmlEvent::StartElement{name, attributes, ..} => {

                    // Start of the root element

                    let mut attr_map = HashMap::new();
                    for attr in attributes {
                        let attr_name = match attr.name.prefix {
                            Some(prefix) => format!("{}:{}", prefix, attr.name.local_name),
                            None => attr.name.local_name,
                        };
                        attr_map.insert(attr_name, attr.value);
                    }

                    let root = Element{
                        prefix: name.prefix,
                        name: name.local_name,
                        attributes: attr_map,
                        children: Vec::new(),
                        contents: None,
                    };
                    doc.root = Some(try!(Document::parse_children(&mut reader, root)));

                },
                XmlEvent::EndDocument => break,
                _ => {},
            }
        }

        Ok(doc)

    }

    /// Internal recursive function to parse children of `element`
    fn parse_children<R: Read>(mut reader: &mut EventReader<R>, element: Element) -> Result<Element, Error> {

        let mut me = element.clone();

        loop {
            let ev = try!(reader.next());
            match ev {
                XmlEvent::StartElement{name, attributes, ..} => {

                    let mut attr_map = HashMap::new();
                    for attr in attributes {
                        let attr_name = match attr.name.prefix {
                            Some(prefix) => format!("{}:{}", prefix, attr.name.local_name),
                            None => attr.name.local_name,
                        };
                        attr_map.insert(attr_name, attr.value);
                    }

                    let child = Element{
                        prefix: name.prefix,
                        name: name.local_name,
                        attributes: attr_map,
                        children: Vec::new(),
                        contents: None
                    };
                    me.children.push(try!(Document::parse_children(&mut reader, child)));

                },
                XmlEvent::EndElement{name} => {

                    if name.prefix == me.prefix && name.local_name == me.name {
                        return Ok(me);
                    } else {
                        // This should never happen, since the base xml library will panic first
                        panic!("Unexpected closing tag: {}, expected {}", name, element.name);
                    }

                },
                XmlEvent::Characters(s) => {

                    let contents = match me.contents {
                        Some(v) => v,
                        None => String::new(),
                    };
                    me.contents = Some(contents + &s)

                },
                XmlEvent::CData(s) => {

                    let contents = match me.contents {
                        Some(v) => v,
                        None => String::new(),
                    };
                    me.contents = Some(contents + "<![CDATA[" + &s + "]]>");

                },
                XmlEvent::Whitespace(_) => {},
                XmlEvent::Comment(_) => {},
                _ => {},
            }
        }
    }

}
<|endoftext|>


<commit_before>#![license = "MIT"]
#![feature(plugin_registrar)]
#![deny(warnings)]
#![deny(missing_doc)]

//! Stainless is a lightweight, unopinionated testing framework for Rust.

extern crate syntax;
extern crate rustc;

use self::describe::describe;
use rustc::plugin;

mod describe;

#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(reg: &mut plugin::Registry) {
    reg.register_macro("describe", describe);
}

<commit_msg>(doc) Added crate comment for stainless.<commit_after>#![license = "MIT"]
#![feature(plugin_registrar)]
#![deny(warnings)]
#![deny(missing_doc)]

//! Stainless is a lightweight, flexible, unopinionated testing framework.
//!
//! ## Example
//!
//! ```ignore
//! describe!("stainless" {
//!     before_each {
//!         // Start up a test.
//!         let mut stainless = true;
//!     }
//!
//!     it "makes organizing tests easy" {
//!         // Do the test.
//!         assert!(stainless);
//!     }
//!
//!     after_each {
//!         // End the test.
//!         stainless = false;
//!     }
//!
//!     describe!("nesting" {
//!         it "makes it simple to categorize tests" {
//!             // It even generates submodules!
//!             assert_eq!(2u, 2u);
//!         }
//!     })
//! })
//! ```
//!
//! Expands to (roughly):
//!
//! ```rust
//! mod stainless {
//!     #[test]
//!     fn makes_organizing_tests_easy() {
//!         let mut stainless = true;
//!         assert!(stainless);
//!         stainless = false;
//!     }
//!
//!     mod nesting {
//!         #[test]
//!         fn makes_it_simple_to_categorize_tests() {
//!             assert_eq!(2u, 2u);
//!         }
//!     }
//! }
//! ```
//!
//! Stainless exports the `describe!` syntax extension, which allows
//! you to quickly generate complex testing hierarchies and reduce
//! boilerplate through `before_each` and `after_each`.
//!
//! Stainless currently supports 3 types of subblocks:
//!  - `before_each` and `after_each`,
//!  - `it`
//!  - nested `describe!`
//!
//! `before_each` and `after_each` allow you to group common initialization
//! and teardown for a group of tests into a single block, shortening your
//! tests.
//!
//! `it` generates tests which use `before_each` and `after_each`.
//!
//! Nested `describe!` blocks allow you to better organize your tests into
//! small units and gives you granular control over where `before_each` and
//! `after_each` apply.
//!
//! Together, these 3 types of subblocks give you more flexibility and control
//! than the built in testing infrastructure.
//!

extern crate syntax;
extern crate rustc;

use self::describe::describe;
use rustc::plugin;

mod describe;

#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(reg: &mut plugin::Registry) {
    reg.register_macro("describe", describe);
}

<|endoftext|>


<commit_before>/// The focus on this file is to describe the data-structures
/// for IA-32e paging mode.
use core::fmt;

pub type PAddr = u64;
pub type VAddr = u64;

pub const BASE_PAGE_SIZE: u64 = 4096;

bitflags! {
    flags PML4Entry: u64 {
        /// Read/write; if 0, writes may not be allowed to the 512-GByte region
        /// controlled by this entry (see Section 4.6)
        const PML4_RW      = 0b00000010,
        /// User/supervisor; if 0, user-mode accesses are not allowed
        /// to the 512-GByte region controlled by this entry.
        const PML4_US      = 0b00000100,
        /// Page-level write-through; indirectly determines the memory type used to
        /// access the page-directory-pointer table referenced by this entry.
        const PML4_PWT     = 0b00001000,
        /// Page-level cache disable; indirectly determines the memory type used to
        /// access the page-directory-pointer table referenced by this entry.
        const PML4_PCD     = 0b00010000,
        /// Accessed; indicates whether this entry has been used for linear-address translation.
        const PML4_A       = 0b00100000,
        /// If IA32_EFER.NXE = 1, execute-disable
        /// If 1, instruction fetches are not allowed from the 512-GByte region.
        const PML4_XD      = 1 << 63,
    }
}

impl PML4Entry {
    pub fn new(&mut self, pdpt: PAddr) {
        assert!(pdpt % BASE_PAGE_SIZE == 0);
        self.bits = pdpt;
    }
}

impl fmt::Debug for PML4Entry {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.bits)
    }
}

bitflags! {
    flags PDPTEntry: u64 {
        /// Present; must be 1 to map a 1-GByte page or reference a page directory.
        const PDPT_P       = 0b00000001,
        /// Read/write; if 0, writes may not be allowed to the 1-GByte region controlled by this entry
        const PDPT_RW      = 0b00000010,
        /// User/supervisor; user-mode accesses are not allowed to the 1-GByte region controlled by this entry.
        const PDPT_US      = 0b00000100,
        /// Page-level write-through.
        const PDPT_PWT     = 0b00001000,
        /// Page-level cache disable.
        const PDPT_PCD     = 0b00010000,
        /// Accessed; if PDPT_PS set indicates whether software has accessed the 1-GByte page
        /// else indicates whether this entry has been used for linear-address translation
        const PDPT_A       = 0b00100000,
        /// Dirty; if PDPT_PS indicates whether software has written to the 1-GByte page referenced by this entry.
        /// else ignored.
        const PDPT_D       = 0b01000000,
        /// Page size; if set this entry maps a 1-GByte page; otherwise, this entry references a page directory.
        /// if not PDPT_PS this is ignored.
        const PDPT_PS      = 0b10000000,
        /// Global; if PDPT_PS && CR4.PGE = 1, determines whether the translation is global; ignored otherwise
        /// if not PDPT_PS this is ignored.
        const PDPT_G       = 1<<8,
        /// Indirectly determines the memory type used to access the 1-GByte page referenced by this entry.
        const PDPT_PAT     = 1<<12,
        /// If IA32_EFER.NXE = 1, execute-disable
        /// If 1, instruction fetches are not allowed from the 512-GByte region.
        const PDPT_XD      = 1 << 63,
    }
}

impl PDPTEntry {
    pub fn new(&mut self) {
        self.bits = 0;
    }
}

impl fmt::Debug for PDPTEntry {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.bits)
    }
}

bitflags! {
    flags PDEntry: u64 {
        /// Present; must be 1 to map a 2-MByte page or reference a page table.
        const PD_P       = 0b00000001,
        /// Read/write; if 0, writes may not be allowed to the 2-MByte region controlled by this entry
        const PD_RW      = 0b00000010,
        /// User/supervisor; user-mode accesses are not allowed to the 2-MByte region controlled by this entry.
        const PD_US      = 0b00000100,
        /// Page-level write-through.
        const PD_PWT     = 0b00001000,
        /// Page-level cache disable.
        const PD_PCD     = 0b00010000,
        /// Accessed; if PD_PS set indicates whether software has accessed the 2-MByte page
        /// else indicates whether this entry has been used for linear-address translation
        const PD_A       = 0b00100000,
        /// Dirty; if PD_PS indicates whether software has written to the 2-MByte page referenced by this entry.
        /// else ignored.
        const PD_D       = 0b01000000,
        /// Page size; if set this entry maps a 2-MByte page; otherwise, this entry references a page directory.
        const PD_PS      = 0b10000000,
        /// Global; if PD_PS && CR4.PGE = 1, determines whether the translation is global; ignored otherwise
        /// if not PD_PS this is ignored.
        const PD_G       = 1<<8,
        /// Indirectly determines the memory type used to access the 2-MByte page referenced by this entry.
        /// if not PD_PS this is ignored.
        const PD_PAT     = 1<<12,
        /// If IA32_EFER.NXE = 1, execute-disable
        /// If 1, instruction fetches are not allowed from the 512-GByte region.
        const PD_XD      = 1 << 63,
    }
}

impl PDEntry {
    pub fn new(&mut self) {
        self.bits = 0;
    }
}

impl fmt::Debug for PDEntry {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.bits)
    }
}

bitflags! {
    flags PTEntry: u64 {
        /// Present; must be 1 to map a 4-KByte page.
        const PT_P       = 0b00000001,
        /// Read/write; if 0, writes may not be allowed to the 4-KByte region controlled by this entry
        const PT_RW      = 0b00000010,
        /// User/supervisor; user-mode accesses are not allowed to the 4-KByte region controlled by this entry.
        const PT_US      = 0b00000100,
        /// Page-level write-through.
        const PT_PWT     = 0b00001000,
        /// Page-level cache disable.
        const PT_PCD     = 0b00010000,
        /// Accessed; indicates whether software has accessed the 4-KByte page
        const PT_A       = 0b00100000,
        /// Dirty; indicates whether software has written to the 4-KByte page referenced by this entry.
        const PT_D       = 0b01000000,
        /// Global; if CR4.PGE = 1, determines whether the translation is global (see Section 4.10); ignored otherwise
        const PT_G       = 1<<8,
        /// If IA32_EFER.NXE = 1, execute-disable
        /// If 1, instruction fetches are not allowed from the 512-GByte region.
        const PT_XD      = 1 << 63,
    }
}

impl PTEntry {
    pub fn new(&mut self) {
        self.bits = 0;
    }
}

impl fmt::Debug for PTEntry {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.bits)
    }
}
<commit_msg>Added types for page-tables.<commit_after>/// The focus on this file is to describe the data-structures
/// for IA-32e paging mode.
use core::fmt;
use core::mem::{size_of};

pub type PAddr = u64;
pub type VAddr = usize;

pub const BASE_PAGE_SIZE: u64 = 4096; // 4 KiB
pub const LARGE_PAGE_SIZE: u64 = 1024*1024*2; // 2 MiB
pub const HUGE_PAGE_SIZE: u64 = 1024*1024*1024; // 1 GiB

/// A PML4 table.
/// In practice this has only 4 entries but it still needs to be the size of a 4K page.
pub type PML4  = [PML4Entry; 512];

/// A page directory pointer table.
pub type PDPT  = [PDPTEntry; 512];

/// A page directory.
pub type PD    = [PDEntry; 512];

/// A page table.
pub type PT    = [PTEntry; 512];

bitflags! {
    flags PML4Entry: u64 {
        /// Read/write; if 0, writes may not be allowed to the 512-GByte region
        /// controlled by this entry (see Section 4.6)
        const PML4_RW      = 0b00000010,
        /// User/supervisor; if 0, user-mode accesses are not allowed
        /// to the 512-GByte region controlled by this entry.
        const PML4_US      = 0b00000100,
        /// Page-level write-through; indirectly determines the memory type used to
        /// access the page-directory-pointer table referenced by this entry.
        const PML4_PWT     = 0b00001000,
        /// Page-level cache disable; indirectly determines the memory type used to
        /// access the page-directory-pointer table referenced by this entry.
        const PML4_PCD     = 0b00010000,
        /// Accessed; indicates whether this entry has been used for linear-address translation.
        const PML4_A       = 0b00100000,
        /// If IA32_EFER.NXE = 1, execute-disable
        /// If 1, instruction fetches are not allowed from the 512-GByte region.
        const PML4_XD      = 1 << 63,
    }
}

impl PML4Entry {
    pub fn new(&mut self, pdpt: PAddr) {
        assert!(pdpt % BASE_PAGE_SIZE == 0);
        self.bits = pdpt;
    }
}

impl fmt::Debug for PML4Entry {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.bits)
    }
}

bitflags! {
    flags PDPTEntry: u64 {
        /// Present; must be 1 to map a 1-GByte page or reference a page directory.
        const PDPT_P       = 0b00000001,
        /// Read/write; if 0, writes may not be allowed to the 1-GByte region controlled by this entry
        const PDPT_RW      = 0b00000010,
        /// User/supervisor; user-mode accesses are not allowed to the 1-GByte region controlled by this entry.
        const PDPT_US      = 0b00000100,
        /// Page-level write-through.
        const PDPT_PWT     = 0b00001000,
        /// Page-level cache disable.
        const PDPT_PCD     = 0b00010000,
        /// Accessed; if PDPT_PS set indicates whether software has accessed the 1-GByte page
        /// else indicates whether this entry has been used for linear-address translation
        const PDPT_A       = 0b00100000,
        /// Dirty; if PDPT_PS indicates whether software has written to the 1-GByte page referenced by this entry.
        /// else ignored.
        const PDPT_D       = 0b01000000,
        /// Page size; if set this entry maps a 1-GByte page; otherwise, this entry references a page directory.
        /// if not PDPT_PS this is ignored.
        const PDPT_PS      = 0b10000000,
        /// Global; if PDPT_PS && CR4.PGE = 1, determines whether the translation is global; ignored otherwise
        /// if not PDPT_PS this is ignored.
        const PDPT_G       = 1<<8,
        /// Indirectly determines the memory type used to access the 1-GByte page referenced by this entry.
        const PDPT_PAT     = 1<<12,
        /// If IA32_EFER.NXE = 1, execute-disable
        /// If 1, instruction fetches are not allowed from the 512-GByte region.
        const PDPT_XD      = 1 << 63,
    }
}

impl PDPTEntry {
    pub fn new(&mut self, pd: PAddr) {
        assert!(pd % BASE_PAGE_SIZE == 0);
        self.bits = pd;
    }
}

impl fmt::Debug for PDPTEntry {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.bits)
    }
}

bitflags! {
    flags PDEntry: u64 {
        /// Present; must be 1 to map a 2-MByte page or reference a page table.
        const PD_P       = 0b00000001,
        /// Read/write; if 0, writes may not be allowed to the 2-MByte region controlled by this entry
        const PD_RW      = 0b00000010,
        /// User/supervisor; user-mode accesses are not allowed to the 2-MByte region controlled by this entry.
        const PD_US      = 0b00000100,
        /// Page-level write-through.
        const PD_PWT     = 0b00001000,
        /// Page-level cache disable.
        const PD_PCD     = 0b00010000,
        /// Accessed; if PD_PS set indicates whether software has accessed the 2-MByte page
        /// else indicates whether this entry has been used for linear-address translation
        const PD_A       = 0b00100000,
        /// Dirty; if PD_PS indicates whether software has written to the 2-MByte page referenced by this entry.
        /// else ignored.
        const PD_D       = 0b01000000,
        /// Page size; if set this entry maps a 2-MByte page; otherwise, this entry references a page directory.
        const PD_PS      = 0b10000000,
        /// Global; if PD_PS && CR4.PGE = 1, determines whether the translation is global; ignored otherwise
        /// if not PD_PS this is ignored.
        const PD_G       = 1<<8,
        /// Indirectly determines the memory type used to access the 2-MByte page referenced by this entry.
        /// if not PD_PS this is ignored.
        const PD_PAT     = 1<<12,
        /// If IA32_EFER.NXE = 1, execute-disable
        /// If 1, instruction fetches are not allowed from the 512-GByte region.
        const PD_XD      = 1 << 63,
    }
}

impl PDEntry {
    pub fn new(&mut self, pt: PAddr) {
        assert!(pt % BASE_PAGE_SIZE == 0);
        self.bits = pt;
    }
}

impl fmt::Debug for PDEntry {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.bits)
    }
}

bitflags! {
    flags PTEntry: u64 {
        /// Present; must be 1 to map a 4-KByte page.
        const PT_P       = 0b00000001,
        /// Read/write; if 0, writes may not be allowed to the 4-KByte region controlled by this entry
        const PT_RW      = 0b00000010,
        /// User/supervisor; user-mode accesses are not allowed to the 4-KByte region controlled by this entry.
        const PT_US      = 0b00000100,
        /// Page-level write-through.
        const PT_PWT     = 0b00001000,
        /// Page-level cache disable.
        const PT_PCD     = 0b00010000,
        /// Accessed; indicates whether software has accessed the 4-KByte page
        const PT_A       = 0b00100000,
        /// Dirty; indicates whether software has written to the 4-KByte page referenced by this entry.
        const PT_D       = 0b01000000,
        /// Global; if CR4.PGE = 1, determines whether the translation is global (see Section 4.10); ignored otherwise
        const PT_G       = 1<<8,
        /// If IA32_EFER.NXE = 1, execute-disable
        /// If 1, instruction fetches are not allowed from the 512-GByte region.
        const PT_XD      = 1 << 63,
    }
}

impl PTEntry {
    pub fn new(&mut self, page: PAddr) {
        assert!(page % BASE_PAGE_SIZE == 0);
        self.bits = page;
    }
}

impl fmt::Debug for PTEntry {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.bits)
    }
}
<|endoftext|>


<commit_before>/// Finds the index of the least item in `slice` for which the `predicate` holds.
// Adapted from core::slice::binary_search_by().
pub fn least_satisfying<T, P>(slice: &[T], mut predicate: P) -> usize
    where P: FnMut(&T) -> bool
{
    // TODO: assert if fails and succedds at the ends?
    // TODO: make it return Option<usize>, in case predicate holds nowhere.
    let mut base = 0usize;
    let mut s = slice;

    loop {
        let (head, tail) = s.split_at(s.len() >> 1);
        if tail.is_empty() {
            return base + head.len();
        }
        if predicate(&tail[0]) {
            s = head;
        } else {
            base += head.len() + 1;
            s = &tail[1..];
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_bisect() {
        let s = &[0, 3, 7, 10, 33, 169, 222, 223];
        assert_eq!(0, least_satisfying(s, |&x| x >= 0));
        assert_eq!(5, least_satisfying(s, |&x| x >= 50));
        assert_eq!(1, least_satisfying(s, |&x| x >= 3));
        assert_eq!(2, least_satisfying(s, |&x| x > 3));
    }
}
<commit_msg>Fix typo in comment<commit_after>/// Finds the index of the least item in `slice` for which the `predicate` holds.
// Adapted from core::slice::binary_search_by().
pub fn least_satisfying<T, P>(slice: &[T], mut predicate: P) -> usize
    where P: FnMut(&T) -> bool
{
    // TODO: assert if fails and succeeds at the ends?
    // TODO: make it return Option<usize>, in case predicate holds nowhere.
    let mut base = 0usize;
    let mut s = slice;

    loop {
        let (head, tail) = s.split_at(s.len() >> 1);
        if tail.is_empty() {
            return base + head.len();
        }
        if predicate(&tail[0]) {
            s = head;
        } else {
            base += head.len() + 1;
            s = &tail[1..];
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_bisect() {
        let s = &[0, 3, 7, 10, 33, 169, 222, 223];
        assert_eq!(0, least_satisfying(s, |&x| x >= 0));
        assert_eq!(5, least_satisfying(s, |&x| x >= 50));
        assert_eq!(1, least_satisfying(s, |&x| x >= 3));
        assert_eq!(2, least_satisfying(s, |&x| x > 3));
    }
}
<|endoftext|>


<commit_before>extern crate sfml;
#[macro_use]
extern crate log;
extern crate env_logger;

use sfml::window::{ContextSettings, VideoMode, window_style};
use sfml::window::event;
use sfml::graphics::RenderWindow;
use sfml::system::Clock;

mod engine_config;

fn fake_main() -> i32 {
    // Init'ing the log system is the first thing to try. Without it, nothing else
    // can be done or reported, so unwrap() will be used here and ONLY here.
    env_logger::init().unwrap();
    debug!("env_logger has been initialized successfully.");

    // TODO: Init Lua here.

    // Acquire the engine configuration. Failing this is a fatal error.
    let engine_config = match engine_config::get_engine_config() {
        Ok(config) => config,
        Err(error) => {
            error!("Failed to acquire engine configuration:\n\t{}", error);
            return 1;
        }
    };

    // TODO: Init the game state here.

    // Initialize the game window. If this can't be done, there's really no point in
    // continuing on.
    let mut window = match RenderWindow::new(VideoMode::new_init(engine_config.screen_width,
                                                                 engine_config.screen_height,
                                                                 32),
                                             "Game Title",
                                             window_style::CLOSE,
                                             &ContextSettings::default()) {
        Some(window) => window,
        None => {
            error!("Could not init a RenderWindow. There is likely a problem with your system.");
            return 1;
        }
    };
    // Set the game's maximum framerate.
    window.set_framerate_limit(engine_config.maximum_framerate);

    // Set up a clock to keep track of how long frames take.
    let frame_clock = Clock::new();
    while window.is_open() {
        // events() returns an iterator over all events in the queue.
        for current_event in window.events() {
            if current_event == event::Closed {
                window.close()
            }
        }
    }
    return 0;
}

fn main() {
    // Fake-main technique. This allows the main() function to return an int (i32) status code.
    std::process::exit(fake_main());
}
<commit_msg>Clarify a few things<commit_after>extern crate sfml;
#[macro_use]
extern crate log;
extern crate env_logger;

use sfml::window::{ContextSettings, VideoMode, window_style};
use sfml::window::event;
use sfml::graphics::RenderWindow;
use sfml::system::Clock;

mod engine_config;

fn fake_main() -> i32 {
    // Init'ing the log system is the first thing to try. Without it, nothing else
    // can be done or reported, so unwrap() will be used here and ONLY here.
    env_logger::init().unwrap();
    info!("env_logger has been initialized successfully.");

    // TODO: Init Lua here.

    // Acquire the engine configuration. Failing this is a fatal error.
    let engine_config = match engine_config::get_engine_config() {
        Ok(config) => config,
        Err(error) => {
            error!("Failed to acquire engine configuration:\n\t{}", error);
            return 1;
        }
    };

    // TODO: Init the game state here.

    // Initialize the game window. If this can't be done, there's really no point in
    // continuing on.
    let mut window = match RenderWindow::new(VideoMode::new_init(engine_config.screen_width,
                                                                 engine_config.screen_height,
                                                                 32),
                                             "Game Title",
                                             window_style::CLOSE,
                                             &ContextSettings::default()) {
        Some(window) => window,
        None => {
            error!("Could not init a RenderWindow. There is likely a problem with your system.");
            return 1;
        }
    };
    // Set the game's maximum framerate.
    window.set_framerate_limit(engine_config.maximum_framerate);

    // Set up a clock to keep track of how long frames take.
    let frame_clock = Clock::new();
    while window.is_open() {
        // events() returns an iterator over all events in the queue.
        for current_event in window.events() {
            if current_event == event::Closed {
                window.close();
            }
        }

        // TODO: Change the world's state here.

    }
    return 0;
}

fn main() {
    // Fake-main technique. This allows the main() function to return an int (i32) status code.
    std::process::exit(fake_main());
}
<|endoftext|>


<commit_before>//! Tools to retrieve Internet-time using NTP protocol.

use std::num::Float;
use time::Timespec;
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use std::io;
use error;

const NTP_CLIENT: u8 = 3;
const NTP_HEADER_SIZE: usize = 48; // 12 words
const NTP_TO_UNIX_EPOCH: i64 = 2208988800;

const LEAP_SHIFT: i32 = 6;
const VERSION_SHIFT: i32 = 3;

#[derive(Debug)]
pub struct NTPTimestamp {
    seconds: u32,
    fraction: u32
}

impl NTPTimestamp {
    pub fn as_timespec(&self) -> Timespec {
        Timespec{sec: (self.seconds as i64) - NTP_TO_UNIX_EPOCH,
                 nsec: (((self.fraction as f64) / 2f64.powi(32) ) / 1e-9) as i32}
    }
}

#[derive(Debug)]
pub struct NTPHeader {
    leap: u8,
    version: u8,
    mode: u8,
    stratum: u8,
    poll: u8,
    precision: u8,
    root_delay: u32,
    root_dispersion: u32,
    reference_id: u32,
    reference_timestamp: NTPTimestamp,
    origin_timestamp: NTPTimestamp,
    receive_timestamp: NTPTimestamp,
    pub transmit_timestamp: NTPTimestamp,
}

impl NTPHeader {
    pub fn new() -> NTPHeader {
        NTPHeader {
            leap: 0,
            version: 3,
            mode: NTP_CLIENT,
            stratum: 0,
            poll: 0,
            precision: 0,
            root_delay : 0,
            root_dispersion : 0,
            reference_id : 0,
            reference_timestamp : NTPTimestamp{seconds:0, fraction:0},
            origin_timestamp : NTPTimestamp{seconds:0, fraction:0},
            receive_timestamp : NTPTimestamp{seconds:0, fraction:0},
            transmit_timestamp : NTPTimestamp{seconds:0, fraction:0}
        }
    }

    pub fn encode(&self) -> Result<Vec<u8>, error::Error> {
        let mut vec = Vec::<u8>::new();

        try!(vec.write_u8(self.leap << LEAP_SHIFT | self.version << VERSION_SHIFT | self.mode));
        try!(vec.write_u8(self.stratum));
        try!(vec.write_u8(self.poll));
        try!(vec.write_u8(self.precision));
        try!(vec.write_u32::<BigEndian>(self.root_delay));
        try!(vec.write_u32::<BigEndian>(self.root_dispersion));
        try!(vec.write_u32::<BigEndian>(self.reference_id));
        try!(vec.write_u32::<BigEndian>(self.reference_timestamp.seconds));
        try!(vec.write_u32::<BigEndian>(self.reference_timestamp.fraction));
        try!(vec.write_u32::<BigEndian>(self.origin_timestamp.seconds));
        try!(vec.write_u32::<BigEndian>(self.origin_timestamp.fraction));
        try!(vec.write_u32::<BigEndian>(self.receive_timestamp.seconds));
        try!(vec.write_u32::<BigEndian>(self.receive_timestamp.fraction));
        try!(vec.write_u32::<BigEndian>(self.transmit_timestamp.seconds));
        try!(vec.write_u32::<BigEndian>(self.transmit_timestamp.fraction));
        Ok(vec)
    }

    pub fn decode(size: usize, buf: & [u8]) -> Result<NTPHeader, error::Error> {
        let mut reader = io::Cursor::new(buf);
        let mut header = NTPHeader::new();

        if size < NTP_HEADER_SIZE {
            return Err(error::Error::UnexpectedSize(NTP_HEADER_SIZE, size));
        }

        let leap_version_mode = try!(reader.read_u8());
        header.leap = (leap_version_mode >> LEAP_SHIFT) & 0b11;
        header.version = (leap_version_mode >> VERSION_SHIFT) & 0b111;
        header.mode = leap_version_mode & 0b111;
        header.stratum = try!(reader.read_u8());
        header.poll = try!(reader.read_u8());
        header.precision = try!(reader.read_u8());
        header.root_delay = try!(reader.read_u32::<BigEndian>());
        header.root_dispersion = try!(reader.read_u32::<BigEndian>());
        header.reference_id = try!(reader.read_u32::<BigEndian>());
        header.reference_timestamp.seconds = try!(reader.read_u32::<BigEndian>());
        header.reference_timestamp.fraction = try!(reader.read_u32::<BigEndian>());
        header.origin_timestamp.seconds = try!(reader.read_u32::<BigEndian>());
        header.origin_timestamp.fraction = try!(reader.read_u32::<BigEndian>());
        header.receive_timestamp.seconds = try!(reader.read_u32::<BigEndian>());
        header.receive_timestamp.fraction = try!(reader.read_u32::<BigEndian>());
        header.transmit_timestamp.seconds = try!(reader.read_u32::<BigEndian>());
        header.transmit_timestamp.fraction = try!(reader.read_u32::<BigEndian>());

        Ok(header)
    }
}
<commit_msg>Remove use of unused/depricated interface<commit_after>//! Tools to retrieve Internet-time using NTP protocol.

use time::Timespec;
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use std::io;
use error;

const NTP_CLIENT: u8 = 3;
const NTP_HEADER_SIZE: usize = 48; // 12 words
const NTP_TO_UNIX_EPOCH: i64 = 2208988800;

const LEAP_SHIFT: i32 = 6;
const VERSION_SHIFT: i32 = 3;

#[derive(Debug)]
pub struct NTPTimestamp {
    seconds: u32,
    fraction: u32
}

impl NTPTimestamp {
    pub fn as_timespec(&self) -> Timespec {
        Timespec{sec: (self.seconds as i64) - NTP_TO_UNIX_EPOCH,
                 nsec: (((self.fraction as f64) / 2f64.powi(32) ) / 1e-9) as i32}
    }
}

#[derive(Debug)]
pub struct NTPHeader {
    leap: u8,
    version: u8,
    mode: u8,
    stratum: u8,
    poll: u8,
    precision: u8,
    root_delay: u32,
    root_dispersion: u32,
    reference_id: u32,
    reference_timestamp: NTPTimestamp,
    origin_timestamp: NTPTimestamp,
    receive_timestamp: NTPTimestamp,
    pub transmit_timestamp: NTPTimestamp,
}

impl NTPHeader {
    pub fn new() -> NTPHeader {
        NTPHeader {
            leap: 0,
            version: 3,
            mode: NTP_CLIENT,
            stratum: 0,
            poll: 0,
            precision: 0,
            root_delay : 0,
            root_dispersion : 0,
            reference_id : 0,
            reference_timestamp : NTPTimestamp{seconds:0, fraction:0},
            origin_timestamp : NTPTimestamp{seconds:0, fraction:0},
            receive_timestamp : NTPTimestamp{seconds:0, fraction:0},
            transmit_timestamp : NTPTimestamp{seconds:0, fraction:0}
        }
    }

    pub fn encode(&self) -> Result<Vec<u8>, error::Error> {
        let mut vec = Vec::<u8>::new();

        try!(vec.write_u8(self.leap << LEAP_SHIFT | self.version << VERSION_SHIFT | self.mode));
        try!(vec.write_u8(self.stratum));
        try!(vec.write_u8(self.poll));
        try!(vec.write_u8(self.precision));
        try!(vec.write_u32::<BigEndian>(self.root_delay));
        try!(vec.write_u32::<BigEndian>(self.root_dispersion));
        try!(vec.write_u32::<BigEndian>(self.reference_id));
        try!(vec.write_u32::<BigEndian>(self.reference_timestamp.seconds));
        try!(vec.write_u32::<BigEndian>(self.reference_timestamp.fraction));
        try!(vec.write_u32::<BigEndian>(self.origin_timestamp.seconds));
        try!(vec.write_u32::<BigEndian>(self.origin_timestamp.fraction));
        try!(vec.write_u32::<BigEndian>(self.receive_timestamp.seconds));
        try!(vec.write_u32::<BigEndian>(self.receive_timestamp.fraction));
        try!(vec.write_u32::<BigEndian>(self.transmit_timestamp.seconds));
        try!(vec.write_u32::<BigEndian>(self.transmit_timestamp.fraction));
        Ok(vec)
    }

    pub fn decode(size: usize, buf: & [u8]) -> Result<NTPHeader, error::Error> {
        let mut reader = io::Cursor::new(buf);
        let mut header = NTPHeader::new();

        if size < NTP_HEADER_SIZE {
            return Err(error::Error::UnexpectedSize(NTP_HEADER_SIZE, size));
        }

        let leap_version_mode = try!(reader.read_u8());
        header.leap = (leap_version_mode >> LEAP_SHIFT) & 0b11;
        header.version = (leap_version_mode >> VERSION_SHIFT) & 0b111;
        header.mode = leap_version_mode & 0b111;
        header.stratum = try!(reader.read_u8());
        header.poll = try!(reader.read_u8());
        header.precision = try!(reader.read_u8());
        header.root_delay = try!(reader.read_u32::<BigEndian>());
        header.root_dispersion = try!(reader.read_u32::<BigEndian>());
        header.reference_id = try!(reader.read_u32::<BigEndian>());
        header.reference_timestamp.seconds = try!(reader.read_u32::<BigEndian>());
        header.reference_timestamp.fraction = try!(reader.read_u32::<BigEndian>());
        header.origin_timestamp.seconds = try!(reader.read_u32::<BigEndian>());
        header.origin_timestamp.fraction = try!(reader.read_u32::<BigEndian>());
        header.receive_timestamp.seconds = try!(reader.read_u32::<BigEndian>());
        header.receive_timestamp.fraction = try!(reader.read_u32::<BigEndian>());
        header.transmit_timestamp.seconds = try!(reader.read_u32::<BigEndian>());
        header.transmit_timestamp.fraction = try!(reader.read_u32::<BigEndian>());

        Ok(header)
    }
}
<|endoftext|>


<commit_before>use json;
use std::ops;

use {Document};

pub use json::buffer::Target;

/// A buffer points to binary data representing geometry, animations, or skins.
#[derive(Clone, Debug)]
pub struct Buffer<'a> {
    /// The parent `Document` struct.
    document: &'a Document,

    /// The corresponding JSON index.
    index: usize,

    /// The corresponding JSON struct.
    json: &'a json::buffer::Buffer,
}

/// A view into a buffer generally representing a subset of the buffer.
#[derive(Clone, Debug)]
pub struct View<'a> {
    /// The parent `Document` struct.
    document: &'a Document,

    /// The corresponding JSON index.
    index: usize,

    /// The corresponding JSON struct.
    json: &'a json::buffer::View,

    /// The parent `Buffer`.
    parent: Buffer<'a>,
}

/// Describes a buffer data source.
#[derive(Clone, Debug)]
pub enum Source<'a> {
    /// Buffer data is contained in the `BIN` section of binary glTF.
    Bin,

    /// Buffer data is contained in an external data source.
    Uri(&'a str),
}

/// Buffer data belonging to an imported glTF asset.
#[cfg(feature = "import")]
#[derive(Clone, Debug)]
pub struct Data(pub Vec<u8>);

impl ops::Deref for Data {
    type Target = [u8];
    fn deref(&self) -> &Self::Target {
        self.0.as_slice()
    }
}

impl<'a> Buffer<'a> {
    /// Constructs a `Buffer`.
    pub(crate) fn new(
        document: &'a Document,
        index: usize,
        json: &'a json::buffer::Buffer,
    ) -> Self {
        Self {
            document: document,
            index: index,
            json: json,
        }
    }

    /// Returns the internal JSON index.
    pub fn index(&self) -> usize {
        self.index
    }

    /// Returns the buffer data source.
    pub fn source(&self) -> Source<'a> {
        if let Some(uri) = self.json.uri.as_ref().map(String::as_str) {
            Source::Uri(uri)
        } else {
            Source::Bin
        }
    }

    /// The length of the buffer in bytes.
    pub fn length(&self) -> usize {
        self.json.byte_length as usize
    }

    /// Optional user-defined name for this object.
    #[cfg(feature = "names")]
    pub fn name(&self) -> Option<&str> {
        self.json.name.as_ref().map(String::as_str)
    }

    /// Optional application specific data.
    pub fn extras(&self) -> &json::Extras {
        &self.json.extras
    }
}

impl<'a> View<'a> {
    /// Constructs a `View`.
    pub(crate) fn new(
        document: &'a Document,
        index: usize,
        json: &'a json::buffer::View,
    ) -> Self {
        let parent = document.buffers().nth(json.buffer.value()).unwrap();
        Self {
            document,
            index,
            json,
            parent,
        }
    }

    /// Returns the internal JSON index.
    pub fn index(&self) -> usize {
        self.index
    }

    /// Returns the parent `Buffer`.
    pub fn buffer(&self) -> Buffer<'a> {
        self.document.buffers().nth(self.json.buffer.value()).unwrap()
    }

    /// Returns the length of the buffer view in bytes.
    pub fn length(&self) -> usize {
        self.json.byte_length as usize
    }

    /// Returns the offset into the parent buffer in bytes.
    pub fn offset(&self) -> usize {
        self.json.byte_offset as usize
    }

    /// Returns the stride in bytes between vertex attributes or other interleavable
    /// data. When `None`, data is assumed to be tightly packed.
    pub fn stride(&self) -> Option<usize> {
        self.json.byte_stride.map(|x| x.0 as usize)
    }

    /// Optional user-defined name for this object.
    #[cfg(feature = "names")]
    pub fn name(&self) -> Option<&str> {
        self.json.name.as_ref().map(String::as_str)
    }

    /// Optional target the buffer should be bound to.
    pub fn target(&self) -> Option<Target> {
        self.json.target.map(|target| target.unwrap())
    }

    /// Optional application specific data.
    pub fn extras(&self) -> &json::Extras {
        &self.json.extras
    }
}
<commit_msg>Fix build error without import feature<commit_after>use json;
use std::ops;

use {Document};

pub use json::buffer::Target;

/// A buffer points to binary data representing geometry, animations, or skins.
#[derive(Clone, Debug)]
pub struct Buffer<'a> {
    /// The parent `Document` struct.
    document: &'a Document,

    /// The corresponding JSON index.
    index: usize,

    /// The corresponding JSON struct.
    json: &'a json::buffer::Buffer,
}

/// A view into a buffer generally representing a subset of the buffer.
#[derive(Clone, Debug)]
pub struct View<'a> {
    /// The parent `Document` struct.
    document: &'a Document,

    /// The corresponding JSON index.
    index: usize,

    /// The corresponding JSON struct.
    json: &'a json::buffer::View,

    /// The parent `Buffer`.
    parent: Buffer<'a>,
}

/// Describes a buffer data source.
#[derive(Clone, Debug)]
pub enum Source<'a> {
    /// Buffer data is contained in the `BIN` section of binary glTF.
    Bin,

    /// Buffer data is contained in an external data source.
    Uri(&'a str),
}

/// Buffer data belonging to an imported glTF asset.
#[cfg(feature = "import")]
#[derive(Clone, Debug)]
pub struct Data(pub Vec<u8>);

#[cfg(feature = "import")]
impl ops::Deref for Data {
    type Target = [u8];
    fn deref(&self) -> &Self::Target {
        self.0.as_slice()
    }
}

impl<'a> Buffer<'a> {
    /// Constructs a `Buffer`.
    pub(crate) fn new(
        document: &'a Document,
        index: usize,
        json: &'a json::buffer::Buffer,
    ) -> Self {
        Self {
            document: document,
            index: index,
            json: json,
        }
    }

    /// Returns the internal JSON index.
    pub fn index(&self) -> usize {
        self.index
    }

    /// Returns the buffer data source.
    pub fn source(&self) -> Source<'a> {
        if let Some(uri) = self.json.uri.as_ref().map(String::as_str) {
            Source::Uri(uri)
        } else {
            Source::Bin
        }
    }

    /// The length of the buffer in bytes.
    pub fn length(&self) -> usize {
        self.json.byte_length as usize
    }

    /// Optional user-defined name for this object.
    #[cfg(feature = "names")]
    pub fn name(&self) -> Option<&str> {
        self.json.name.as_ref().map(String::as_str)
    }

    /// Optional application specific data.
    pub fn extras(&self) -> &json::Extras {
        &self.json.extras
    }
}

impl<'a> View<'a> {
    /// Constructs a `View`.
    pub(crate) fn new(
        document: &'a Document,
        index: usize,
        json: &'a json::buffer::View,
    ) -> Self {
        let parent = document.buffers().nth(json.buffer.value()).unwrap();
        Self {
            document,
            index,
            json,
            parent,
        }
    }

    /// Returns the internal JSON index.
    pub fn index(&self) -> usize {
        self.index
    }

    /// Returns the parent `Buffer`.
    pub fn buffer(&self) -> Buffer<'a> {
        self.document.buffers().nth(self.json.buffer.value()).unwrap()
    }

    /// Returns the length of the buffer view in bytes.
    pub fn length(&self) -> usize {
        self.json.byte_length as usize
    }

    /// Returns the offset into the parent buffer in bytes.
    pub fn offset(&self) -> usize {
        self.json.byte_offset as usize
    }

    /// Returns the stride in bytes between vertex attributes or other interleavable
    /// data. When `None`, data is assumed to be tightly packed.
    pub fn stride(&self) -> Option<usize> {
        self.json.byte_stride.map(|x| x.0 as usize)
    }

    /// Optional user-defined name for this object.
    #[cfg(feature = "names")]
    pub fn name(&self) -> Option<&str> {
        self.json.name.as_ref().map(String::as_str)
    }

    /// Optional target the buffer should be bound to.
    pub fn target(&self) -> Option<Target> {
        self.json.target.map(|target| target.unwrap())
    }

    /// Optional application specific data.
    pub fn extras(&self) -> &json::Extras {
        &self.json.extras
    }
}
<|endoftext|>


<commit_before>//! Buffers to safely work with audio samples.

use num_traits::Float;

use std::slice;
use std::iter::Zip;

/// AudioBuffer contains references to the audio buffers for all input and output channels
pub struct AudioBuffer<'a, T: 'a + Float> {
    inputs: &'a [*const T],
    outputs: &'a mut [*mut T],
    samples: usize,
}

impl<'a, T: 'a + Float> AudioBuffer<'a, T> {

    /// Create an `AudioBuffer` from slices of raw pointers. Useful in a Rust VST host.
    #[inline(always)]
    pub fn new(inputs: &'a [*const T], outputs: &'a mut [*mut T], samples: usize) -> Self {
        Self {
            inputs: inputs,
            outputs: outputs,
            samples: samples,
        }
    }

    /// Create an `AudioBuffer` from raw pointers. Only really useful for interacting with the VST API.
    #[inline(always)]
    pub fn from_raw(input_count: usize, output_count: usize,
                    inputs_raw: *const *const T, outputs_raw: *mut *mut T, samples: usize) -> Self {
        Self {
            inputs: unsafe { slice::from_raw_parts(inputs_raw, input_count) },
            outputs: unsafe { slice::from_raw_parts_mut(outputs_raw, output_count) },
            samples: samples,
        }
    }

    /// The number of input channels that this buffer was created for
    #[inline(always)]
    pub fn input_count(&self) -> usize { self.inputs.len() }

    /// The number of output channels that this buffer was created for
    #[inline(always)]
    pub fn output_count(&self) -> usize { self.outputs.len() }

    /// The number of samples in this buffer (same for all channels)
    #[inline(always)]
    pub fn samples(&self) -> usize { self.samples }

    /// The raw inputs to pass to processReplacing
    #[inline(always)]
    pub(crate) fn raw_inputs(&self) -> &[*const T] { &self.inputs }

    /// The raw outputs to pass to processReplacing
    #[inline(always)]
    pub(crate) fn raw_outputs(&mut self) -> &mut [*mut T] { &mut self.outputs }

    /// Split this buffer into separate inputs and outputs.
    #[inline(always)]
    pub fn split<'b>(&'b mut self) -> (Inputs<'b, T>, Outputs<'b, T>) where 'a: 'b {
        (
            Inputs { bufs: &self.inputs, samples: self.samples },
            Outputs { bufs: &self.outputs, samples: self.samples }
        )
    }

    /// Zip together buffers.
    #[inline(always)]
    pub fn zip<'b>(&'b mut self) -> Zip<InputIterator<'b, T>, OutputIterator<'b, T>> where 'a: 'b {
        let (inputs, outputs) = self.split();
        inputs.into_iter().zip(outputs)
    }
}

use std::ops::{Index, IndexMut};

/// Wrapper type to access the buffers for the input channels of an AudioBuffer in a safe way.
/// Behaves like a slice.
#[derive(Copy, Clone)]
pub struct Inputs<'a, T: 'a> {
    bufs: &'a [*const T],
    samples: usize,
}

impl<'a, T> Inputs<'a, T> {

    /// Number of channels
    pub fn len(&self) -> usize { self.bufs.len() }

    /// Access channel at the given index, unchecked
    pub fn get(&self, i: usize) -> &'a [T] {
        unsafe { slice::from_raw_parts(self.bufs[i], self.samples) }
    }

    /// Split borrowing at the given index, like for slices
    pub fn split_at(&self, i: usize) -> (Inputs<'a, T>, Inputs<'a, T>) {
        let (l, r) = self.bufs.split_at(i);
        (
            Inputs { bufs: &l, samples: self.samples },
            Inputs { bufs: &r, samples: self.samples }
        )
    }
}

impl<'a, T> Index<usize> for Inputs<'a, T> {
    type Output = [T];

    fn index(&self, i: usize) -> &Self::Output {
        self.get(i)
    }
}

/// Iterator over buffers for input channels of an AudioBuffer.
pub struct InputIterator<'a, T: 'a> {
    data: Inputs<'a, T>,
    i: usize,
}

impl<'a, T> Iterator for InputIterator<'a, T> {
    type Item = &'a [T];

    fn next(&mut self) -> Option<Self::Item> {
        if self.i < self.data.len() {
            let val = self.data.get(self.i);
            self.i += 1;
            Some(val)
        } else {
            None
        }
    }
}

impl<'a, T: Sized> IntoIterator for Inputs<'a, T> {
    type Item = &'a [T];
    type IntoIter = InputIterator<'a, T>;

    fn into_iter(self) -> Self::IntoIter {
        InputIterator { data: self, i: 0 }
    }
}

/// Wrapper type to access the buffers for the output channels of an AudioBuffer in a safe way.
/// Behaves like a slice.
#[derive(Copy, Clone)]
pub struct Outputs<'a, T: 'a> {
    bufs: &'a [*mut T],
    samples: usize,
}

impl<'a, T> Outputs<'a, T> {

    /// Number of channels
    pub fn len(&self) -> usize { self.bufs.len() }

    /// Access channel at the given index, unchecked
    pub fn get(&self, i: usize) -> &'a [T] {
        unsafe { slice::from_raw_parts(self.bufs[i], self.samples) }
    }

    /// Mutably access channel at the given index, unchecked
    pub fn get_mut(&self, i: usize) -> &'a mut [T] {
        unsafe { slice::from_raw_parts_mut(self.bufs[i], self.samples) }
    }

    /// Split borrowing at the given index, like for slices
    pub fn split_at_mut(&mut self, i: usize) -> (Outputs<'a, T>, Outputs<'a, T>) {
        let (l, r) = self.bufs.split_at(i);
        (
            Outputs { bufs: &l, samples: self.samples },
            Outputs { bufs: &r, samples: self.samples }
        )
    }
}

impl<'a, T> Index<usize> for Outputs<'a, T> {
    type Output = [T];

    fn index(&self, i: usize) -> &Self::Output {
        self.get(i)
    }
}

impl<'a, T> IndexMut<usize> for Outputs<'a, T> {
    fn index_mut(&mut self, i: usize) -> &mut Self::Output {
        self.get_mut(i)
    }
}

/// Iterator over buffers for output channels of an AudioBuffer.
pub struct OutputIterator<'a, T: 'a> {
    data: Outputs<'a, T>,
    i: usize,
}

impl<'a, T> Iterator for OutputIterator<'a, T> {
    type Item = &'a mut [T];

    fn next(&mut self) -> Option<Self::Item> {
        if self.i < self.data.len() {
            let val = self.data.get_mut(self.i);
            self.i += 1;
            Some(val)
        } else {
            None
        }
    }
}

impl<'a, T: Sized> IntoIterator for Outputs<'a, T> {
    type Item = &'a mut [T];
    type IntoIter = OutputIterator<'a, T>;

    fn into_iter(self) -> Self::IntoIter {
        OutputIterator { data: self, i: 0 }
    }
}

use event::{Event, MidiEvent};
use api;
use std::mem;

/// This buffer is used for sending midi events through the VST interface.
/// The purpose of this is to convert outgoing midi events from event::Event to api::Events.
/// It only allocates memory in new() and reuses the memory between calls.
pub struct SendEventBuffer {
    buf: Vec<u8>,
    api_events: Vec<api::SysExEvent>,
}

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

impl SendEventBuffer {

    /// Creates a buffer for sending up to the given number of midi events per frame
    #[inline(always)]
    pub fn new(capacity: usize) -> Self {
        let header_size = mem::size_of::<api::Events>() - (mem::size_of::<*mut api::Event>() * 2);
        let body_size = mem::size_of::<*mut api::Event>() * capacity;
        let mut buf = vec![0u8; header_size + body_size];
        let api_events = vec![unsafe { mem::zeroed::<api::SysExEvent>() }; capacity];
        {
            let ptrs = {
                let e = Self::buf_as_api_events(&mut buf);
                e.num_events = capacity as i32;
                e.events_raw_mut()
            };
            for (ptr, event) in ptrs.iter_mut().zip(&api_events) {
                let (ptr, event): (&mut *const api::SysExEvent, &api::SysExEvent) = (ptr, event);
                *ptr = event;
            }
        }
        Self {
            buf: buf,
            api_events: api_events,
        }
    }

    #[inline(always)]
    fn buf_as_api_events(buf: &mut [u8]) -> &mut api::Events {
        unsafe { &mut *(buf.as_mut_ptr() as *mut api::Events) }
    }

    /// Use this for sending events to a host or plugin.
    ///
    /// # Example
    /// ```no_run
    /// # use vst2::plugin::{Info, Plugin, HostCallback};
    /// # use vst2::buffer::{AudioBuffer, SendEventBuffer};
    /// # use vst2::host::Host;
    /// # struct ExamplePlugin { host: HostCallback, send_buffer: SendEventBuffer }
    /// # impl Plugin for ExamplePlugin {
    /// #     fn get_info(&self) -> Info { Default::default() }
    /// #
    /// // Processor that clips samples above 0.4 or below -0.4:
    /// fn process(&mut self, buffer: &mut AudioBuffer<f32>){
    ///     let events = vec![
    ///         // ...
    ///     ];
    ///     self.send_buffer.store(&events);
    ///     self.host.process_events(self.send_buffer.events());
    /// }
    /// # }
    /// ```
    pub fn store(&mut self, events: &[Event]) {
        self.set_num_events(events.len());

        for (event, out) in events.iter().zip(self.api_events.iter_mut()) {
            let (event, out): (&Event, &mut api::SysExEvent) = (event, out);
            match *event {
                Event::Midi(ev) => {
                    Self::store_midi_impl(out, &ev);
                }
                Event::SysEx(ev) => {
                    *out = api::SysExEvent {
                        event_type: api::EventType::SysEx,
                        byte_size: mem::size_of::<api::SysExEvent>() as i32,
                        delta_frames: ev.delta_frames,
                        _flags: 0,
                        data_size: ev.payload.len() as i32,
                        _reserved1: 0,
                        system_data: ev.payload.as_ptr() as *const u8 as *mut u8,
                        _reserved2: 0,
                    };
                }
                Event::Deprecated(e) => {
                    let out = unsafe { &mut *(out as *mut _ as *mut _) };
                    *out = e;
                }
            };
        }
    }

    /// Use this for sending midi events to a host or plugin.
    /// Like store() but for when you're not sending any SysExEvents, only MidiEvents.
    pub fn store_midi(&mut self, events: &[MidiEvent]) {
        self.set_num_events(events.len());

        for (event, out) in events.iter().zip(self.api_events.iter_mut()) {
            let (ev, out): (&MidiEvent, &mut api::SysExEvent) = (event, out);
            Self::store_midi_impl(out, ev);
        }
    }

    fn store_midi_impl(out: &mut api::SysExEvent, ev: &MidiEvent) {
        use api::flags::REALTIME_EVENT;
        let out = unsafe { &mut *(out as *mut _ as *mut _) };
        *out = api::MidiEvent {
            event_type: api::EventType::Midi,
            byte_size: mem::size_of::<api::MidiEvent>() as i32,
            delta_frames: ev.delta_frames,
            flags: if ev.live { REALTIME_EVENT.bits() } else { 0 },
            note_length: ev.note_length.unwrap_or(0),
            note_offset: ev.note_offset.unwrap_or(0),
            midi_data: ev.data,
            _midi_reserved: 0,
            detune: ev.detune,
            note_off_velocity: ev.note_off_velocity,
            _reserved1: 0,
            _reserved2: 0
        };
    }

    fn set_num_events(&mut self, events_len: usize) {
        use std::cmp::min;
        let e = Self::buf_as_api_events(&mut self.buf);
        e.num_events = min(self.api_events.len(), events_len) as i32;
    }

    /// Use this for sending midi events to a host or plugin.
    /// See `store()`
    #[inline(always)]
    pub fn events(&self) -> &api::Events {
        unsafe { &*(self.buf.as_ptr() as *const api::Events) }
    }
}

#[cfg(test)]
mod tests {
    use buffer::AudioBuffer;

    /// Size of buffers used in tests.
    const SIZE: usize = 1024;

    /// Test that creating and zipping buffers works.
    ///
    /// This test creates a channel for 2 inputs and 2 outputs. The input channels are simply values
    /// from 0 to `SIZE-1` (e.g. [0, 1, 2, 3, 4, .. , SIZE - 1]) and the output channels are just 0.
    /// This test assures that when the buffers are zipped together, the input values do not change.
    #[test]
    fn buffer_zip() {
        let in1: Vec<f32> = (0..SIZE).map(|x| x as f32).collect();
        let in2 = in1.clone();

        let mut out1 = vec![0.0; SIZE];
        let mut out2 = out1.clone();

        let inputs = vec![in1.as_ptr(), in2.as_ptr()];
        let mut outputs = vec![out1.as_mut_ptr(), out2.as_mut_ptr()];
        let mut buffer = AudioBuffer::new(&inputs, &mut outputs, SIZE);

        for (input, output) in buffer.zip() {
            input.into_iter().zip(output.into_iter())
            .fold(0, |acc, (input, output)| {
                assert_eq!(*input - acc as f32, 0.0);
                assert_eq!(*output, 0.0);
                acc + 1
            });
        }
    }

    /// Test that creating buffers from raw pointers works.
    #[test]
    fn from_raw() {
        let in1: Vec<f32> = (0..SIZE).map(|x| x as f32).collect();
        let in2 = in1.clone();

        let mut out1 = vec![0.0; SIZE];
        let mut out2 = out1.clone();

        let inputs = vec![in1.as_ptr(), in2.as_ptr()];
        let mut outputs = vec![out1.as_mut_ptr(), out2.as_mut_ptr()];
        let mut buffer = AudioBuffer::from_raw(2, 2, inputs.as_ptr(), outputs.as_mut_ptr(), SIZE);

        for (input, output) in buffer.zip() {
            input.into_iter().zip(output.into_iter())
            .fold(0, |acc, (input, output)| {
                assert_eq!(*input - acc as f32, 0.0);
                assert_eq!(*output, 0.0);
                acc + 1
            });
        }
    }
}<commit_msg>make SendEventBuffer::store() and store_midi() more flexible, taking an iterator over events that may be values or refs<commit_after>//! Buffers to safely work with audio samples.

use num_traits::Float;

use std::slice;
use std::iter::Zip;

/// AudioBuffer contains references to the audio buffers for all input and output channels
pub struct AudioBuffer<'a, T: 'a + Float> {
    inputs: &'a [*const T],
    outputs: &'a mut [*mut T],
    samples: usize,
}

impl<'a, T: 'a + Float> AudioBuffer<'a, T> {

    /// Create an `AudioBuffer` from slices of raw pointers. Useful in a Rust VST host.
    #[inline(always)]
    pub fn new(inputs: &'a [*const T], outputs: &'a mut [*mut T], samples: usize) -> Self {
        Self {
            inputs: inputs,
            outputs: outputs,
            samples: samples,
        }
    }

    /// Create an `AudioBuffer` from raw pointers. Only really useful for interacting with the VST API.
    #[inline(always)]
    pub fn from_raw(input_count: usize, output_count: usize,
                    inputs_raw: *const *const T, outputs_raw: *mut *mut T, samples: usize) -> Self {
        Self {
            inputs: unsafe { slice::from_raw_parts(inputs_raw, input_count) },
            outputs: unsafe { slice::from_raw_parts_mut(outputs_raw, output_count) },
            samples: samples,
        }
    }

    /// The number of input channels that this buffer was created for
    #[inline(always)]
    pub fn input_count(&self) -> usize { self.inputs.len() }

    /// The number of output channels that this buffer was created for
    #[inline(always)]
    pub fn output_count(&self) -> usize { self.outputs.len() }

    /// The number of samples in this buffer (same for all channels)
    #[inline(always)]
    pub fn samples(&self) -> usize { self.samples }

    /// The raw inputs to pass to processReplacing
    #[inline(always)]
    pub(crate) fn raw_inputs(&self) -> &[*const T] { &self.inputs }

    /// The raw outputs to pass to processReplacing
    #[inline(always)]
    pub(crate) fn raw_outputs(&mut self) -> &mut [*mut T] { &mut self.outputs }

    /// Split this buffer into separate inputs and outputs.
    #[inline(always)]
    pub fn split<'b>(&'b mut self) -> (Inputs<'b, T>, Outputs<'b, T>) where 'a: 'b {
        (
            Inputs { bufs: &self.inputs, samples: self.samples },
            Outputs { bufs: &self.outputs, samples: self.samples }
        )
    }

    /// Zip together buffers.
    #[inline(always)]
    pub fn zip<'b>(&'b mut self) -> Zip<InputIterator<'b, T>, OutputIterator<'b, T>> where 'a: 'b {
        let (inputs, outputs) = self.split();
        inputs.into_iter().zip(outputs)
    }
}

use std::ops::{Index, IndexMut};

/// Wrapper type to access the buffers for the input channels of an AudioBuffer in a safe way.
/// Behaves like a slice.
#[derive(Copy, Clone)]
pub struct Inputs<'a, T: 'a> {
    bufs: &'a [*const T],
    samples: usize,
}

impl<'a, T> Inputs<'a, T> {

    /// Number of channels
    pub fn len(&self) -> usize { self.bufs.len() }

    /// Access channel at the given index, unchecked
    pub fn get(&self, i: usize) -> &'a [T] {
        unsafe { slice::from_raw_parts(self.bufs[i], self.samples) }
    }

    /// Split borrowing at the given index, like for slices
    pub fn split_at(&self, i: usize) -> (Inputs<'a, T>, Inputs<'a, T>) {
        let (l, r) = self.bufs.split_at(i);
        (
            Inputs { bufs: &l, samples: self.samples },
            Inputs { bufs: &r, samples: self.samples }
        )
    }
}

impl<'a, T> Index<usize> for Inputs<'a, T> {
    type Output = [T];

    fn index(&self, i: usize) -> &Self::Output {
        self.get(i)
    }
}

/// Iterator over buffers for input channels of an AudioBuffer.
pub struct InputIterator<'a, T: 'a> {
    data: Inputs<'a, T>,
    i: usize,
}

impl<'a, T> Iterator for InputIterator<'a, T> {
    type Item = &'a [T];

    fn next(&mut self) -> Option<Self::Item> {
        if self.i < self.data.len() {
            let val = self.data.get(self.i);
            self.i += 1;
            Some(val)
        } else {
            None
        }
    }
}

impl<'a, T: Sized> IntoIterator for Inputs<'a, T> {
    type Item = &'a [T];
    type IntoIter = InputIterator<'a, T>;

    fn into_iter(self) -> Self::IntoIter {
        InputIterator { data: self, i: 0 }
    }
}

/// Wrapper type to access the buffers for the output channels of an AudioBuffer in a safe way.
/// Behaves like a slice.
#[derive(Copy, Clone)]
pub struct Outputs<'a, T: 'a> {
    bufs: &'a [*mut T],
    samples: usize,
}

impl<'a, T> Outputs<'a, T> {

    /// Number of channels
    pub fn len(&self) -> usize { self.bufs.len() }

    /// Access channel at the given index, unchecked
    pub fn get(&self, i: usize) -> &'a [T] {
        unsafe { slice::from_raw_parts(self.bufs[i], self.samples) }
    }

    /// Mutably access channel at the given index, unchecked
    pub fn get_mut(&self, i: usize) -> &'a mut [T] {
        unsafe { slice::from_raw_parts_mut(self.bufs[i], self.samples) }
    }

    /// Split borrowing at the given index, like for slices
    pub fn split_at_mut(&mut self, i: usize) -> (Outputs<'a, T>, Outputs<'a, T>) {
        let (l, r) = self.bufs.split_at(i);
        (
            Outputs { bufs: &l, samples: self.samples },
            Outputs { bufs: &r, samples: self.samples }
        )
    }
}

impl<'a, T> Index<usize> for Outputs<'a, T> {
    type Output = [T];

    fn index(&self, i: usize) -> &Self::Output {
        self.get(i)
    }
}

impl<'a, T> IndexMut<usize> for Outputs<'a, T> {
    fn index_mut(&mut self, i: usize) -> &mut Self::Output {
        self.get_mut(i)
    }
}

/// Iterator over buffers for output channels of an AudioBuffer.
pub struct OutputIterator<'a, T: 'a> {
    data: Outputs<'a, T>,
    i: usize,
}

impl<'a, T> Iterator for OutputIterator<'a, T> {
    type Item = &'a mut [T];

    fn next(&mut self) -> Option<Self::Item> {
        if self.i < self.data.len() {
            let val = self.data.get_mut(self.i);
            self.i += 1;
            Some(val)
        } else {
            None
        }
    }
}

impl<'a, T: Sized> IntoIterator for Outputs<'a, T> {
    type Item = &'a mut [T];
    type IntoIter = OutputIterator<'a, T>;

    fn into_iter(self) -> Self::IntoIter {
        OutputIterator { data: self, i: 0 }
    }
}

use event::{Event, MidiEvent};
use api;
use std::mem;
use std::borrow::Borrow;

/// This buffer is used for sending midi events through the VST interface.
/// The purpose of this is to convert outgoing midi events from event::Event to api::Events.
/// It only allocates memory in new() and reuses the memory between calls.
pub struct SendEventBuffer {
    buf: Vec<u8>,
    api_events: Vec<api::SysExEvent>,
}

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

impl SendEventBuffer {

    /// Creates a buffer for sending up to the given number of midi events per frame
    #[inline(always)]
    pub fn new(capacity: usize) -> Self {
        let header_size = mem::size_of::<api::Events>() - (mem::size_of::<*mut api::Event>() * 2);
        let body_size = mem::size_of::<*mut api::Event>() * capacity;
        let mut buf = vec![0u8; header_size + body_size];
        let api_events = vec![unsafe { mem::zeroed::<api::SysExEvent>() }; capacity];
        {
            let ptrs = {
                let e = Self::buf_as_api_events(&mut buf);
                e.num_events = capacity as i32;
                e.events_raw_mut()
            };
            for (ptr, event) in ptrs.iter_mut().zip(&api_events) {
                let (ptr, event): (&mut *const api::SysExEvent, &api::SysExEvent) = (ptr, event);
                *ptr = event;
            }
        }
        Self {
            buf: buf,
            api_events: api_events,
        }
    }

    #[inline(always)]
    fn buf_as_api_events(buf: &mut [u8]) -> &mut api::Events {
        unsafe { &mut *(buf.as_mut_ptr() as *mut api::Events) }
    }

    /// Use this for sending events to a host or plugin.
    ///
    /// # Example
    /// ```no_run
    /// # use vst2::plugin::{Info, Plugin, HostCallback};
    /// # use vst2::buffer::{AudioBuffer, SendEventBuffer};
    /// # use vst2::host::Host;
    /// # struct ExamplePlugin { host: HostCallback, send_buffer: SendEventBuffer }
    /// # impl Plugin for ExamplePlugin {
    /// #     fn get_info(&self) -> Info { Default::default() }
    /// #
    /// // Processor that clips samples above 0.4 or below -0.4:
    /// fn process(&mut self, buffer: &mut AudioBuffer<f32>){
    ///     let events = vec![
    ///         // ...
    ///     ];
    ///     self.send_buffer.store(&events);
    ///     self.host.process_events(self.send_buffer.events());
    /// }
    /// # }
    /// ```
    pub fn store<'a, T: IntoIterator<Item = U>, U: Borrow<Event<'a>>>(&mut self, events: T) {
        let count = events.into_iter().zip(self.api_events.iter_mut()).map(|(event, out)| {
            let (event, out): (&Event, &mut api::SysExEvent) = (event.borrow(), out);
            match *event {
                Event::Midi(ev) => {
                    Self::store_midi_impl(out, &ev);
                }
                Event::SysEx(ev) => {
                    *out = api::SysExEvent {
                        event_type: api::EventType::SysEx,
                        byte_size: mem::size_of::<api::SysExEvent>() as i32,
                        delta_frames: ev.delta_frames,
                        _flags: 0,
                        data_size: ev.payload.len() as i32,
                        _reserved1: 0,
                        system_data: ev.payload.as_ptr() as *const u8 as *mut u8,
                        _reserved2: 0,
                    };
                }
                Event::Deprecated(e) => {
                    let out = unsafe { &mut *(out as *mut _ as *mut _) };
                    *out = e;
                }
            };
        }).count();
        self.set_num_events(count);
    }

    /// Use this for sending midi events to a host or plugin.
    /// Like store() but for when you're not sending any SysExEvents, only MidiEvents.
    pub fn store_midi<T: IntoIterator<Item = U>, U: Borrow<MidiEvent>>(&mut self, events: T) {
        let count = events.into_iter().zip(self.api_events.iter_mut()).map(|(event, out)| {
            let (ev, out): (&MidiEvent, &mut api::SysExEvent) = (event.borrow(), out);
            Self::store_midi_impl(out, ev);
        }).count();
        self.set_num_events(count);
    }

    fn store_midi_impl(out: &mut api::SysExEvent, ev: &MidiEvent) {
        use api::flags::REALTIME_EVENT;
        let out = unsafe { &mut *(out as *mut _ as *mut _) };
        *out = api::MidiEvent {
            event_type: api::EventType::Midi,
            byte_size: mem::size_of::<api::MidiEvent>() as i32,
            delta_frames: ev.delta_frames,
            flags: if ev.live { REALTIME_EVENT.bits() } else { 0 },
            note_length: ev.note_length.unwrap_or(0),
            note_offset: ev.note_offset.unwrap_or(0),
            midi_data: ev.data,
            _midi_reserved: 0,
            detune: ev.detune,
            note_off_velocity: ev.note_off_velocity,
            _reserved1: 0,
            _reserved2: 0
        };
    }

    fn set_num_events(&mut self, events_len: usize) {
        use std::cmp::min;
        let e = Self::buf_as_api_events(&mut self.buf);
        e.num_events = min(self.api_events.len(), events_len) as i32;
    }

    /// Use this for sending midi events to a host or plugin.
    /// See `store()`
    #[inline(always)]
    pub fn events(&self) -> &api::Events {
        unsafe { &*(self.buf.as_ptr() as *const api::Events) }
    }
}

#[cfg(test)]
mod tests {
    use buffer::AudioBuffer;

    /// Size of buffers used in tests.
    const SIZE: usize = 1024;

    /// Test that creating and zipping buffers works.
    ///
    /// This test creates a channel for 2 inputs and 2 outputs. The input channels are simply values
    /// from 0 to `SIZE-1` (e.g. [0, 1, 2, 3, 4, .. , SIZE - 1]) and the output channels are just 0.
    /// This test assures that when the buffers are zipped together, the input values do not change.
    #[test]
    fn buffer_zip() {
        let in1: Vec<f32> = (0..SIZE).map(|x| x as f32).collect();
        let in2 = in1.clone();

        let mut out1 = vec![0.0; SIZE];
        let mut out2 = out1.clone();

        let inputs = vec![in1.as_ptr(), in2.as_ptr()];
        let mut outputs = vec![out1.as_mut_ptr(), out2.as_mut_ptr()];
        let mut buffer = AudioBuffer::new(&inputs, &mut outputs, SIZE);

        for (input, output) in buffer.zip() {
            input.into_iter().zip(output.into_iter())
            .fold(0, |acc, (input, output)| {
                assert_eq!(*input - acc as f32, 0.0);
                assert_eq!(*output, 0.0);
                acc + 1
            });
        }
    }

    /// Test that creating buffers from raw pointers works.
    #[test]
    fn from_raw() {
        let in1: Vec<f32> = (0..SIZE).map(|x| x as f32).collect();
        let in2 = in1.clone();

        let mut out1 = vec![0.0; SIZE];
        let mut out2 = out1.clone();

        let inputs = vec![in1.as_ptr(), in2.as_ptr()];
        let mut outputs = vec![out1.as_mut_ptr(), out2.as_mut_ptr()];
        let mut buffer = AudioBuffer::from_raw(2, 2, inputs.as_ptr(), outputs.as_mut_ptr(), SIZE);

        for (input, output) in buffer.zip() {
            input.into_iter().zip(output.into_iter())
            .fold(0, |acc, (input, output)| {
                assert_eq!(*input - acc as f32, 0.0);
                assert_eq!(*output, 0.0);
                acc + 1
            });
        }
    }
}<|endoftext|>


<commit_before>use std::mem;
use std::ptr;
use std::marker::PhantomData;
use std::borrow::BorrowMut;
use gl;
use gl::types::*;
use context::ContextOf;
use framebuffer::FramebufferBinding;
use types::{DrawingMode, GLError};
use index_data::{IndexData, IndexDatum, IndexDatumType};

pub struct Buffer {
    gl_id: GLuint
}

impl Buffer {
    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }
}

impl Drop for Buffer {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteBuffers(1, &self.gl_id as *const GLuint);
        }
    }
}

impl<AB, EAB, P, FB, RB, TU> ContextOf<AB, EAB, P, FB, RB, TU> {
    pub fn gen_buffer(&self) -> Buffer {
        unsafe {
            let mut id : GLuint = 0;

            gl::GenBuffers(1, &mut id as *mut GLuint);
            dbg_gl_sanity_check! {
                GLError::InvalidValue => "`n` is negative",
                _ => "Unknown error"
            }

            Buffer { gl_id: id }
        }
    }

    pub fn bind_array_buffer<'a>(self, buffer: &'a mut Buffer)
        -> (
            ArrayBufferBinding<'a>,
            ContextOf<(), EAB, P, FB, RB, TU>
        )
        where AB: BorrowMut<ArrayBufferBinder>
    {
        let (mut array_buffer, gl) = self.split_array_buffer();
        (array_buffer.borrow_mut().bind(buffer), gl)
    }

    pub fn bind_element_array_buffer<'a>(self, buffer: &'a mut Buffer)
        -> (
            ElementArrayBufferBinding<'a>,
            ContextOf<AB, (), P, FB, RB, TU>
        )
        where EAB: BorrowMut<ElementArrayBufferBinder>
    {
        let (mut element_array_buffer, gl) = self.split_element_array_buffer();
        (element_array_buffer.borrow_mut().bind(buffer), gl)
    }
}

gl_enum! {
    pub gl_enum BufferDataUsage {
        StreamDraw as STREAM_DRAW = gl::STREAM_DRAW,
        StaticDraw as STATIC_DRAW = gl::STATIC_DRAW,
        DynamicDraw as DYNAMIC_DRAW = gl::DYNAMIC_DRAW
    }
}

gl_enum! {
    pub gl_enum BufferBindingTarget {
        ArrayBuffer as ARRAY_BUFFER = gl::ARRAY_BUFFER,
        ElementArrayBuffer as ELEMENT_ARRAY_BUFFER = gl::ELEMENT_ARRAY_BUFFER
    }
}

pub trait BufferBinding {
    fn target(&self) -> BufferBindingTarget;

    fn buffer_bytes(&mut self, bytes: &[u8], usage: BufferDataUsage) {
        let ptr = bytes.as_ptr();
        let size = bytes.len() * mem::size_of::<u8>();
        unsafe {
            gl::BufferData(self.target().gl_enum(),
                           size as GLsizeiptr,
                           ptr as *const GLvoid,
                           usage.gl_enum());
            dbg_gl_error! {
                GLError::InvalidEnum => "Invalid `target` or `usage`",
                GLError::InvalidValue => "`size` is negative",
                GLError::InvalidOperation => "Object 0 is bound to buffer target",
                GLError::OutOfMemory => "Unable to create a large enough buffer",
                _ => "Unknown error"
            }
        }
    }
}

pub struct ArrayBufferBinding<'a> {
    phantom: PhantomData<&'a mut Buffer>
}

impl<'a> BufferBinding for ArrayBufferBinding<'a> {
    fn target(&self) -> BufferBindingTarget {
        ARRAY_BUFFER
    }
}

unsafe fn _draw_elements(mode: DrawingMode,
                         count: usize,
                         index_type: IndexDatumType,
                         indices: *const GLvoid)
{
    let gl_index_type: GLenum = match index_type {
        IndexDatumType::UnsignedByte => gl::UNSIGNED_BYTE,
        IndexDatumType::UnsignedShort => gl::UNSIGNED_SHORT
    };
    gl::DrawElements(mode.gl_enum(),
                     count as GLsizei,
                     gl_index_type,
                     indices);
    dbg_gl_error! {
        GLError::InvalidEnum => "`mode` or `type` is not an accepted value",
        GLError::InvalidValue => "`count` is negative",
        GLError::InvalidFramebufferOperation => "The current framebuffer is not framebuffer-complete",
        _ => "Unknown error"
    }
}

impl<'a> ArrayBufferBinding<'a> {
    pub unsafe fn vertex_attrib_pointer(&self,
                                        attrib: super::ProgramAttrib,
                                        components: i8,
                                        gl_type: super::DataType,
                                        normalized: bool,
                                        stride: usize,
                                        offset: usize)
    {
        debug_assert!(1 <= components && components <= 4);

        let gl_normalized = if normalized { gl::TRUE } else { gl::FALSE };
        gl::VertexAttribPointer(attrib.gl_index,
                                components as GLint,
                                gl_type.gl_enum(),
                                gl_normalized,
                                stride as GLsizei,
                                offset as *const GLvoid);
        dbg_gl_error! {
            GLError::InvalidEnum => "Illegal vertex attribute type",
            GLError::InvalidValue => "`stride` is negative, `size` is not in range, or `index` is >= GL_MAX_VERTEX_ATTRIBS",
            GLError::InvalidFramebufferOperation => "Currently bound framebuffer is not framebuffer complete",
            _ => "Unknown error"
        }
    }
}

impl<'a> FramebufferBinding<'a> {
    pub unsafe fn draw_arrays_range(&mut self,
                                    _ab: &ArrayBufferBinding,
                                    mode: DrawingMode,
                                    first: u32,
                                    count: usize)
    {
        gl::DrawArrays(mode.gl_enum(), first as GLint, count as GLsizei);
        dbg_gl_sanity_check! {
            GLError::InvalidEnum => "`mode` is not an accepted value",
            GLError::InvalidValue => "`count` is negative",
            _ => "Unknown error"
        }
    }

    pub unsafe fn draw_n_elements_buffered(&mut self,
                                           _ab: &ArrayBufferBinding,
                                           _eab: &ElementArrayBufferBinding,
                                           mode: DrawingMode,
                                           count: usize,
                                           index_type: IndexDatumType)
    {
        _draw_elements(mode, count, index_type, ptr::null());
    }

    pub unsafe fn draw_n_elements<I>(&mut self,
                                     _ab: &ArrayBufferBinding,
                                     mode: DrawingMode,
                                     count: usize,
                                     indices: &[I])
        where I: IndexDatum, [I]: IndexData
    {
        debug_assert!(count <= indices.len());

        let ptr = indices.index_bytes().as_ptr();
        let index_type = I::index_datum_type();
        _draw_elements(mode, count, index_type, mem::transmute(ptr));
    }

    pub unsafe fn draw_elements<I>(&mut self,
                                   _ab: &ArrayBufferBinding,
                                   mode: DrawingMode,
                                   indices: &[I])
        where I: IndexDatum, [I]: IndexData
    {
        self.draw_n_elements(_ab, mode, indices.len(), indices);
    }
}

pub struct ElementArrayBufferBinding<'a> {
    phantom: PhantomData<&'a mut Buffer>
}

impl<'a> BufferBinding for ElementArrayBufferBinding<'a> {
    fn target(&self) -> BufferBindingTarget {
        ELEMENT_ARRAY_BUFFER
    }
}

fn _bind_buffer(target: BufferBindingTarget, buffer: &mut Buffer) {
    unsafe {
        gl::BindBuffer(target as GLuint, buffer.gl_id());
        dbg_gl_sanity_check! {
            GLError::InvalidEnum => "`target` is not an allowed value",
            _ => "Unknown error"
        }
    }
}

pub struct ArrayBufferBinder;
impl ArrayBufferBinder {
    pub fn bind<'a>(&mut self, buffer: &'a mut Buffer) -> ArrayBufferBinding<'a>
    {
        let binding = ArrayBufferBinding { phantom: PhantomData };
        _bind_buffer(binding.target(), buffer);
        binding
    }
}

pub struct ElementArrayBufferBinder;
impl ElementArrayBufferBinder {
    pub fn bind<'a>(&mut self, buffer: &'a mut Buffer)
        -> ElementArrayBufferBinding<'a>
    {
        let binding = ElementArrayBufferBinding { phantom: PhantomData };
        _bind_buffer(binding.target(), buffer);
        binding
    }
}
<commit_msg>Add `BufferBinderOf` struct<commit_after>use std::mem;
use std::ptr;
use std::marker::PhantomData;
use std::borrow::BorrowMut;
use gl;
use gl::types::*;
use context::ContextOf;
use framebuffer::FramebufferBinding;
use types::{DrawingMode, GLError};
use index_data::{IndexData, IndexDatum, IndexDatumType};

pub struct Buffer {
    gl_id: GLuint
}

impl Buffer {
    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }
}

impl Drop for Buffer {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteBuffers(1, &self.gl_id as *const GLuint);
        }
    }
}

impl<AB, EAB, P, FB, RB, TU> ContextOf<AB, EAB, P, FB, RB, TU> {
    pub fn gen_buffer(&self) -> Buffer {
        unsafe {
            let mut id : GLuint = 0;

            gl::GenBuffers(1, &mut id as *mut GLuint);
            dbg_gl_sanity_check! {
                GLError::InvalidValue => "`n` is negative",
                _ => "Unknown error"
            }

            Buffer { gl_id: id }
        }
    }

    pub fn bind_array_buffer<'a>(self, buffer: &'a mut Buffer)
        -> (
            ArrayBufferBinding<'a>,
            ContextOf<(), EAB, P, FB, RB, TU>
        )
        where AB: BorrowMut<ArrayBufferBinder>
    {
        let (mut array_buffer, gl) = self.split_array_buffer();
        (array_buffer.borrow_mut().bind(buffer), gl)
    }

    pub fn bind_element_array_buffer<'a>(self, buffer: &'a mut Buffer)
        -> (
            ElementArrayBufferBinding<'a>,
            ContextOf<AB, (), P, FB, RB, TU>
        )
        where EAB: BorrowMut<ElementArrayBufferBinder>
    {
        let (mut element_array_buffer, gl) = self.split_element_array_buffer();
        (element_array_buffer.borrow_mut().bind(buffer), gl)
    }
}

gl_enum! {
    pub gl_enum BufferDataUsage {
        StreamDraw as STREAM_DRAW = gl::STREAM_DRAW,
        StaticDraw as STATIC_DRAW = gl::STATIC_DRAW,
        DynamicDraw as DYNAMIC_DRAW = gl::DYNAMIC_DRAW
    }
}

gl_enum! {
    pub gl_enum BufferBindingTarget {
        ArrayBuffer as ARRAY_BUFFER = gl::ARRAY_BUFFER,
        ElementArrayBuffer as ELEMENT_ARRAY_BUFFER = gl::ELEMENT_ARRAY_BUFFER
    }
}

pub trait BufferBinding {
    fn target(&self) -> BufferBindingTarget;

    fn buffer_bytes(&mut self, bytes: &[u8], usage: BufferDataUsage) {
        let ptr = bytes.as_ptr();
        let size = bytes.len() * mem::size_of::<u8>();
        unsafe {
            gl::BufferData(self.target().gl_enum(),
                           size as GLsizeiptr,
                           ptr as *const GLvoid,
                           usage.gl_enum());
            dbg_gl_error! {
                GLError::InvalidEnum => "Invalid `target` or `usage`",
                GLError::InvalidValue => "`size` is negative",
                GLError::InvalidOperation => "Object 0 is bound to buffer target",
                GLError::OutOfMemory => "Unable to create a large enough buffer",
                _ => "Unknown error"
            }
        }
    }
}

pub struct ArrayBufferBinding<'a> {
    phantom: PhantomData<&'a mut Buffer>
}

impl<'a> BufferBinding for ArrayBufferBinding<'a> {
    fn target(&self) -> BufferBindingTarget {
        ARRAY_BUFFER
    }
}

unsafe fn _draw_elements(mode: DrawingMode,
                         count: usize,
                         index_type: IndexDatumType,
                         indices: *const GLvoid)
{
    let gl_index_type: GLenum = match index_type {
        IndexDatumType::UnsignedByte => gl::UNSIGNED_BYTE,
        IndexDatumType::UnsignedShort => gl::UNSIGNED_SHORT
    };
    gl::DrawElements(mode.gl_enum(),
                     count as GLsizei,
                     gl_index_type,
                     indices);
    dbg_gl_error! {
        GLError::InvalidEnum => "`mode` or `type` is not an accepted value",
        GLError::InvalidValue => "`count` is negative",
        GLError::InvalidFramebufferOperation => "The current framebuffer is not framebuffer-complete",
        _ => "Unknown error"
    }
}

impl<'a> ArrayBufferBinding<'a> {
    pub unsafe fn vertex_attrib_pointer(&self,
                                        attrib: super::ProgramAttrib,
                                        components: i8,
                                        gl_type: super::DataType,
                                        normalized: bool,
                                        stride: usize,
                                        offset: usize)
    {
        debug_assert!(1 <= components && components <= 4);

        let gl_normalized = if normalized { gl::TRUE } else { gl::FALSE };
        gl::VertexAttribPointer(attrib.gl_index,
                                components as GLint,
                                gl_type.gl_enum(),
                                gl_normalized,
                                stride as GLsizei,
                                offset as *const GLvoid);
        dbg_gl_error! {
            GLError::InvalidEnum => "Illegal vertex attribute type",
            GLError::InvalidValue => "`stride` is negative, `size` is not in range, or `index` is >= GL_MAX_VERTEX_ATTRIBS",
            GLError::InvalidFramebufferOperation => "Currently bound framebuffer is not framebuffer complete",
            _ => "Unknown error"
        }
    }
}

impl<'a> FramebufferBinding<'a> {
    pub unsafe fn draw_arrays_range(&mut self,
                                    _ab: &ArrayBufferBinding,
                                    mode: DrawingMode,
                                    first: u32,
                                    count: usize)
    {
        gl::DrawArrays(mode.gl_enum(), first as GLint, count as GLsizei);
        dbg_gl_sanity_check! {
            GLError::InvalidEnum => "`mode` is not an accepted value",
            GLError::InvalidValue => "`count` is negative",
            _ => "Unknown error"
        }
    }

    pub unsafe fn draw_n_elements_buffered(&mut self,
                                           _ab: &ArrayBufferBinding,
                                           _eab: &ElementArrayBufferBinding,
                                           mode: DrawingMode,
                                           count: usize,
                                           index_type: IndexDatumType)
    {
        _draw_elements(mode, count, index_type, ptr::null());
    }

    pub unsafe fn draw_n_elements<I>(&mut self,
                                     _ab: &ArrayBufferBinding,
                                     mode: DrawingMode,
                                     count: usize,
                                     indices: &[I])
        where I: IndexDatum, [I]: IndexData
    {
        debug_assert!(count <= indices.len());

        let ptr = indices.index_bytes().as_ptr();
        let index_type = I::index_datum_type();
        _draw_elements(mode, count, index_type, mem::transmute(ptr));
    }

    pub unsafe fn draw_elements<I>(&mut self,
                                   _ab: &ArrayBufferBinding,
                                   mode: DrawingMode,
                                   indices: &[I])
        where I: IndexDatum, [I]: IndexData
    {
        self.draw_n_elements(_ab, mode, indices.len(), indices);
    }
}

pub struct ElementArrayBufferBinding<'a> {
    phantom: PhantomData<&'a mut Buffer>
}

impl<'a> BufferBinding for ElementArrayBufferBinding<'a> {
    fn target(&self) -> BufferBindingTarget {
        ELEMENT_ARRAY_BUFFER
    }
}

fn _bind_buffer(target: BufferBindingTarget, buffer: &mut Buffer) {
    unsafe {
        gl::BindBuffer(target as GLuint, buffer.gl_id());
        dbg_gl_sanity_check! {
            GLError::InvalidEnum => "`target` is not an allowed value",
            _ => "Unknown error"
        }
    }
}

pub struct BufferBinderOf<A, E> {
    array: A,
    element_array: E
}

pub struct ArrayBufferBinder;
impl ArrayBufferBinder {
    pub fn bind<'a>(&mut self, buffer: &'a mut Buffer) -> ArrayBufferBinding<'a>
    {
        let binding = ArrayBufferBinding { phantom: PhantomData };
        _bind_buffer(binding.target(), buffer);
        binding
    }
}

pub struct ElementArrayBufferBinder;
impl ElementArrayBufferBinder {
    pub fn bind<'a>(&mut self, buffer: &'a mut Buffer)
        -> ElementArrayBufferBinding<'a>
    {
        let binding = ElementArrayBufferBinding { phantom: PhantomData };
        _bind_buffer(binding.target(), buffer);
        binding
    }
}
<|endoftext|>