<commit_before>// Copyright 2013-2014 Jeffery Olson
//
// Licensed under the 3-Clause BSD License, see LICENSE.txt
// at the top-level of this repository.
// This file may not be copied, modified, or distributed
// except according to those terms.
#![crate_id="http://olsonjeffery.github.io#schemers:0.0.1"]
#![desc = "Simple Scheme Interpreter"]
#![license = "3-Clause BSD"]

use std::from_str::FromStr;

// this is starting out as a straight port of Peter Norvig's
// lis.py (the first iteration) to Rust

#[cfg(not(test))]
fn main() {
    use std::os::args;
    let args: Vec<~str> = args().move_iter().skip(1).collect();
    if args.len() == 0 {
        fail!("no program provided");
    }
    let program: ~str = args.move_iter()
        .fold(~"", |memo, arg| memo + arg + " ").trim().to_owned();
    let tokens = &mut tokenize(program);
    println!("{:?}", read(tokens));
}

// parser impl
fn pad_input(input: ~str) -> ~str {
    input.replace("(", " ( ").replace(")", " ) ")
}

fn tokenize(input: ~str) -> Vec<~str> {
    pad_input(input).split_str(" ")
        .filter(|i| *i != "").map(|i| i.to_owned()).collect()
}

#[deriving(Eq, Show)]
pub enum ParseItem {
    AtomItem(Atom),
    ListItem(Vec<~ParseItem>)
}
impl ParseItem {
    pub fn new_atom(input: ~str) -> ParseItem {
        let first_char = input.char_at(0);
        match first_char {
            '0' | '1' | '2' | '3' | '4' | '5' |
            '6' | '7' | '8' | '9' => {
                let val = FromStr::from_str(input);
                match val {
                    Some(val) => AtomItem(IntAtom(val)),
                    None => fail!("Cannot parse number-like input of: {}", input)
                }
            },
            _ => AtomItem(StrAtom(input))
        }
    }
}

#[deriving(Eq, Show)]
pub enum Atom {
    StrAtom(~str),
    IntAtom(int)
}

impl ParseItem {
    pub fn is_atom(&self) -> bool {
        match *self {
            AtomItem(_) => true,
            _ => false
        }
    }
}

fn read(tokens: &mut Vec<~str>) -> ParseItem {
    let current_token =
        tokens.shift().expect("calling read() w/ empty token list; shouldn't happen");
    match current_token {
        ref x if *x == ~"(" => {
            let mut list = Vec::new();
            while *tokens.get(0) != ~")" {
                list.push(box read(tokens));
            }
            tokens.shift();
            ListItem(list)
        },
        ref x if *x == ~")" => fail!("hit ) token; shouldn't happen"),
        x => ParseItem::new_atom(x)
    }
}

#[cfg(test)]
mod parser_test {
    use super::{pad_input, tokenize, read, AtomItem, ListItem, StrAtom, IntAtom};

    #[test]
    fn pad_input_should_insert_spaces_before_and_after_parens() {
        assert_eq!(pad_input(~"(x 1 2 3)"), ~" ( x 1 2 3 ) ");
    }

    #[test]
    fn tokenize_string_into_tokens() {
        let tokens = tokenize(~"(foo 12 3)");
        assert_eq!(tokens.len(), 5);
        assert_eq!(tokens.get(0).to_owned(), ~"(");
        assert_eq!(tokens.get(1).to_owned(), ~"foo");
        assert_eq!(tokens.get(2).to_owned(), ~"12");
        assert_eq!(tokens.get(3).to_owned(), ~"3");
        assert_eq!(tokens.get(4).to_owned(), ~")");
    }

    #[test]
    fn should_parse_tokens_consisting_of_a_str_atom_and_convert_it_to_a_parse_item() {
        let tokens = &mut tokenize(~"bar");
        let parsed_item = read(tokens);
        println!("{:?}", parsed_item);
        match parsed_item {
            AtomItem(StrAtom(val)) => {
                assert_eq!(val, ~"bar")
            },
            _ => assert!(false)
        }
    }
    #[test]
    fn should_parse_tokens_consisting_of_an_int_atom_and_convert_it_to_a_parse_item() {
        let tokens = &mut tokenize(~"42");
        let parsed_item = read(tokens);
        println!("{:?}", parsed_item);
        match parsed_item {
            AtomItem(IntAtom(val)) => {
                assert_eq!(val, 42)
            },
            _ => assert!(false)
        }
    }

    #[test]
    fn should_parse_tokens_consisting_of_a_list_of_atoms_and_parse_it() {
        let tokens = &mut tokenize(~"(bar 12 45)");
        let parsed_item = read(tokens);
        assert_eq!(parsed_item.is_atom(), false);
        match parsed_item {
            ListItem(items) => {
                let items_len = items.len();
                assert!(3 == items_len);
                assert_eq!(items.get(0).is_atom(), true);
                assert_eq!(*items.get(0), ~AtomItem(StrAtom(~"bar")));
                assert_eq!(items.get(1).is_atom(), true);
                assert_eq!(*items.get(1), ~AtomItem(IntAtom(12)));
                assert_eq!(items.get(2).is_atom(), true);
                assert_eq!(*items.get(2), ~AtomItem(IntAtom(45)));
            },
            _ => fail!("got back an atom, it seems")
        }
    }
    #[test]
    fn should_parse_tokens_consisting_of_a_list_of_atoms_and_a_nested_list() {
        let tokens = &mut tokenize(~"((2 3) bar 12 (hee (hah)))");
        let parsed_item = read(tokens);
        assert_eq!(parsed_item.is_atom(), false);
        match parsed_item {
            ListItem(items) => {
                let items_len = items.len();
                assert!(4 == items_len);
                match *items.get(0) {
                    ~ListItem(ref items) => {
                        assert_eq!(items.len(), 2);
                        assert_eq!(*items.get(0), ~AtomItem(IntAtom(2)));
                        assert_eq!(*items.get(1), ~AtomItem(IntAtom(3)));
                    },
                    _ => fail!("shoulda got a list")
                }
                assert_eq!(*items.get(1), ~AtomItem(StrAtom(~"bar")));
                assert_eq!(*items.get(2), ~AtomItem(IntAtom(12)));
                match *items.get(3) {
                    ~ListItem(ref items) => {
                        assert_eq!(items.len(), 2);
                        assert_eq!(*items.get(0), ~AtomItem(StrAtom(~"hee")));
                        match *items.get(1) {
                            ~ListItem(ref items) => {
                                assert_eq!(items.len(), 1);
                                assert_eq!(*items.get(0), ~AtomItem(StrAtom(~"hah")));
                            },
                            _ => fail!("shoulda got a list")
                        }
                    },
                    _ => fail!("shoulda got a list")
                }
            },
            _ => fail!("got back an atom, it seems")
        }
    }
}
<commit_msg>reworking some of the terminology of parsing primitives<commit_after>// Copyright 2013-2014 Jeffery Olson
//
// Licensed under the 3-Clause BSD License, see LICENSE.txt
// at the top-level of this repository.
// This file may not be copied, modified, or distributed
// except according to those terms.
#![crate_id="http://olsonjeffery.github.io#schemers:0.0.1"]
#![desc = "Simple Scheme Interpreter"]
#![license = "3-Clause BSD"]

use std::from_str::FromStr;

// this is starting out as a straight port of Peter Norvig's
// lis.py (the first iteration) to Rust

#[cfg(not(test))]
fn main() {
    use std::os::args;
    let args: Vec<~str> = args().move_iter().skip(1).collect();
    if args.len() == 0 {
        fail!("no program provided");
    }
    let program: ~str = args.move_iter()
        .fold(~"", |memo, arg| memo + arg + " ").trim().to_owned();
    let tokens = &mut tokenize(program);
    println!("{:?}", read(tokens));
}

// parser impl
fn pad_input(input: ~str) -> ~str {
    input.replace("(", " ( ").replace(")", " ) ")
}

fn tokenize(input: ~str) -> Vec<~str> {
    pad_input(input).split_str(" ")
        .filter(|i| *i != "").map(|i| i.to_owned()).collect()
}

#[deriving(Eq, Show)]
pub enum ParseItem {
    Atom(AtomType),
    List(Vec<~ParseItem>)
}
impl ParseItem {
    pub fn new_atom(input: ~str) -> ParseItem {
        let first_char = input.char_at(0);
        match first_char {
            '0' | '1' | '2' | '3' | '4' | '5' |
            '6' | '7' | '8' | '9' => {
                let val = FromStr::from_str(input);
                match val {
                    Some(val) => Atom(Integer(val)),
                    None => fail!("Cannot parse number-like input of: {}", input)
                }
            },
            _ => Atom(Symbol(input))
        }
    }
}

#[deriving(Eq, Show)]
pub enum AtomType {
    Symbol(~str),
    Integer(int)
}

impl ParseItem {
    pub fn is_atom(&self) -> bool {
        match *self {
            Atom(_) => true,
            _ => false
        }
    }
}

fn read(tokens: &mut Vec<~str>) -> ParseItem {
    let current_token =
        tokens.shift().expect("calling read() w/ empty token list; shouldn't happen");
    match current_token {
        ref x if *x == ~"(" => {
            let mut list = Vec::new();
            while *tokens.get(0) != ~")" {
                list.push(box read(tokens));
            }
            tokens.shift();
            List(list)
        },
        ref x if *x == ~")" => fail!("hit ) token; shouldn't happen"),
        x => ParseItem::new_atom(x)
    }
}

#[cfg(test)]
mod parser_test {
    use super::{pad_input, tokenize, read, Atom, List, Symbol, Integer};

    #[test]
    fn pad_input_should_insert_spaces_before_and_after_parens() {
        assert_eq!(pad_input(~"(x 1 2 3)"), ~" ( x 1 2 3 ) ");
    }

    #[test]
    fn tokenize_string_into_tokens() {
        let tokens = tokenize(~"(foo 12 3)");
        assert_eq!(tokens.len(), 5);
        assert_eq!(tokens.get(0).to_owned(), ~"(");
        assert_eq!(tokens.get(1).to_owned(), ~"foo");
        assert_eq!(tokens.get(2).to_owned(), ~"12");
        assert_eq!(tokens.get(3).to_owned(), ~"3");
        assert_eq!(tokens.get(4).to_owned(), ~")");
    }

    #[test]
    fn should_parse_tokens_consisting_of_a_str_atom_and_convert_it_to_a_parse_item() {
        let tokens = &mut tokenize(~"bar");
        let parsed_item = read(tokens);
        println!("{:?}", parsed_item);
        match parsed_item {
            Atom(Symbol(val)) => {
                assert_eq!(val, ~"bar")
            },
            _ => assert!(false)
        }
    }
    #[test]
    fn should_parse_tokens_consisting_of_an_int_atom_and_convert_it_to_a_parse_item() {
        let tokens = &mut tokenize(~"42");
        let parsed_item = read(tokens);
        println!("{:?}", parsed_item);
        match parsed_item {
            Atom(Integer(val)) => {
                assert_eq!(val, 42)
            },
            _ => assert!(false)
        }
    }

    #[test]
    fn should_parse_tokens_consisting_of_a_list_of_atoms_and_parse_it() {
        let tokens = &mut tokenize(~"(bar 12 45)");
        let parsed_item = read(tokens);
        assert_eq!(parsed_item.is_atom(), false);
        match parsed_item {
            List(items) => {
                let items_len = items.len();
                assert!(3 == items_len);
                assert_eq!(items.get(0).is_atom(), true);
                assert_eq!(*items.get(0), ~Atom(Symbol(~"bar")));
                assert_eq!(items.get(1).is_atom(), true);
                assert_eq!(*items.get(1), ~Atom(Integer(12)));
                assert_eq!(items.get(2).is_atom(), true);
                assert_eq!(*items.get(2), ~Atom(Integer(45)));
            },
            _ => fail!("got back an atom, it seems")
        }
    }
    #[test]
    fn should_parse_tokens_consisting_of_a_list_of_atoms_and_a_nested_list() {
        let tokens = &mut tokenize(~"((2 3) bar 12 (hee (hah)))");
        let parsed_item = read(tokens);
        assert_eq!(parsed_item.is_atom(), false);
        match parsed_item {
            List(items) => {
                let items_len = items.len();
                assert!(4 == items_len);
                match *items.get(0) {
                    ~List(ref items) => {
                        assert_eq!(items.len(), 2);
                        assert_eq!(*items.get(0), ~Atom(Integer(2)));
                        assert_eq!(*items.get(1), ~Atom(Integer(3)));
                    },
                    _ => fail!("shoulda got a list")
                }
                assert_eq!(*items.get(1), ~Atom(Symbol(~"bar")));
                assert_eq!(*items.get(2), ~Atom(Integer(12)));
                match *items.get(3) {
                    ~List(ref items) => {
                        assert_eq!(items.len(), 2);
                        assert_eq!(*items.get(0), ~Atom(Symbol(~"hee")));
                        match *items.get(1) {
                            ~List(ref items) => {
                                assert_eq!(items.len(), 1);
                                assert_eq!(*items.get(0), ~Atom(Symbol(~"hah")));
                            },
                            _ => fail!("shoulda got a list")
                        }
                    },
                    _ => fail!("shoulda got a list")
                }
            },
            _ => fail!("got back an atom, it seems")
        }
    }
}
<|endoftext|>


<commit_before>
// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! LookupHost result from a resolution with a Resolver

use std::io;
use std::mem;
use std::net::IpAddr;
use std::slice::Iter;

use futures::{Async, future, Future, Poll, task};

use trust_dns::client::ClientHandle;
use trust_dns::error::ClientError;
use trust_dns::op::Message;
use trust_dns::rr::{DNSClass, Name, RData, RecordType};

use config::LookupIpStrategy;

/// Result of a DNS query when querying for A or AAAA records.
#[derive(Debug)]
pub struct LookupIp {
    ips: Vec<IpAddr>,
}

impl LookupIp {
    fn new(ips: Vec<IpAddr>) -> Self {
        LookupIp { ips }
    }

    /// Returns a borrowed iterator of the returned IPs
    pub fn iter(&self) -> LookupIpIter {
        LookupIpIter(self.ips.iter())
    }
}

impl Iterator for LookupIp {
    type Item = IpAddr;

    fn next(&mut self) -> Option<Self::Item> {
        self.ips.pop()
    }
}

/// Borrowed view of set of IPs returned from a LookupIp
pub struct LookupIpIter<'a>(Iter<'a, IpAddr>);

impl<'a> Iterator for LookupIpIter<'a> {
    type Item = &'a IpAddr;

    fn next(&mut self) -> Option<Self::Item> {
        self.0.next()
    }
}

/// The Future returned from ResolverFuture when performing an A or AAAA lookup.
pub struct LookupIpFuture {
    future: Box<Future<Item = LookupIp, Error = io::Error>>,
}

impl LookupIpFuture {
    pub(crate) fn lookup<C: ClientHandle>(
        host: &str,
        strategy: LookupIpStrategy,
        client: &mut C,
    ) -> Self {
        let name = match Name::parse(host, None) {
            Ok(name) => name,
            Err(err) => {
                return LookupIpFuture { future: Box::new(future::err(io::Error::from(err))) }
            }
        };

        let query = LookupIpState::lookup(name, strategy, client);
        LookupIpFuture { future: Box::new(query) }
    }
}

impl Future for LookupIpFuture {
    type Item = LookupIp;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        self.future.poll()
    }
}

// TODO: maximum recursion on CNAME, etc, chains...
// struct LookupStack(Vec<Query>);

// impl LookupStack {
//     // pushes the Query onto the stack, and returns a reference. An error will be returned
//     fn push(&mut self, query: Query) -> io::Result<&Query> {
//         if self.0.contains(&query) {
//             return Err(io::Error::new(io::ErrorKind::Other, "circular CNAME or other recursion"));
//         }

//         self.0.push(query);
//         Ok(self.0.last().unwrap())
//     }
// }

enum LookupIpState {
    Query(Box<Future<Item = Vec<IpAddr>, Error = ClientError>>),
    Fin(Vec<IpAddr>),
}

impl LookupIpState {
    pub fn lookup<C: ClientHandle>(name: Name, strategy: LookupIpStrategy, client: &mut C) -> Self {
        let query_future = lookup(name, strategy, client);

        LookupIpState::Query(query_future)
    }

    fn transition_query(&mut self, ips: Vec<IpAddr>) {
        assert!(if let LookupIpState::Query(_) = *self {
            true
        } else {
            false
        });

        // transition
        mem::replace(self, LookupIpState::Fin(ips));
    }
}

impl Future for LookupIpState {
    type Item = LookupIp;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        // first transition any polling that is needed (mutable refs...)
        let poll;
        match *self {
            LookupIpState::Query(ref mut query) => {
                poll = query.poll().map_err(|e| e.into());
                match poll {
                    Ok(Async::NotReady) => {
                        return Ok(Async::NotReady);
                    }
                    Ok(Async::Ready(_)) => (), // handled in next match
                    Err(e) => {
                        return Err(e);
                    }
                }
            }
            LookupIpState::Fin(ref mut ips) => {
                let ips = mem::replace(ips, Vec::<IpAddr>::new());
                let ips = LookupIp::new(ips);
                return Ok(Async::Ready(ips));
            }
        }

        // getting here means there are Aync::Ready available.
        match *self {
            LookupIpState::Query(_) => {
                match poll {
                    Ok(Async::Ready(ips)) => self.transition_query(ips),
                    _ => panic!("should have returned earlier"),
                }
            }
            LookupIpState::Fin(_) => panic!("should have returned earlier"),
        }

        task::current().notify(); // yield
        Ok(Async::NotReady)
    }
}

fn lookup<C: ClientHandle>(
    name: Name,
    strategy: LookupIpStrategy,
    client: &mut C,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    match strategy {
        LookupIpStrategy::Ipv4Only => ipv4_only(name, client),
        LookupIpStrategy::Ipv6Only => ipv6_only(name, client),
        LookupIpStrategy::Ipv4AndIpv6 => ipv4_and_ipv6(name, client),
        LookupIpStrategy::Ipv6thenIpv4 => unimplemented!(),
        LookupIpStrategy::Ipv4thenIpv6 => unimplemented!(),
    }
}

fn map_message_to_ipaddr(mut message: Message) -> Vec<IpAddr> {
    message
        .take_answers()
        .iter()
        .filter_map(|r| match *r.rdata() {
            RData::A(ipaddr) => Some(IpAddr::V4(ipaddr)),
            RData::AAAA(ipaddr) => Some(IpAddr::V6(ipaddr)),
            _ => None,
        })
        .collect()
}

/// queries only for A records
fn ipv4_only<C: ClientHandle>(
    name: Name,
    client: &mut C,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    Box::new(client.query(name, DNSClass::IN, RecordType::A).map(
        map_message_to_ipaddr,
    ))
}

fn ipv6_only<C: ClientHandle>(
    name: Name,
    client: &mut C,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    Box::new(client.query(name, DNSClass::IN, RecordType::AAAA).map(
        map_message_to_ipaddr,
    ))
}

fn ipv4_and_ipv6<C: ClientHandle>(
    name: Name,
    client: &mut C,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    Box::new(
        client
            .query(name.clone(), DNSClass::IN, RecordType::A)
            .map(map_message_to_ipaddr)
            .select(client.query(name, DNSClass::IN, RecordType::AAAA).map(
                map_message_to_ipaddr,
            ))
            .then(|sel_res| {
                match sel_res {
                    // Some ips returned, get the other record result, or else just return record
                    Ok((mut ips, remaining_query)) => {
                        Box::new(remaining_query.then(move |query_res| match query_res {
                            /// join AAAA and A results
                            Ok(mut rem_ips) => {
                                rem_ips.append(&mut ips);
                                future::ok(rem_ips)
                            }
                            // One failed, just return the other
                            Err(_) => future::ok(ips),
                        })) as
                            // This cast is to resolve a comilation error, not sure of it's necessity
                            Box<Future<Item = Vec<IpAddr>, Error = ClientError>>
                    }

                    // One failed, just return the other
                    Err((_, remaining_query)) => Box::new(remaining_query),
                }
            }),
    )
}

// TODO: build some non-network tests which test all variants of the Strategies...<commit_msg>tests for all strategies<commit_after>
// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! LookupHost result from a resolution with a Resolver

use std::io;
use std::mem;
use std::net::IpAddr;
use std::slice::Iter;

use futures::{Async, future, Future, Poll, task};

use trust_dns::client::ClientHandle;
use trust_dns::error::ClientError;
use trust_dns::op::Message;
use trust_dns::rr::{DNSClass, Name, RData, RecordType};

use config::LookupIpStrategy;

/// Result of a DNS query when querying for A or AAAA records.
#[derive(Debug)]
pub struct LookupIp {
    ips: Vec<IpAddr>,
}

impl LookupIp {
    fn new(ips: Vec<IpAddr>) -> Self {
        LookupIp { ips }
    }

    /// Returns a borrowed iterator of the returned IPs
    pub fn iter(&self) -> LookupIpIter {
        LookupIpIter(self.ips.iter())
    }
}

impl Iterator for LookupIp {
    type Item = IpAddr;

    fn next(&mut self) -> Option<Self::Item> {
        self.ips.pop()
    }
}

/// Borrowed view of set of IPs returned from a LookupIp
pub struct LookupIpIter<'a>(Iter<'a, IpAddr>);

impl<'a> Iterator for LookupIpIter<'a> {
    type Item = &'a IpAddr;

    fn next(&mut self) -> Option<Self::Item> {
        self.0.next()
    }
}

/// The Future returned from ResolverFuture when performing an A or AAAA lookup.
pub struct LookupIpFuture {
    future: Box<Future<Item = LookupIp, Error = io::Error>>,
}

impl LookupIpFuture {
    pub(crate) fn lookup<C: ClientHandle + 'static>(
        host: &str,
        strategy: LookupIpStrategy,
        client: &mut C,
    ) -> Self {
        let name = match Name::parse(host, None) {
            Ok(name) => name,
            Err(err) => {
                return LookupIpFuture { future: Box::new(future::err(io::Error::from(err))) }
            }
        };

        let query = LookupIpState::lookup(name, strategy, client);
        LookupIpFuture { future: Box::new(query) }
    }
}

impl Future for LookupIpFuture {
    type Item = LookupIp;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        self.future.poll()
    }
}

// TODO: maximum recursion on CNAME, etc, chains...
// struct LookupStack(Vec<Query>);

// impl LookupStack {
//     // pushes the Query onto the stack, and returns a reference. An error will be returned
//     fn push(&mut self, query: Query) -> io::Result<&Query> {
//         if self.0.contains(&query) {
//             return Err(io::Error::new(io::ErrorKind::Other, "circular CNAME or other recursion"));
//         }

//         self.0.push(query);
//         Ok(self.0.last().unwrap())
//     }
// }

enum LookupIpState {
    Query(Box<Future<Item = Vec<IpAddr>, Error = ClientError>>),
    Fin(Vec<IpAddr>),
}

impl LookupIpState {
    pub fn lookup<C: ClientHandle + 'static>(
        name: Name,
        strategy: LookupIpStrategy,
        client: &mut C,
    ) -> Self {
        let query_future = lookup(name, strategy, client);

        LookupIpState::Query(query_future)
    }

    fn transition_query(&mut self, ips: Vec<IpAddr>) {
        assert!(if let LookupIpState::Query(_) = *self {
            true
        } else {
            false
        });

        // transition
        mem::replace(self, LookupIpState::Fin(ips));
    }
}

impl Future for LookupIpState {
    type Item = LookupIp;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        // first transition any polling that is needed (mutable refs...)
        let poll;
        match *self {
            LookupIpState::Query(ref mut query) => {
                poll = query.poll().map_err(|e| e.into());
                match poll {
                    Ok(Async::NotReady) => {
                        return Ok(Async::NotReady);
                    }
                    Ok(Async::Ready(_)) => (), // handled in next match
                    Err(e) => {
                        return Err(e);
                    }
                }
            }
            LookupIpState::Fin(ref mut ips) => {
                let ips = mem::replace(ips, Vec::<IpAddr>::new());
                let ips = LookupIp::new(ips);
                return Ok(Async::Ready(ips));
            }
        }

        // getting here means there are Aync::Ready available.
        match *self {
            LookupIpState::Query(_) => {
                match poll {
                    Ok(Async::Ready(ips)) => self.transition_query(ips),
                    _ => panic!("should have returned earlier"),
                }
            }
            LookupIpState::Fin(_) => panic!("should have returned earlier"),
        }

        task::current().notify(); // yield
        Ok(Async::NotReady)
    }
}

fn lookup<C: ClientHandle + 'static>(
    name: Name,
    strategy: LookupIpStrategy,
    client: &mut C,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    match strategy {
        LookupIpStrategy::Ipv4Only => ipv4_only(name, client),
        LookupIpStrategy::Ipv6Only => ipv6_only(name, client),
        LookupIpStrategy::Ipv4AndIpv6 => ipv4_and_ipv6(name, client),
        LookupIpStrategy::Ipv6thenIpv4 => ipv6_then_ipv4(name, client),
        LookupIpStrategy::Ipv4thenIpv6 => ipv4_then_ipv6(name, client),
    }
}

fn map_message_to_ipaddr(mut message: Message) -> Vec<IpAddr> {
    message
        .take_answers()
        .iter()
        .filter_map(|r| match *r.rdata() {
            RData::A(ipaddr) => Some(IpAddr::V4(ipaddr)),
            RData::AAAA(ipaddr) => Some(IpAddr::V6(ipaddr)),
            _ => None,
        })
        .collect()
}

/// queries only for A records
fn ipv4_only<C: ClientHandle>(
    name: Name,
    client: &mut C,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    Box::new(client.query(name, DNSClass::IN, RecordType::A).map(
        map_message_to_ipaddr,
    ))
}

/// queries only for AAAA records
fn ipv6_only<C: ClientHandle>(
    name: Name,
    client: &mut C,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    Box::new(client.query(name, DNSClass::IN, RecordType::AAAA).map(
        map_message_to_ipaddr,
    ))
}

/// queries only for A and AAAA in parallel
fn ipv4_and_ipv6<C: ClientHandle>(
    name: Name,
    client: &mut C,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    Box::new(
        client
            .query(name.clone(), DNSClass::IN, RecordType::A)
            .map(map_message_to_ipaddr)
            .select(client.query(name, DNSClass::IN, RecordType::AAAA).map(
                map_message_to_ipaddr,
            ))
            .then(|sel_res| {
                match sel_res {
                    // Some ips returned, get the other record result, or else just return record
                    Ok((mut ips, remaining_query)) => {
                        Box::new(remaining_query.then(move |query_res| match query_res {
                            /// join AAAA and A results
                            Ok(mut rem_ips) => {
                                rem_ips.append(&mut ips);
                                future::ok(rem_ips)
                            }
                            // One failed, just return the other
                            Err(_) => future::ok(ips),
                        })) as
                            // This cast is to resolve a comilation error, not sure of it's necessity
                            Box<Future<Item = Vec<IpAddr>, Error = ClientError>>
                    }

                    // One failed, just return the other
                    Err((_, remaining_query)) => Box::new(remaining_query),
                }
            }),
    )
}

/// queries only for AAAA and on no results queries for A
fn ipv6_then_ipv4<C: ClientHandle + 'static>(
    name: Name,
    client: &mut C,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    rt_then_swap(name, client, RecordType::AAAA, RecordType::A)
}

/// queries only for A and on no results queries for AAAA
fn ipv4_then_ipv6<C: ClientHandle + 'static>(
    name: Name,
    client: &mut C,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    rt_then_swap(name, client, RecordType::A, RecordType::AAAA)
}

/// queries only for first_type and on no results queries for second_type
fn rt_then_swap<C: ClientHandle + 'static>(
    name: Name,
    client: &mut C,
    first_type: RecordType,
    second_type: RecordType,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    let mut or_client = client.clone();
    Box::new(
        client
            .query(name.clone(), DNSClass::IN, first_type)
            .map(map_message_to_ipaddr)
            .then(move |res| {
                match res {
                    Ok(ips) => {
                        println!("ips");
                        if ips.is_empty() {
                            println!("ips, are empty");

                            // no ips returns, NXDomain or Otherwise, doesn't matter
                            Box::new(
                                or_client
                                    .query(name.clone(), DNSClass::IN, second_type)
                                    .map(map_message_to_ipaddr),
                            ) as
                                Box<Future<Item = Vec<IpAddr>, Error = ClientError>>
                        } else {
                            Box::new(future::ok(ips)) as
                                Box<Future<Item = Vec<IpAddr>, Error = ClientError>>
                        }
                    }
                    Err(_) => {
                        Box::new(
                            or_client
                                .query(name.clone(), DNSClass::IN, second_type)
                                .map(map_message_to_ipaddr),
                        )
                    }
                }
            }),
    )
}

// TODO: need to add some Err(result) tests...
#[cfg(test)]
mod tests {
    use std::io;
    use std::mem;
    use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
    use std::slice::Iter;
    use std::sync::{Arc, Mutex};

    use futures::{Async, future, Future, Poll, task};

    use trust_dns::client::ClientHandle;
    use trust_dns::error::ClientError;
    use trust_dns::op::Message;
    use trust_dns::rr::{DNSClass, Name, Record, RData, RecordType};

    use config::LookupIpStrategy;

    use super::*;

    #[derive(Clone)]
    struct MockClientHandle {
        messages: Arc<Mutex<Vec<Message>>>,
    }

    impl ClientHandle for MockClientHandle {
        fn send(&mut self, message: Message) -> Box<Future<Item = Message, Error = ClientError>> {
            Box::new(future::ok(self.messages.lock().unwrap().pop().unwrap_or(
                Message::new(),
            )))
        }
    }

    fn v4_message() -> Message {
        let mut message = Message::new();
        message.insert_answers(vec![
            Record::from_rdata(
                Name::root(),
                0,
                RecordType::A,
                RData::A(Ipv4Addr::new(127, 0, 0, 1))
            ),
        ]);
        message
    }

    fn v6_message() -> Message {
        let mut message = Message::new();
        message.insert_answers(vec![
            Record::from_rdata(
                Name::root(),
                0,
                RecordType::AAAA,
                RData::AAAA(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1))
            ),
        ]);
        message
    }

    fn mock(messages: Vec<Message>) -> MockClientHandle {
        MockClientHandle { messages: Arc::new(Mutex::new(messages)) }
    }

    #[test]
    fn test_ipv4_only_strategy() {
        assert_eq!(
            ipv4_only(Name::root(), &mut mock(vec![v4_message()]))
                .wait()
                .unwrap(),
            vec![Ipv4Addr::new(127, 0, 0, 1)]
        );
    }

    #[test]
    fn test_ipv6_only_strategy() {
        assert_eq!(
            ipv6_only(Name::root(), &mut mock(vec![v6_message()]))
                .wait()
                .unwrap(),
            vec![Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)]
        );
    }

    #[test]
    fn test_ipv4_and_ipv6_strategy() {
        // both succeed
        assert_eq!(
            ipv4_and_ipv6(Name::root(), &mut mock(vec![v4_message(), v6_message()]))
                .wait()
                .unwrap(),
            vec![
                IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
                IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)),
            ]
        );

        // only ipv4 available
        assert_eq!(
            ipv4_and_ipv6(Name::root(), &mut mock(vec![v4_message()]))
                .wait()
                .unwrap(),
            vec![IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))]
        );

        // only ipv6 available
        assert_eq!(
            ipv4_and_ipv6(Name::root(), &mut mock(vec![v6_message()]))
                .wait()
                .unwrap(),
            vec![IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1))]
        );
    }

    #[test]
    fn test_ipv6_then_ipv4_strategy() {
        // ipv6 first
        assert_eq!(
            ipv6_then_ipv4(Name::root(), &mut mock(vec![v6_message()]))
                .wait()
                .unwrap(),
            vec![Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)]
        );

        // nothing then ipv4
        assert_eq!(
            ipv6_then_ipv4(Name::root(), &mut mock(vec![v4_message(), Message::new()]))
                .wait()
                .unwrap(),
            vec![Ipv4Addr::new(127, 0, 0, 1)]
        );
    }

    #[test]
    fn test_ipv4_then_ipv6_strategy() {
        // ipv6 first
        assert_eq!(
            ipv4_then_ipv6(Name::root(), &mut mock(vec![v4_message()]))
                .wait()
                .unwrap(),
            vec![Ipv4Addr::new(127, 0, 0, 1)]
        );

        // nothing then ipv6
        assert_eq!(
            ipv4_then_ipv6(Name::root(), &mut mock(vec![v6_message(), Message::new()]))
                .wait()
                .unwrap(),
            vec![Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)]
        );
    }
}<|endoftext|>


<commit_before>extern crate libsqlite3_sys as ffi;

use std::collections::HashMap;
use std::os::raw as libc;
use std::ptr::NonNull;
use std::{slice, str};

use crate::row::*;
use crate::sqlite::Sqlite;

#[allow(missing_debug_implementations, missing_copy_implementations)]
pub struct SqliteValue {
    value: ffi::sqlite3_value,
}

pub struct SqliteRow {
    stmt: NonNull<ffi::sqlite3_stmt>,
    next_col_index: libc::c_int,
}

impl SqliteValue {
    #[allow(clippy::new_ret_no_self)]
    pub(crate) unsafe fn new<'a>(inner: *mut ffi::sqlite3_value) -> Option<&'a Self> {
        (inner as *const _ as *const Self).as_ref().and_then(|v| {
            if v.is_null() {
                None
            } else {
                Some(v)
            }
        })
    }

    pub fn read_text(&self) -> &str {
        unsafe {
            let ptr = ffi::sqlite3_value_text(self.value());
            let len = ffi::sqlite3_value_bytes(self.value());
            let bytes = slice::from_raw_parts(ptr as *const u8, len as usize);
            // The string is guaranteed to be utf8 according to
            // https://www.sqlite.org/c3ref/value_blob.html
            str::from_utf8_unchecked(bytes)
        }
    }

    pub fn read_blob(&self) -> &[u8] {
        unsafe {
            let ptr = ffi::sqlite3_value_blob(self.value());
            let len = ffi::sqlite3_value_bytes(self.value());
            slice::from_raw_parts(ptr as *const u8, len as usize)
        }
    }

    pub fn read_integer(&self) -> i32 {
        unsafe { ffi::sqlite3_value_int(self.value()) as i32 }
    }

    pub fn read_long(&self) -> i64 {
        unsafe { ffi::sqlite3_value_int64(self.value()) as i64 }
    }

    pub fn read_double(&self) -> f64 {
        unsafe { ffi::sqlite3_value_double(self.value()) as f64 }
    }

    pub fn is_null(&self) -> bool {
        let tpe = unsafe { ffi::sqlite3_value_type(self.value()) };
        tpe == ffi::SQLITE_NULL
    }

    fn value(&self) -> *mut ffi::sqlite3_value {
        &self.value as *const _ as _
    }
}

impl SqliteRow {
    pub(crate) fn new(inner_statement: NonNull<ffi::sqlite3_stmt>) -> Self {
        SqliteRow {
            stmt: inner_statement,
            next_col_index: 0,
        }
    }

    pub fn into_named<'a>(self, indices: &'a HashMap<&'a str, usize>) -> SqliteNamedRow<'a> {
        SqliteNamedRow {
            stmt: self.stmt,
            column_indices: indices,
        }
    }
}

impl Row<Sqlite> for SqliteRow {
    fn take(&mut self) -> Option<&SqliteValue> {
        let col_index = self.next_col_index;
        self.next_col_index += 1;

        unsafe {
            let ptr = ffi::sqlite3_column_value(self.stmt.as_ptr(), col_index);
            SqliteValue::new(ptr)
        }
    }

    fn next_is_null(&self, count: usize) -> bool {
        (0..count).all(|i| {
            let idx = self.next_col_index + i as libc::c_int;
            let tpe = unsafe { ffi::sqlite3_column_type(self.stmt.as_ptr(), idx) };
            tpe == ffi::SQLITE_NULL
        })
    }

    fn column_name(&self) -> Option<&str> {
        unsafe {
            let ptr = if self.next_col_index == 0 {
                ffi::sqlite3_column_name(self.stmt.as_ptr(), 0)
            } else {
                ffi::sqlite3_column_name(self.stmt.as_ptr(), self.next_col_index - 1)
            };
            Some(
                std::ffi::CStr::from_ptr(ptr)
                    .to_str()
                    .expect(
                        "The Sqlite documentation states that this is UTF8. \
                         If you see this error message something has gone \
                         horribliy wrong. Please open an issue at the \
                         diesel repository."),
            )
        }
    }

    fn column_count(&self) -> usize {
        unsafe { ffi::sqlite3_column_count(self.stmt.as_ptr()) as usize }
    }
}

pub struct SqliteNamedRow<'a> {
    stmt: NonNull<ffi::sqlite3_stmt>,
    column_indices: &'a HashMap<&'a str, usize>,
}

impl<'a> NamedRow<Sqlite> for SqliteNamedRow<'a> {
    fn index_of(&self, column_name: &str) -> Option<usize> {
        self.column_indices.get(column_name).cloned()
    }

    fn get_raw_value(&self, idx: usize) -> Option<&SqliteValue> {
        unsafe {
            let ptr = ffi::sqlite3_column_value(self.stmt.as_ptr(), idx as libc::c_int);
            SqliteValue::new(ptr)
        }
    }
}
<commit_msg>Run rustfmt<commit_after>extern crate libsqlite3_sys as ffi;

use std::collections::HashMap;
use std::os::raw as libc;
use std::ptr::NonNull;
use std::{slice, str};

use crate::row::*;
use crate::sqlite::Sqlite;

#[allow(missing_debug_implementations, missing_copy_implementations)]
pub struct SqliteValue {
    value: ffi::sqlite3_value,
}

pub struct SqliteRow {
    stmt: NonNull<ffi::sqlite3_stmt>,
    next_col_index: libc::c_int,
}

impl SqliteValue {
    #[allow(clippy::new_ret_no_self)]
    pub(crate) unsafe fn new<'a>(inner: *mut ffi::sqlite3_value) -> Option<&'a Self> {
        (inner as *const _ as *const Self).as_ref().and_then(|v| {
            if v.is_null() {
                None
            } else {
                Some(v)
            }
        })
    }

    pub fn read_text(&self) -> &str {
        unsafe {
            let ptr = ffi::sqlite3_value_text(self.value());
            let len = ffi::sqlite3_value_bytes(self.value());
            let bytes = slice::from_raw_parts(ptr as *const u8, len as usize);
            // The string is guaranteed to be utf8 according to
            // https://www.sqlite.org/c3ref/value_blob.html
            str::from_utf8_unchecked(bytes)
        }
    }

    pub fn read_blob(&self) -> &[u8] {
        unsafe {
            let ptr = ffi::sqlite3_value_blob(self.value());
            let len = ffi::sqlite3_value_bytes(self.value());
            slice::from_raw_parts(ptr as *const u8, len as usize)
        }
    }

    pub fn read_integer(&self) -> i32 {
        unsafe { ffi::sqlite3_value_int(self.value()) as i32 }
    }

    pub fn read_long(&self) -> i64 {
        unsafe { ffi::sqlite3_value_int64(self.value()) as i64 }
    }

    pub fn read_double(&self) -> f64 {
        unsafe { ffi::sqlite3_value_double(self.value()) as f64 }
    }

    pub fn is_null(&self) -> bool {
        let tpe = unsafe { ffi::sqlite3_value_type(self.value()) };
        tpe == ffi::SQLITE_NULL
    }

    fn value(&self) -> *mut ffi::sqlite3_value {
        &self.value as *const _ as _
    }
}

impl SqliteRow {
    pub(crate) fn new(inner_statement: NonNull<ffi::sqlite3_stmt>) -> Self {
        SqliteRow {
            stmt: inner_statement,
            next_col_index: 0,
        }
    }

    pub fn into_named<'a>(self, indices: &'a HashMap<&'a str, usize>) -> SqliteNamedRow<'a> {
        SqliteNamedRow {
            stmt: self.stmt,
            column_indices: indices,
        }
    }
}

impl Row<Sqlite> for SqliteRow {
    fn take(&mut self) -> Option<&SqliteValue> {
        let col_index = self.next_col_index;
        self.next_col_index += 1;

        unsafe {
            let ptr = ffi::sqlite3_column_value(self.stmt.as_ptr(), col_index);
            SqliteValue::new(ptr)
        }
    }

    fn next_is_null(&self, count: usize) -> bool {
        (0..count).all(|i| {
            let idx = self.next_col_index + i as libc::c_int;
            let tpe = unsafe { ffi::sqlite3_column_type(self.stmt.as_ptr(), idx) };
            tpe == ffi::SQLITE_NULL
        })
    }

    fn column_name(&self) -> Option<&str> {
        unsafe {
            let ptr = if self.next_col_index == 0 {
                ffi::sqlite3_column_name(self.stmt.as_ptr(), 0)
            } else {
                ffi::sqlite3_column_name(self.stmt.as_ptr(), self.next_col_index - 1)
            };
            Some(std::ffi::CStr::from_ptr(ptr).to_str().expect(
                "The Sqlite documentation states that this is UTF8. \
                 If you see this error message something has gone \
                 horribliy wrong. Please open an issue at the \
                 diesel repository.",
            ))
        }
    }

    fn column_count(&self) -> usize {
        unsafe { ffi::sqlite3_column_count(self.stmt.as_ptr()) as usize }
    }
}

pub struct SqliteNamedRow<'a> {
    stmt: NonNull<ffi::sqlite3_stmt>,
    column_indices: &'a HashMap<&'a str, usize>,
}

impl<'a> NamedRow<Sqlite> for SqliteNamedRow<'a> {
    fn index_of(&self, column_name: &str) -> Option<usize> {
        self.column_indices.get(column_name).cloned()
    }

    fn get_raw_value(&self, idx: usize) -> Option<&SqliteValue> {
        unsafe {
            let ptr = ffi::sqlite3_column_value(self.stmt.as_ptr(), idx as libc::c_int);
            SqliteValue::new(ptr)
        }
    }
}
<|endoftext|>


<commit_before>use nom::{self, IResult, Needed};

use std::io::{self, Read};
use std::ptr;
use std::cmp;

use super::StreamProducer;

/// Represent the different kinds of errors.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum ErrorKind {
  IO(io::ErrorKind),
  Incomplete(usize),
  Continue,
  EndOfInput,
  Unknown,
  // Parser Error
  HeaderParser,
  MetadataHeaderParser,
  StreamInfoParser,
  PaddingParser,
  ApplicationParser,
  SeekTableParser,
  VorbisCommentParser,
  CueSheetParser,
  PictureParser,
  UnknownParser,
  BlockingStrategyParser,
  BlockingSampleParser,
  ChannelBitsParser,
  UTF8HeaderParser,
  UTF8BodyParser,
  CRC8Parser,
  FrameFooterParser,
  // Invalid Error
  InvalidBlockType,
  InvalidSyncCode,
  InvalidBlockSample,
  InvalidChannelBits,
  InvalidUTF8,
  InvalidCRC8,
  InvalidCRC16,
  // Not Found
  NotFound,
}

/// Structure that hold a slice of bytes.
pub struct ByteStream<'a> {
  offset: usize,
  bytes: &'a [u8],
}

impl<'a> ByteStream<'a> {
  /// Construct a `ByteStream` based on the passed in byte slice.
  pub fn new(bytes: &'a [u8]) -> Self {
    ByteStream {
      offset: 0,
      bytes: bytes,
    }
  }

  /// Return the number of bytes that haven't been consumed yet.
  #[inline]
  pub fn len(&self) -> usize {
    self.bytes.len() - self.offset
  }

  /// Return true if the stream contains no more bytes.
  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }
}

impl<'a> StreamProducer for ByteStream<'a> {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind> {
    if self.is_empty() {
      return Err(ErrorKind::EndOfInput);
    }

    match f(&self.bytes[self.offset..]) {
      IResult::Done(i, o)    => {
        self.offset += self.len() - i.len();

        Ok(o)
      }
      IResult::Incomplete(n) => {
        let mut needed = self.len();

        if let Needed::Size(size) = n {
          needed = size;
        }

        Err(ErrorKind::Incomplete(needed))
      }
      IResult::Error(e)      => {
        match e {
          nom::Err::Code(k)               |
          nom::Err::Node(k, _)            |
          nom::Err::Position(k, _)        |
          nom::Err::NodePosition(k, _, _) => {
            if let nom::ErrorKind::Custom(kind) = k {
              Err(kind)
            } else {
              Err(ErrorKind::Unknown)
            }
          }
        }
      },
    }
  }
}

// Growable buffer of bytes.
//
// Mainly used to the `ReadStream` structure but can be used seperately for
// manually filling with some `Read` source.
pub struct Buffer {
  data: Vec<u8>,
  filled: usize,
  offset: usize,
}

impl Buffer {
  // Default constructor for `Buffer`
  pub fn new() -> Self {
    Self::with_capacity(1024)
  }

  // Explicitly set the buffer capacity.
  pub fn with_capacity(capacity: usize) -> Self {
    let mut buffer = Vec::with_capacity(capacity);

    unsafe {
      buffer.set_len(capacity);
    }

    Buffer {
      data: buffer,
      filled: 0,
      offset: 0,
    }
  }

  // Return the number of read bytes that haven't been consumed yet.
  #[inline]
  pub fn len(&self) -> usize {
    self.filled - self.offset
  }

  // Return true if buffer contains no more bytes.
  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }

  // The set length of the unlining buffer.
  #[inline]
  pub fn capacity(&self) -> usize {
    self.data.len()
  }

  // Return a reference to the slice of unread bytes.
  pub fn as_slice(&self) -> &[u8] {
    &self.data[self.offset..self.filled]
  }

  // Fill the buffer with bytes from a `Read` source.
  pub fn fill<R: Read>(&mut self, reader: &mut R) -> io::Result<usize> {
    reader.read(&mut self.data[self.filled..]).map(|consumed| {
      self.filled += consumed;

      consumed
    })
  }

  // Resize the current buffer
  //
  // This will only allocate data when the size requests is larger than the
  // current capacity of the buffer, otherwise it moves the currently filled
  // data to the beginning of the buffer.
  pub fn resize(&mut self, size: usize) {
    if size > self.data.capacity() {
      self.data.reserve(size);

      let capacity = self.data.capacity();

      unsafe {
        self.data.set_len(capacity);
      }
    }

    if self.data.len() - self.filled < size  {
      let length  = self.filled - self.offset;
      let mut_ptr = self.data.as_mut_ptr();

      unsafe {
        let offset_ptr  = self.data.as_ptr().offset(self.offset as isize);

        ptr::copy(offset_ptr, mut_ptr, length);
      }

      self.filled -= self.offset;
      self.offset  = 0;
    }
  }

  // Move the offset by the amount of consumed bytes.
  pub fn consume(&mut self, consumed: usize) {
    self.offset += consumed;
  }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum ParserState {
  Incomplete,
  EndOfInput,
}

fn fill<R: Read>(buffer: &mut Buffer, reader: &mut R, needed: usize)
                 -> io::Result<usize> {
  let mut read = 0;

  if buffer.len() < needed {
    buffer.resize(needed);

    while buffer.len() < needed {
      let size_read = try!(buffer.fill(reader));

      if size_read > 0 {
        read += size_read;
      } else {
        break;
      }
    }
  }

  Ok(read)
}

/// Structure that hold a reader for a source of bytes.
pub struct ReadStream<R: Read> {
  reader: R,
  buffer: Buffer,
  needed: usize,
  state: ParserState,
}

impl<R> ReadStream<R> where R: Read {
  /// Constructor for `ReadStream` based on a `Read` source.
  pub fn new(reader: R) -> Self {
    ReadStream {
      reader: reader,
      buffer: Buffer::new(),
      needed: 0,
      state: ParserState::Incomplete,
    }
  }

  // Fill the stream with bytes from a `Read` source.
  fn fill(&mut self) -> io::Result<usize> {
    let needed = cmp::max(1, self.needed);

    fill(&mut self.buffer, &mut self.reader, needed).map(|consumed| {
      if self.buffer.len() < needed {
        self.state = ParserState::EndOfInput;
      }

      consumed
    })
  }
}

fn from_iresult<T>(buffer: &Buffer, result: IResult<&[u8], T, ErrorKind>)
                   -> Result<(usize, T), ErrorKind> {
  match result {
    IResult::Done(i, o)    => Ok((buffer.len() - i.len(), o)),
    IResult::Incomplete(n) => {
      let mut needed = buffer.capacity() + 1024;

      if let Needed::Size(size) = n {
        needed = size;
      }

      Err(ErrorKind::Incomplete(needed))
    }
    IResult::Error(e)      => {
      match e {
        nom::Err::Code(k)               |
        nom::Err::Node(k, _)            |
        nom::Err::Position(k, _)        |
        nom::Err::NodePosition(k, _, _) => {
          if let nom::ErrorKind::Custom(kind) = k {
            Err(kind)
          } else {
            Err(ErrorKind::Unknown)
          }
        }
      }
    },
  }
}

impl<R> StreamProducer for ReadStream<R> where R: Read {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind> {
    if self.state != ParserState::EndOfInput {
      try!(self.fill().map_err(|e| ErrorKind::IO(e.kind())));
    }

    let mut buffer = &mut self.buffer;

    if buffer.is_empty() {
      self.state = ParserState::EndOfInput;

      return Err(ErrorKind::EndOfInput);
    }

    let result = {
      let iresult = f(buffer.as_slice());

      from_iresult(&buffer, iresult)
    };

    match result {
      Ok((consumed, o)) => {
        buffer.consume(consumed);

        Ok(o)
      }
      Err(kind)         => {
        if let ErrorKind::Incomplete(needed) = kind {
          self.needed = needed;

          Err(ErrorKind::Continue)
        } else {
          Err(kind)
        }
      }
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use utility::StreamProducer;
  use nom::{self, IResult};

  #[inline]
  fn be_u32(input: &[u8]) -> IResult<&[u8], u32, ErrorKind> {
    nom::be_u32(input).map_err(to_custom_error!(Unknown))
  }

  #[test]
  fn test_buffer() {
    let mut buffer = Buffer::new();
    let bytes      = b"Hello World";
    let mut reader = &bytes[..];

    assert!(buffer.is_empty());
    assert_eq!(buffer.capacity(), 1024);

    let bytes_read = buffer.fill(&mut reader).unwrap_or(0);
    let bytes_len  = bytes.len();

    assert_eq!(bytes_read, bytes_len);
    assert_eq!(buffer.len(), bytes_len);
    assert_eq!(buffer.as_slice(), bytes);

    buffer.resize(512);
    assert_eq!(buffer.capacity(), 1024);
  }

  #[test]
  fn test_byte_stream() {
    let bytes      = b"Hello World";
    let mut stream = ByteStream::new(bytes);

    assert_eq!(stream.len(), bytes.len());

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444);
    assert_eq!(stream.len(), 7);
  }

  #[test]
  fn test_read_stream() {
    let bytes      = b"Hello World";
    let mut stream = ReadStream::new(&bytes[..]);

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444)
  }
}
<commit_msg>Add documentation for top level parsing<commit_after>use nom::{self, IResult, Needed};

use std::io::{self, Read};
use std::ptr;
use std::cmp;

use super::StreamProducer;

/// Represent the different kinds of errors.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum ErrorKind {
  /// Error from I/O.
  IO(io::ErrorKind),
  /// A parser stopped midway and need more bytes to consume.
  Incomplete(usize),
  /// A parser has completes and there is still more bytes to consume.
  Continue,
  /// A parser has completes and there is no more bytes to consume.
  EndOfInput,
  /// A non-specified error.
  Unknown,
  // Parser Error
  HeaderParser,
  MetadataHeaderParser,
  StreamInfoParser,
  PaddingParser,
  ApplicationParser,
  SeekTableParser,
  VorbisCommentParser,
  CueSheetParser,
  PictureParser,
  UnknownParser,
  BlockingStrategyParser,
  BlockingSampleParser,
  ChannelBitsParser,
  UTF8HeaderParser,
  UTF8BodyParser,
  CRC8Parser,
  FrameFooterParser,
  // Invalid Error
  InvalidBlockType,
  InvalidSyncCode,
  InvalidBlockSample,
  InvalidChannelBits,
  InvalidUTF8,
  InvalidCRC8,
  InvalidCRC16,
  // Not Found
  NotFound,
}

/// Structure that hold a slice of bytes.
pub struct ByteStream<'a> {
  offset: usize,
  bytes: &'a [u8],
}

impl<'a> ByteStream<'a> {
  /// Construct a `ByteStream` based on the passed in byte slice.
  pub fn new(bytes: &'a [u8]) -> Self {
    ByteStream {
      offset: 0,
      bytes: bytes,
    }
  }

  /// Return the number of bytes that haven't been consumed yet.
  #[inline]
  pub fn len(&self) -> usize {
    self.bytes.len() - self.offset
  }

  /// Return true if the stream contains no more bytes.
  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }
}

impl<'a> StreamProducer for ByteStream<'a> {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind> {
    if self.is_empty() {
      return Err(ErrorKind::EndOfInput);
    }

    match f(&self.bytes[self.offset..]) {
      IResult::Done(i, o)    => {
        self.offset += self.len() - i.len();

        Ok(o)
      }
      IResult::Incomplete(n) => {
        let mut needed = self.len();

        if let Needed::Size(size) = n {
          needed = size;
        }

        Err(ErrorKind::Incomplete(needed))
      }
      IResult::Error(e)      => {
        match e {
          nom::Err::Code(k)               |
          nom::Err::Node(k, _)            |
          nom::Err::Position(k, _)        |
          nom::Err::NodePosition(k, _, _) => {
            if let nom::ErrorKind::Custom(kind) = k {
              Err(kind)
            } else {
              Err(ErrorKind::Unknown)
            }
          }
        }
      },
    }
  }
}

// Growable buffer of bytes.
//
// Mainly used to the `ReadStream` structure but can be used seperately for
// manually filling with some `Read` source.
pub struct Buffer {
  data: Vec<u8>,
  filled: usize,
  offset: usize,
}

impl Buffer {
  // Default constructor for `Buffer`
  pub fn new() -> Self {
    Self::with_capacity(1024)
  }

  // Explicitly set the buffer capacity.
  pub fn with_capacity(capacity: usize) -> Self {
    let mut buffer = Vec::with_capacity(capacity);

    unsafe {
      buffer.set_len(capacity);
    }

    Buffer {
      data: buffer,
      filled: 0,
      offset: 0,
    }
  }

  // Return the number of read bytes that haven't been consumed yet.
  #[inline]
  pub fn len(&self) -> usize {
    self.filled - self.offset
  }

  // Return true if buffer contains no more bytes.
  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }

  // The set length of the unlining buffer.
  #[inline]
  pub fn capacity(&self) -> usize {
    self.data.len()
  }

  // Return a reference to the slice of unread bytes.
  pub fn as_slice(&self) -> &[u8] {
    &self.data[self.offset..self.filled]
  }

  // Fill the buffer with bytes from a `Read` source.
  pub fn fill<R: Read>(&mut self, reader: &mut R) -> io::Result<usize> {
    reader.read(&mut self.data[self.filled..]).map(|consumed| {
      self.filled += consumed;

      consumed
    })
  }

  // Resize the current buffer
  //
  // This will only allocate data when the size requests is larger than the
  // current capacity of the buffer, otherwise it moves the currently filled
  // data to the beginning of the buffer.
  pub fn resize(&mut self, size: usize) {
    if size > self.data.capacity() {
      self.data.reserve(size);

      let capacity = self.data.capacity();

      unsafe {
        self.data.set_len(capacity);
      }
    }

    if self.data.len() - self.filled < size  {
      let length  = self.filled - self.offset;
      let mut_ptr = self.data.as_mut_ptr();

      unsafe {
        let offset_ptr  = self.data.as_ptr().offset(self.offset as isize);

        ptr::copy(offset_ptr, mut_ptr, length);
      }

      self.filled -= self.offset;
      self.offset  = 0;
    }
  }

  // Move the offset by the amount of consumed bytes.
  pub fn consume(&mut self, consumed: usize) {
    self.offset += consumed;
  }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum ParserState {
  Incomplete,
  EndOfInput,
}

fn fill<R: Read>(buffer: &mut Buffer, reader: &mut R, needed: usize)
                 -> io::Result<usize> {
  let mut read = 0;

  if buffer.len() < needed {
    buffer.resize(needed);

    while buffer.len() < needed {
      let size_read = try!(buffer.fill(reader));

      if size_read > 0 {
        read += size_read;
      } else {
        break;
      }
    }
  }

  Ok(read)
}

/// Structure that hold a reader for a source of bytes.
pub struct ReadStream<R: Read> {
  reader: R,
  buffer: Buffer,
  needed: usize,
  state: ParserState,
}

impl<R> ReadStream<R> where R: Read {
  /// Constructor for `ReadStream` based on a `Read` source.
  pub fn new(reader: R) -> Self {
    ReadStream {
      reader: reader,
      buffer: Buffer::new(),
      needed: 0,
      state: ParserState::Incomplete,
    }
  }

  // Fill the stream with bytes from a `Read` source.
  fn fill(&mut self) -> io::Result<usize> {
    let needed = cmp::max(1, self.needed);

    fill(&mut self.buffer, &mut self.reader, needed).map(|consumed| {
      if self.buffer.len() < needed {
        self.state = ParserState::EndOfInput;
      }

      consumed
    })
  }
}

fn from_iresult<T>(buffer: &Buffer, result: IResult<&[u8], T, ErrorKind>)
                   -> Result<(usize, T), ErrorKind> {
  match result {
    IResult::Done(i, o)    => Ok((buffer.len() - i.len(), o)),
    IResult::Incomplete(n) => {
      let mut needed = buffer.capacity() + 1024;

      if let Needed::Size(size) = n {
        needed = size;
      }

      Err(ErrorKind::Incomplete(needed))
    }
    IResult::Error(e)      => {
      match e {
        nom::Err::Code(k)               |
        nom::Err::Node(k, _)            |
        nom::Err::Position(k, _)        |
        nom::Err::NodePosition(k, _, _) => {
          if let nom::ErrorKind::Custom(kind) = k {
            Err(kind)
          } else {
            Err(ErrorKind::Unknown)
          }
        }
      }
    },
  }
}

impl<R> StreamProducer for ReadStream<R> where R: Read {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind> {
    if self.state != ParserState::EndOfInput {
      try!(self.fill().map_err(|e| ErrorKind::IO(e.kind())));
    }

    let mut buffer = &mut self.buffer;

    if buffer.is_empty() {
      self.state = ParserState::EndOfInput;

      return Err(ErrorKind::EndOfInput);
    }

    let result = {
      let iresult = f(buffer.as_slice());

      from_iresult(&buffer, iresult)
    };

    match result {
      Ok((consumed, o)) => {
        buffer.consume(consumed);

        Ok(o)
      }
      Err(kind)         => {
        if let ErrorKind::Incomplete(needed) = kind {
          self.needed = needed;

          Err(ErrorKind::Continue)
        } else {
          Err(kind)
        }
      }
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use utility::StreamProducer;
  use nom::{self, IResult};

  #[inline]
  fn be_u32(input: &[u8]) -> IResult<&[u8], u32, ErrorKind> {
    nom::be_u32(input).map_err(to_custom_error!(Unknown))
  }

  #[test]
  fn test_buffer() {
    let mut buffer = Buffer::new();
    let bytes      = b"Hello World";
    let mut reader = &bytes[..];

    assert!(buffer.is_empty());
    assert_eq!(buffer.capacity(), 1024);

    let bytes_read = buffer.fill(&mut reader).unwrap_or(0);
    let bytes_len  = bytes.len();

    assert_eq!(bytes_read, bytes_len);
    assert_eq!(buffer.len(), bytes_len);
    assert_eq!(buffer.as_slice(), bytes);

    buffer.resize(512);
    assert_eq!(buffer.capacity(), 1024);
  }

  #[test]
  fn test_byte_stream() {
    let bytes      = b"Hello World";
    let mut stream = ByteStream::new(bytes);

    assert_eq!(stream.len(), bytes.len());

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444);
    assert_eq!(stream.len(), 7);
  }

  #[test]
  fn test_read_stream() {
    let bytes      = b"Hello World";
    let mut stream = ReadStream::new(&bytes[..]);

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444)
  }
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;
use std::collections::{HashMap, HashSet};
use context::{ContextOf, AContext, ContextBufferExt,
              ArrayBufferBinding, ArrayBufferContext,
              ElementArrayBufferBinding, ElementArrayBufferContext};
use program::ProgramAttrib;
use vertex_data::{VertexData, VertexBytes, VertexAttribute};
use index_data::{IndexData, IndexDatum};
use buffer::Buffer;
use types::DrawingMode;

#[derive(Debug)]
pub enum AttribAddError {
    DuplicateAttrib(String)
}

#[derive(Debug)]
pub struct AttribError {
    missing_attribs: Vec<String>,
    unknown_attribs: Vec<String>
}

pub struct AttribBinder {
    attribs: HashMap<String, ProgramAttrib>
}

impl AttribBinder {
    pub fn new() -> Self {
        AttribBinder {
            attribs: HashMap::new()
        }
    }

    pub fn add(&mut self, name: &str, attrib: ProgramAttrib)
        -> Result<(), AttribAddError>
    {
        match self.attribs.insert(name.into(), attrib) {
            None => Ok(()),
            Some(_) => Err(AttribAddError::DuplicateAttrib(name.into()))
        }
    }

    fn for_each<T, F>(&self, mut f: F) -> Result<(), AttribError>
        where T: VertexData, F: FnMut(VertexAttribute, ProgramAttrib)
    {
        // TODO: Avoid heap allocations
        // TODO: Avoid redundant calls to T::visit_attributes
        let mut attribs =
            HashMap::<String, (VertexAttribute, ProgramAttrib)>::new();
        let mut missing = Vec::<String>::new();

        T::visit_attributes(|vertex_attrib| {
            match self.attribs.get(&vertex_attrib.name) {
                Some(program_attrib) => {
                    let pair = (vertex_attrib.clone(), *program_attrib);
                    attribs.insert(vertex_attrib.name, pair);
                },
                None => {
                    missing.push(vertex_attrib.name);
                }
            }
        });

        let unknown: Vec<_> = {
            let expected: HashSet<_> = self.attribs.keys().collect();
            let actual: HashSet<_> = attribs.keys().collect();
            expected.difference(&actual).cloned().cloned().collect()
        };

        if missing.is_empty() && unknown.is_empty() {
            for (_, (vertex_attrib, program_attrib)) in attribs.into_iter() {
                f(vertex_attrib, program_attrib);
            }
            Ok(())
        }
        else {
            Err(AttribError {
                missing_attribs: missing,
                unknown_attribs: unknown
            })
        }
    }

    pub fn enable<V, C>(&self, gl: &mut C) -> Result<(), AttribError>
        where V: VertexData, C: AContext
    {
        self.for_each::<V, _>(|_, program_attrib| {
            gl.enable_vertex_attrib_array(program_attrib);
        })
    }

    pub fn bind<V, C>(&self, gl: &C) -> Result<(), AttribError>
        where V: VertexData, C: AContext
    {
        self.for_each::<V, _>(|vertex_attrib, program_attrib| {
            unsafe {
                // TODO: Refactor!
                // (Make vertex_attrib_pointer take vertex_attrib)
                gl.vertex_attrib_pointer(program_attrib,
                                         vertex_attrib.ty.components,
                                         vertex_attrib.ty.data,
                                         vertex_attrib.ty.normalize,
                                         vertex_attrib.stride,
                                         vertex_attrib.offset);
            }
        })
    }
}

#[derive(Debug)]
pub enum VertexBindError {
    BindingError(AttribError),
    NoAttributeBindings
}

impl From<AttribError> for VertexBindError {
    fn from(attrib_error: AttribError) -> VertexBindError {
        VertexBindError::BindingError(attrib_error)
    }
}

pub struct VertexBuffer<T: VertexData> {
    attrib_binder: Option<AttribBinder>,
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<V: VertexData> VertexBuffer<V> {
    pub fn bind_attrib_pointers(&mut self, binder: AttribBinder) {
        self.attrib_binder = Some(binder);
    }

    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut Buffer {
        &mut self.buffer
    }
}

pub struct VertexBufferBinding<'a, T: VertexData + 'a> {
    gl_buffer: ArrayBufferBinding<'a>,
    count: &'a mut usize,
    _phantom: PhantomData<*const VertexBuffer<T>>
}

pub trait ContextVertexBufferExt: AContext {
    fn new_vertex_buffer<V: VertexData>(&self) -> VertexBuffer<V> {
        VertexBuffer {
            attrib_binder: None,
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }

    fn buffer_vertices<T>(&self,
                          gl_vbo: &mut VertexBufferBinding<T>,
                          vertices: &[T],
                          usage: super::BufferDataUsage)
        where T: VertexData, [T]: VertexBytes
    {

        *gl_vbo.count = vertices.len();
        self.buffer_bytes(&mut gl_vbo.gl_buffer,
                          vertices.vertex_bytes(),
                          usage);
    }

    fn buffer_indices<T>(&self,
                         gl_ibo: &mut IndexBufferBinding<T>,
                         indices: &[T],
                         usage: super::BufferDataUsage)
        where T: IndexDatum, [T]: IndexData
    {
        *gl_ibo.count = indices.len();
        self.buffer_bytes(&mut gl_ibo.gl_buffer, indices.index_bytes(), usage);
    }

    fn draw_arrays_range_vbo<V>(&self,
                                gl_vbo: &VertexBufferBinding<V>,
                                mode: DrawingMode,
                                start: u32,
                                length: usize)
        where V: VertexData
    {
        debug_assert!((start as usize) + length <= *gl_vbo.count);

        unsafe {
            self.draw_arrays_range(&gl_vbo.gl_buffer, mode, start, length);
        }
    }

    fn draw_arrays_vbo<V>(&self,
                          gl_vbo: &VertexBufferBinding<V>,
                          mode: DrawingMode)
        where V: VertexData
    {
        unsafe {
            self.draw_arrays_range(&gl_vbo.gl_buffer,
                                   mode,
                                   0,
                                   *gl_vbo.count);
        }
    }

    fn draw_n_elements_buffered_vbo<V, I>(&self,
                                          gl_vbo: &VertexBufferBinding<V>,
                                          gl_ibo: &IndexBufferBinding<I>,
                                          mode: DrawingMode,
                                          length: usize)
        where V: VertexData, I: IndexDatum
    {
        debug_assert!(length <= *gl_ibo.count);

        unsafe {
            self.draw_n_elements_buffered(&gl_vbo.gl_buffer,
                                          &gl_ibo.gl_buffer,
                                          mode,
                                          length,
                                          I::index_datum_type());
        }
    }

    fn draw_elements_buffered_vbo<V, I>(&self,
                                        gl_vbo: &VertexBufferBinding<V>,
                                        gl_ibo: &IndexBufferBinding<I>,
                                        mode: DrawingMode)
        where V: VertexData, I: IndexDatum
    {
        unsafe {
            self.draw_n_elements_buffered(&gl_vbo.gl_buffer,
                                          &gl_ibo.gl_buffer,
                                          mode,
                                          *gl_ibo.count,
                                          I::index_datum_type());
        }
    }

    fn draw_n_elements_vbo<V, I>(&self,
                                 gl_vbo: &VertexBufferBinding<V>,
                                 mode: DrawingMode,
                                 count: usize,
                                 indices: &[I])
        where V: VertexData, I: IndexDatum, [I]: IndexData
    {
        unsafe {
            self.draw_n_elements(&gl_vbo.gl_buffer, mode, count, indices);
        }
    }

    fn draw_elements_vbo<V, I>(&mut self,
                               gl_vbo: &VertexBufferBinding<V>,
                               mode: DrawingMode,
                               indices: &[I])
        where V: VertexData, I: IndexDatum, [I]: IndexData
    {
        unsafe {
            self.draw_elements(&gl_vbo.gl_buffer, mode, indices);
        }
    }
}

impl<C: AContext> ContextVertexBufferExt for C {

}

pub trait VertexBufferContext: ArrayBufferContext + Sized {
    fn bind_vertex_buffer<'a, V>(self, vbo: &'a mut VertexBuffer<V>)
        -> (VertexBufferBinding<V>, Self::Rest)
        where V: VertexData
    {
        // TODO: Cleanup error handling
        let (gl_array_buffer, rest) = match vbo.attrib_binder {
            Some(ref binder) => {
                let buf = &mut vbo.buffer;
                let (gl_buffer, mut rest) = self.bind_array_buffer(buf);
                binder.enable::<V, _>(&mut rest).unwrap();
                binder.bind::<V, _>(&rest).unwrap();
                (gl_buffer, rest)
            },
            None => {
                panic!("No attribute bindings provided for vertex buffer");
            }
        };

        (
            VertexBufferBinding {
                gl_buffer: gl_array_buffer,
                count: &mut vbo.count,
                _phantom: PhantomData
            },
            rest
        )
    }
}

impl<C: ArrayBufferContext> VertexBufferContext for C {

}

pub trait IndexBufferContext: ElementArrayBufferContext + Sized {
    fn bind_index_buffer<'a, I>(self, ibo: &'a mut IndexBuffer<I>)
        -> (IndexBufferBinding<I>, Self::Rest)
        where I: IndexDatum
    {
        let (gl_be, rest) = self.bind_element_array_buffer(&mut ibo.buffer);
        (
            IndexBufferBinding {
                gl_buffer: gl_be,
                count: &mut ibo.count,
                _phantom: PhantomData
            },
            rest
        )
    }
}

impl<C: ElementArrayBufferContext> IndexBufferContext for C {

}

pub struct IndexBuffer<T: IndexDatum> {
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<T: IndexDatum> IndexBuffer<T> {
    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut Buffer {
        &mut self.buffer
    }
}

pub struct IndexBufferBinding<'a, T: IndexDatum + 'a> {
    gl_buffer: ElementArrayBufferBinding<'a>,
    count: &'a mut usize,
    _phantom: PhantomData<*const IndexBuffer<T>>
}

impl<B, F, P, R, T> ContextOf<B, F, P, R, T> {
    pub fn new_index_buffer<I: IndexDatum>(&self) -> IndexBuffer<I> {
        IndexBuffer {
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }
}

#[macro_export]
macro_rules! attrib_pointers {
    ($gl:expr, $vbo:expr, {
        $($field_name:ident => $field_attrib:expr),*
    }) => {
        {
            let mut binder = $crate::AttribBinder::new();
            $(binder.add(stringify!($field_name), $field_attrib).unwrap());*;
            binder
        }
    }
}
<commit_msg>Remove unused `$gl` parameter from `attrib_pointers!` macro<commit_after>use std::marker::PhantomData;
use std::collections::{HashMap, HashSet};
use context::{ContextOf, AContext, ContextBufferExt,
              ArrayBufferBinding, ArrayBufferContext,
              ElementArrayBufferBinding, ElementArrayBufferContext};
use program::ProgramAttrib;
use vertex_data::{VertexData, VertexBytes, VertexAttribute};
use index_data::{IndexData, IndexDatum};
use buffer::Buffer;
use types::DrawingMode;

#[derive(Debug)]
pub enum AttribAddError {
    DuplicateAttrib(String)
}

#[derive(Debug)]
pub struct AttribError {
    missing_attribs: Vec<String>,
    unknown_attribs: Vec<String>
}

pub struct AttribBinder {
    attribs: HashMap<String, ProgramAttrib>
}

impl AttribBinder {
    pub fn new() -> Self {
        AttribBinder {
            attribs: HashMap::new()
        }
    }

    pub fn add(&mut self, name: &str, attrib: ProgramAttrib)
        -> Result<(), AttribAddError>
    {
        match self.attribs.insert(name.into(), attrib) {
            None => Ok(()),
            Some(_) => Err(AttribAddError::DuplicateAttrib(name.into()))
        }
    }

    fn for_each<T, F>(&self, mut f: F) -> Result<(), AttribError>
        where T: VertexData, F: FnMut(VertexAttribute, ProgramAttrib)
    {
        // TODO: Avoid heap allocations
        // TODO: Avoid redundant calls to T::visit_attributes
        let mut attribs =
            HashMap::<String, (VertexAttribute, ProgramAttrib)>::new();
        let mut missing = Vec::<String>::new();

        T::visit_attributes(|vertex_attrib| {
            match self.attribs.get(&vertex_attrib.name) {
                Some(program_attrib) => {
                    let pair = (vertex_attrib.clone(), *program_attrib);
                    attribs.insert(vertex_attrib.name, pair);
                },
                None => {
                    missing.push(vertex_attrib.name);
                }
            }
        });

        let unknown: Vec<_> = {
            let expected: HashSet<_> = self.attribs.keys().collect();
            let actual: HashSet<_> = attribs.keys().collect();
            expected.difference(&actual).cloned().cloned().collect()
        };

        if missing.is_empty() && unknown.is_empty() {
            for (_, (vertex_attrib, program_attrib)) in attribs.into_iter() {
                f(vertex_attrib, program_attrib);
            }
            Ok(())
        }
        else {
            Err(AttribError {
                missing_attribs: missing,
                unknown_attribs: unknown
            })
        }
    }

    pub fn enable<V, C>(&self, gl: &mut C) -> Result<(), AttribError>
        where V: VertexData, C: AContext
    {
        self.for_each::<V, _>(|_, program_attrib| {
            gl.enable_vertex_attrib_array(program_attrib);
        })
    }

    pub fn bind<V, C>(&self, gl: &C) -> Result<(), AttribError>
        where V: VertexData, C: AContext
    {
        self.for_each::<V, _>(|vertex_attrib, program_attrib| {
            unsafe {
                // TODO: Refactor!
                // (Make vertex_attrib_pointer take vertex_attrib)
                gl.vertex_attrib_pointer(program_attrib,
                                         vertex_attrib.ty.components,
                                         vertex_attrib.ty.data,
                                         vertex_attrib.ty.normalize,
                                         vertex_attrib.stride,
                                         vertex_attrib.offset);
            }
        })
    }
}

#[derive(Debug)]
pub enum VertexBindError {
    BindingError(AttribError),
    NoAttributeBindings
}

impl From<AttribError> for VertexBindError {
    fn from(attrib_error: AttribError) -> VertexBindError {
        VertexBindError::BindingError(attrib_error)
    }
}

pub struct VertexBuffer<T: VertexData> {
    attrib_binder: Option<AttribBinder>,
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<V: VertexData> VertexBuffer<V> {
    pub fn bind_attrib_pointers(&mut self, binder: AttribBinder) {
        self.attrib_binder = Some(binder);
    }

    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut Buffer {
        &mut self.buffer
    }
}

pub struct VertexBufferBinding<'a, T: VertexData + 'a> {
    gl_buffer: ArrayBufferBinding<'a>,
    count: &'a mut usize,
    _phantom: PhantomData<*const VertexBuffer<T>>
}

pub trait ContextVertexBufferExt: AContext {
    fn new_vertex_buffer<V: VertexData>(&self) -> VertexBuffer<V> {
        VertexBuffer {
            attrib_binder: None,
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }

    fn buffer_vertices<T>(&self,
                          gl_vbo: &mut VertexBufferBinding<T>,
                          vertices: &[T],
                          usage: super::BufferDataUsage)
        where T: VertexData, [T]: VertexBytes
    {

        *gl_vbo.count = vertices.len();
        self.buffer_bytes(&mut gl_vbo.gl_buffer,
                          vertices.vertex_bytes(),
                          usage);
    }

    fn buffer_indices<T>(&self,
                         gl_ibo: &mut IndexBufferBinding<T>,
                         indices: &[T],
                         usage: super::BufferDataUsage)
        where T: IndexDatum, [T]: IndexData
    {
        *gl_ibo.count = indices.len();
        self.buffer_bytes(&mut gl_ibo.gl_buffer, indices.index_bytes(), usage);
    }

    fn draw_arrays_range_vbo<V>(&self,
                                gl_vbo: &VertexBufferBinding<V>,
                                mode: DrawingMode,
                                start: u32,
                                length: usize)
        where V: VertexData
    {
        debug_assert!((start as usize) + length <= *gl_vbo.count);

        unsafe {
            self.draw_arrays_range(&gl_vbo.gl_buffer, mode, start, length);
        }
    }

    fn draw_arrays_vbo<V>(&self,
                          gl_vbo: &VertexBufferBinding<V>,
                          mode: DrawingMode)
        where V: VertexData
    {
        unsafe {
            self.draw_arrays_range(&gl_vbo.gl_buffer,
                                   mode,
                                   0,
                                   *gl_vbo.count);
        }
    }

    fn draw_n_elements_buffered_vbo<V, I>(&self,
                                          gl_vbo: &VertexBufferBinding<V>,
                                          gl_ibo: &IndexBufferBinding<I>,
                                          mode: DrawingMode,
                                          length: usize)
        where V: VertexData, I: IndexDatum
    {
        debug_assert!(length <= *gl_ibo.count);

        unsafe {
            self.draw_n_elements_buffered(&gl_vbo.gl_buffer,
                                          &gl_ibo.gl_buffer,
                                          mode,
                                          length,
                                          I::index_datum_type());
        }
    }

    fn draw_elements_buffered_vbo<V, I>(&self,
                                        gl_vbo: &VertexBufferBinding<V>,
                                        gl_ibo: &IndexBufferBinding<I>,
                                        mode: DrawingMode)
        where V: VertexData, I: IndexDatum
    {
        unsafe {
            self.draw_n_elements_buffered(&gl_vbo.gl_buffer,
                                          &gl_ibo.gl_buffer,
                                          mode,
                                          *gl_ibo.count,
                                          I::index_datum_type());
        }
    }

    fn draw_n_elements_vbo<V, I>(&self,
                                 gl_vbo: &VertexBufferBinding<V>,
                                 mode: DrawingMode,
                                 count: usize,
                                 indices: &[I])
        where V: VertexData, I: IndexDatum, [I]: IndexData
    {
        unsafe {
            self.draw_n_elements(&gl_vbo.gl_buffer, mode, count, indices);
        }
    }

    fn draw_elements_vbo<V, I>(&mut self,
                               gl_vbo: &VertexBufferBinding<V>,
                               mode: DrawingMode,
                               indices: &[I])
        where V: VertexData, I: IndexDatum, [I]: IndexData
    {
        unsafe {
            self.draw_elements(&gl_vbo.gl_buffer, mode, indices);
        }
    }
}

impl<C: AContext> ContextVertexBufferExt for C {

}

pub trait VertexBufferContext: ArrayBufferContext + Sized {
    fn bind_vertex_buffer<'a, V>(self, vbo: &'a mut VertexBuffer<V>)
        -> (VertexBufferBinding<V>, Self::Rest)
        where V: VertexData
    {
        // TODO: Cleanup error handling
        let (gl_array_buffer, rest) = match vbo.attrib_binder {
            Some(ref binder) => {
                let buf = &mut vbo.buffer;
                let (gl_buffer, mut rest) = self.bind_array_buffer(buf);
                binder.enable::<V, _>(&mut rest).unwrap();
                binder.bind::<V, _>(&rest).unwrap();
                (gl_buffer, rest)
            },
            None => {
                panic!("No attribute bindings provided for vertex buffer");
            }
        };

        (
            VertexBufferBinding {
                gl_buffer: gl_array_buffer,
                count: &mut vbo.count,
                _phantom: PhantomData
            },
            rest
        )
    }
}

impl<C: ArrayBufferContext> VertexBufferContext for C {

}

pub trait IndexBufferContext: ElementArrayBufferContext + Sized {
    fn bind_index_buffer<'a, I>(self, ibo: &'a mut IndexBuffer<I>)
        -> (IndexBufferBinding<I>, Self::Rest)
        where I: IndexDatum
    {
        let (gl_be, rest) = self.bind_element_array_buffer(&mut ibo.buffer);
        (
            IndexBufferBinding {
                gl_buffer: gl_be,
                count: &mut ibo.count,
                _phantom: PhantomData
            },
            rest
        )
    }
}

impl<C: ElementArrayBufferContext> IndexBufferContext for C {

}

pub struct IndexBuffer<T: IndexDatum> {
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<T: IndexDatum> IndexBuffer<T> {
    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut Buffer {
        &mut self.buffer
    }
}

pub struct IndexBufferBinding<'a, T: IndexDatum + 'a> {
    gl_buffer: ElementArrayBufferBinding<'a>,
    count: &'a mut usize,
    _phantom: PhantomData<*const IndexBuffer<T>>
}

impl<B, F, P, R, T> ContextOf<B, F, P, R, T> {
    pub fn new_index_buffer<I: IndexDatum>(&self) -> IndexBuffer<I> {
        IndexBuffer {
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }
}

#[macro_export]
macro_rules! attrib_pointers {
    ($($field_name:ident => $field_attrib:expr),*) => {
        {
            let mut binder = $crate::AttribBinder::new();
            $(binder.add(stringify!($field_name), $field_attrib).unwrap());*;
            binder
        }
    }
}
<|endoftext|>


<commit_before>use gl;
use libc;
use std::collections::HashMap;
use std::c_vec::CVec;
use std::fmt;
use std::mem;
use std::sync::Arc;

/// A list of verices loaded in the graphics card's memory.
pub struct VertexBuffer<T> {
    display: Arc<super::DisplayImpl>,
    id: gl::types::GLuint,
    elements_size: uint,
    bindings: VertexBindings,
    elements_count: uint,
}

/// This public function is accessible from within `glium` but not for the user.
#[doc(hidden)]
pub fn get_clone<T>(vb: &VertexBuffer<T>) -> (gl::types::GLuint, uint, VertexBindings) {
    (vb.id.clone(), vb.elements_size.clone(), vb.bindings.clone())
}

impl<T: VertexFormat + 'static + Send> VertexBuffer<T> {
    /// Builds a new vertex buffer.
    ///
    /// # Example
    ///
    /// ```no_run
    /// # #![feature(phase)]
    /// # #[phase(plugin)]
    /// # extern crate glium_macros;
    /// # extern crate glium;
    /// # fn main() {
    /// #[vertex_format]
    /// struct Vertex {
    ///     position: [f32, ..3],
    ///     texcoords: [f32, ..2],
    /// }
    ///
    /// # let display: glium::Display = unsafe { std::mem::uninitialized() };
    /// let vertex_buffer = glium::VertexBuffer::new(&display, vec![
    ///     Vertex { position: [0.0,  0.0, 0.0], texcoords: [0.0, 1.0] },
    ///     Vertex { position: [5.0, -3.0, 2.0], texcoords: [1.0, 0.0] },
    /// ]);
    /// # }
    /// ```
    ///
    pub fn new(display: &super::Display, data: Vec<T>) -> VertexBuffer<T> {
        VertexBuffer::new_impl(display, data, false)
    }

    /// Builds a new vertex buffer.
    ///
    /// This function will create a buffer that has better performances when the it is modified
    ///  frequently.
    pub fn new_dynamic(display: &super::Display, data: Vec<T>) -> VertexBuffer<T> {
        VertexBuffer::new_impl(display, data, true)
    }

    fn new_impl(display: &super::Display, data: Vec<T>, dynamic: bool) -> VertexBuffer<T> {
        let bindings = VertexFormat::build_bindings(None::<T>);

        let elements_size = { use std::mem; mem::size_of::<T>() };
        let elements_count = data.len();
        let buffer_size = elements_count * elements_size as uint;

        let usage = if dynamic { gl::DYNAMIC_DRAW } else { gl::STATIC_DRAW };

        let (tx, rx) = channel();

        display.context.context.exec(proc(gl, state) {
            unsafe {
                let mut id: gl::types::GLuint = mem::uninitialized();
                gl.GenBuffers(1, &mut id);

                if gl.NamedBufferData.is_loaded() {
                    gl.NamedBufferData(id, buffer_size as gl::types::GLsizei,
                        data.as_ptr() as *const libc::c_void, usage);

                } else if gl.NamedBufferDataEXT.is_loaded() {
                    gl.NamedBufferDataEXT(id, buffer_size as gl::types::GLsizeiptr,
                        data.as_ptr() as *const libc::c_void, usage);

                } else {
                    gl.BindBuffer(gl::ARRAY_BUFFER, id);
                    state.array_buffer_binding = Some(id);
                    gl.BufferData(gl::ARRAY_BUFFER, buffer_size as gl::types::GLsizeiptr,
                        data.as_ptr() as *const libc::c_void, usage);
                }

                tx.send(id);
            }
        });

        VertexBuffer {
            display: display.context.clone(),
            id: rx.recv(),
            elements_size: elements_size,
            bindings: bindings,
            elements_count: elements_count,
        }
    }

    /// Maps the buffer to allow write access to it.
    pub fn map<'a>(&'a mut self) -> Mapping<'a, T> {
        let (tx, rx) = channel();
        let id = self.id.clone();
        let elements_count = self.elements_count.clone();

        self.display.context.exec(proc(gl, state) {
            let ptr = {
                if gl.MapNamedBuffer.is_loaded() {
                    gl.MapNamedBuffer(id, gl::READ_WRITE)
                } else {
                    if state.array_buffer_binding != Some(id) {
                        gl.BindBuffer(gl::ARRAY_BUFFER, id);
                        state.array_buffer_binding = Some(id);
                    }

                    gl.MapBuffer(gl::ARRAY_BUFFER, gl::READ_WRITE)
                }
            };

            tx.send(ptr as *mut T);
        });

        Mapping {
            buffer: self,
            data: unsafe { CVec::new(rx.recv(), elements_count) },
        }
    }
}

impl<T> fmt::Show for VertexBuffer<T> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::FormatError> {
        (format!("VertexBuffer #{}", self.id)).fmt(formatter)
    }
}

#[unsafe_destructor]
impl<T> Drop for VertexBuffer<T> {
    fn drop(&mut self) {
        let id = self.id.clone();
        self.display.context.exec(proc(gl, state) {
            if state.array_buffer_binding == Some(id) {
                state.array_buffer_binding = None;
            }

            if state.element_array_buffer_binding == Some(id) {
                state.element_array_buffer_binding = None;
            }

            unsafe { gl.DeleteBuffers(1, [ id ].as_ptr()); }
        });
    }
}

/// For each binding, the data type, number of elements, and offset.
/// Includes the total size.
#[doc(hidden)]
pub type VertexBindings = HashMap<String, (gl::types::GLenum, gl::types::GLint, uint)>;

/// Trait for structures that represent a vertex.
#[doc(hidden)]
pub trait VertexFormat: Copy {
    fn build_bindings(Option<Self>) -> VertexBindings;
}

/// A mapping of a buffer.
pub struct Mapping<'b, T> {
    buffer: &'b mut VertexBuffer<T>,
    data: CVec<T>,
}

#[unsafe_destructor]
impl<'a, T> Drop for Mapping<'a, T> {
    fn drop(&mut self) {
        let id = self.buffer.id.clone();
        self.buffer.display.context.exec(proc(gl, state) {
            if gl.UnmapNamedBuffer.is_loaded() {
                gl.UnmapNamedBuffer(id);

            } else {
                if state.array_buffer_binding != Some(id) {
                    gl.BindBuffer(gl::ARRAY_BUFFER, id);
                    state.array_buffer_binding = Some(id);
                }

                gl.UnmapBuffer(gl::ARRAY_BUFFER);
            }
        });
    }
}

impl<'a, T> Deref<[T]> for Mapping<'a, T> {
    fn deref<'b>(&'b self) -> &'b [T] {
        self.data.as_slice()
    }
}

impl<'a, T> DerefMut<[T]> for Mapping<'a, T> {
    fn deref_mut<'b>(&'b mut self) -> &'b mut [T] {
        self.data.as_mut_slice()
    }
}
<commit_msg>Fix typo in vertex buffer doc<commit_after>use gl;
use libc;
use std::collections::HashMap;
use std::c_vec::CVec;
use std::fmt;
use std::mem;
use std::sync::Arc;

/// A list of verices loaded in the graphics card's memory.
pub struct VertexBuffer<T> {
    display: Arc<super::DisplayImpl>,
    id: gl::types::GLuint,
    elements_size: uint,
    bindings: VertexBindings,
    elements_count: uint,
}

/// This public function is accessible from within `glium` but not for the user.
#[doc(hidden)]
pub fn get_clone<T>(vb: &VertexBuffer<T>) -> (gl::types::GLuint, uint, VertexBindings) {
    (vb.id.clone(), vb.elements_size.clone(), vb.bindings.clone())
}

impl<T: VertexFormat + 'static + Send> VertexBuffer<T> {
    /// Builds a new vertex buffer.
    ///
    /// # Example
    ///
    /// ```no_run
    /// # #![feature(phase)]
    /// # #[phase(plugin)]
    /// # extern crate glium_macros;
    /// # extern crate glium;
    /// # fn main() {
    /// #[vertex_format]
    /// struct Vertex {
    ///     position: [f32, ..3],
    ///     texcoords: [f32, ..2],
    /// }
    ///
    /// # let display: glium::Display = unsafe { std::mem::uninitialized() };
    /// let vertex_buffer = glium::VertexBuffer::new(&display, vec![
    ///     Vertex { position: [0.0,  0.0, 0.0], texcoords: [0.0, 1.0] },
    ///     Vertex { position: [5.0, -3.0, 2.0], texcoords: [1.0, 0.0] },
    /// ]);
    /// # }
    /// ```
    ///
    pub fn new(display: &super::Display, data: Vec<T>) -> VertexBuffer<T> {
        VertexBuffer::new_impl(display, data, false)
    }

    /// Builds a new vertex buffer.
    ///
    /// This function will create a buffer that has better performances when it is modified
    ///  frequently.
    pub fn new_dynamic(display: &super::Display, data: Vec<T>) -> VertexBuffer<T> {
        VertexBuffer::new_impl(display, data, true)
    }

    fn new_impl(display: &super::Display, data: Vec<T>, dynamic: bool) -> VertexBuffer<T> {
        let bindings = VertexFormat::build_bindings(None::<T>);

        let elements_size = { use std::mem; mem::size_of::<T>() };
        let elements_count = data.len();
        let buffer_size = elements_count * elements_size as uint;

        let usage = if dynamic { gl::DYNAMIC_DRAW } else { gl::STATIC_DRAW };

        let (tx, rx) = channel();

        display.context.context.exec(proc(gl, state) {
            unsafe {
                let mut id: gl::types::GLuint = mem::uninitialized();
                gl.GenBuffers(1, &mut id);

                if gl.NamedBufferData.is_loaded() {
                    gl.NamedBufferData(id, buffer_size as gl::types::GLsizei,
                        data.as_ptr() as *const libc::c_void, usage);

                } else if gl.NamedBufferDataEXT.is_loaded() {
                    gl.NamedBufferDataEXT(id, buffer_size as gl::types::GLsizeiptr,
                        data.as_ptr() as *const libc::c_void, usage);

                } else {
                    gl.BindBuffer(gl::ARRAY_BUFFER, id);
                    state.array_buffer_binding = Some(id);
                    gl.BufferData(gl::ARRAY_BUFFER, buffer_size as gl::types::GLsizeiptr,
                        data.as_ptr() as *const libc::c_void, usage);
                }

                tx.send(id);
            }
        });

        VertexBuffer {
            display: display.context.clone(),
            id: rx.recv(),
            elements_size: elements_size,
            bindings: bindings,
            elements_count: elements_count,
        }
    }

    /// Maps the buffer to allow write access to it.
    pub fn map<'a>(&'a mut self) -> Mapping<'a, T> {
        let (tx, rx) = channel();
        let id = self.id.clone();
        let elements_count = self.elements_count.clone();

        self.display.context.exec(proc(gl, state) {
            let ptr = {
                if gl.MapNamedBuffer.is_loaded() {
                    gl.MapNamedBuffer(id, gl::READ_WRITE)
                } else {
                    if state.array_buffer_binding != Some(id) {
                        gl.BindBuffer(gl::ARRAY_BUFFER, id);
                        state.array_buffer_binding = Some(id);
                    }

                    gl.MapBuffer(gl::ARRAY_BUFFER, gl::READ_WRITE)
                }
            };

            tx.send(ptr as *mut T);
        });

        Mapping {
            buffer: self,
            data: unsafe { CVec::new(rx.recv(), elements_count) },
        }
    }
}

impl<T> fmt::Show for VertexBuffer<T> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::FormatError> {
        (format!("VertexBuffer #{}", self.id)).fmt(formatter)
    }
}

#[unsafe_destructor]
impl<T> Drop for VertexBuffer<T> {
    fn drop(&mut self) {
        let id = self.id.clone();
        self.display.context.exec(proc(gl, state) {
            if state.array_buffer_binding == Some(id) {
                state.array_buffer_binding = None;
            }

            if state.element_array_buffer_binding == Some(id) {
                state.element_array_buffer_binding = None;
            }

            unsafe { gl.DeleteBuffers(1, [ id ].as_ptr()); }
        });
    }
}

/// For each binding, the data type, number of elements, and offset.
/// Includes the total size.
#[doc(hidden)]
pub type VertexBindings = HashMap<String, (gl::types::GLenum, gl::types::GLint, uint)>;

/// Trait for structures that represent a vertex.
#[doc(hidden)]
pub trait VertexFormat: Copy {
    fn build_bindings(Option<Self>) -> VertexBindings;
}

/// A mapping of a buffer.
pub struct Mapping<'b, T> {
    buffer: &'b mut VertexBuffer<T>,
    data: CVec<T>,
}

#[unsafe_destructor]
impl<'a, T> Drop for Mapping<'a, T> {
    fn drop(&mut self) {
        let id = self.buffer.id.clone();
        self.buffer.display.context.exec(proc(gl, state) {
            if gl.UnmapNamedBuffer.is_loaded() {
                gl.UnmapNamedBuffer(id);

            } else {
                if state.array_buffer_binding != Some(id) {
                    gl.BindBuffer(gl::ARRAY_BUFFER, id);
                    state.array_buffer_binding = Some(id);
                }

                gl.UnmapBuffer(gl::ARRAY_BUFFER);
            }
        });
    }
}

impl<'a, T> Deref<[T]> for Mapping<'a, T> {
    fn deref<'b>(&'b self) -> &'b [T] {
        self.data.as_slice()
    }
}

impl<'a, T> DerefMut<[T]> for Mapping<'a, T> {
    fn deref_mut<'b>(&'b mut self) -> &'b mut [T] {
        self.data.as_mut_slice()
    }
}
<|endoftext|>


<commit_before>
use graphics::character::CharacterCache;
use super::Kind;
use super::Update;
use ui::{Ui, UiId};

/// A trait to be implemented for Custom widget types.
///
/// If you think your widget might be useful enough for conrod's official widget library, Feel free
/// to submit a PR at https://github.com/PistonDevelopers/conrod.
pub trait Custom: Clone + ::std::fmt::Debug {
    /// State to be stored within the `Ui`s widget cache.
    type State: State;

    /// After building the widget, we use this method to set its current state into the given `Ui`.
    /// The `Ui` will cache this state and use it for rendering the next time `ui.draw(graphics)`
    /// is called.
    fn set<C>(self, ui_id: UiId, ui: &mut Ui<C, Self>) where C: CharacterCache {
        let state = match *ui.get_widget_mut(ui_id, Kind::Custom(Self::State::init())) {
            ::widget::Kind::Custom(ref state) => state.clone(),
            _ => panic!("The Kind variant returned by Ui is different to that which \
                        was requested (Check that there are no UiId conflicts)."),
        };
        let Update { new_state, xy, depth, element } = self.update(state, ui_id, ui);
        ui.update_widget(ui_id, Kind::Custom(new_state), xy, depth, Some(element));
    }

    /// Return the type of the widget as a &'static str. Note that this must be unique from all
    /// other widgets' unique types. This is used by conrod to help users avoid UiId errors.
    fn unique_type(&self) -> &'static str;

    /// This is the method you have to implement! Your widget's previous state is given to you as a
    /// parameter and it is your job to construct and return an Update that will be used to update
    /// the widget's cached state.
    fn update<C>(mut self, prev: Self::State, ui_id: UiId, ui: &mut Ui<C, Self>) -> Update<Self::State>;
}

/// The widget's state that is to be stored within the `Ui`s widget cache.
pub trait State: Clone + ::std::fmt::Debug {
    /// The inital state.
    fn init() -> Self;
}

impl Custom for () {
    type State = ();
    fn set<C>(self, _: UiId, _ui: &mut Ui<C, ()>) {}
    fn update<C>(self, _: (), _: UiId, _: &mut Ui<C, ()>) -> Update<()> {
        Update {
            new_state: (),
            xy: [0.0, 0.0],
            depth: 0.0,
            element: ::elmesque::element::empty(),
        }
    }
}

impl State for () {
    fn matches(&self, _other: &()) -> bool { true }
    fn init() -> Self { () }
}

<commit_msg>Resolved conflicts with master by removing unnecessary custom module.<commit_after><|endoftext|>