<commit_before>use mio::*;
use mio::timer::Timer;
use mio_uds::{UnixListener,UnixStream};
use slab::Slab;
use std::fs;
use std::fmt;
use std::path::PathBuf;
use std::io::{self,ErrorKind};
use std::os::unix::fs::PermissionsExt;
use std::collections::HashMap;
use std::time::Duration;
use log;
use libc::pid_t;
use serde_json;

use sozu::network::{ProxyOrder,ServerMessage,ServerMessageStatus};
use sozu::channel::Channel;

use config::Config;
use state::{HttpProxy,TlsProxy,ConfigState};

pub mod data;
pub mod orders;
pub mod client;

use self::data::{ConfigMessage,ConfigMessageAnswer,ConfigMessageStatus,ProxyType};
use self::client::{ConnReadError,CommandClient};

const SERVER: Token = Token(0);

#[derive(Copy,Clone,Debug,PartialEq,Eq,PartialOrd,Ord,Hash)]
pub struct FrontToken(pub usize);

impl From<usize> for FrontToken {
    fn from(val: usize) -> FrontToken {
        FrontToken(val)
    }
}

impl From<FrontToken> for usize {
    fn from(val: FrontToken) -> usize {
        val.0
    }
}

//#[derive(Serialize)]
pub struct Proxy {
  pub tag:           String,
  pub id:            u8,
  pub proxy_type:    ProxyType,
  pub channel:       Channel<ProxyOrder,ServerMessage>,
  pub state:         ConfigState,
  pub token:         Option<Token>,
  pub pid:           pid_t,
}

impl Proxy {
  pub fn new(tag: String, id: u8, pid: pid_t, proxy_type: ProxyType, ip_address: String, port: u16, channel: Channel<ProxyOrder,ServerMessage>) -> Proxy {
    let state = match proxy_type {
      ProxyType::HTTP  => ConfigState::Http(HttpProxy::new(ip_address, port)),
      ProxyType::HTTPS => ConfigState::Tls(TlsProxy::new(ip_address, port)),
      _                => unimplemented!(),
    };

    Proxy {
      tag:        tag,
      id:         id,
      proxy_type: proxy_type,
      channel:    channel,
      state:      state,
      token:      None,
      pid:        pid,
    }
  }
}

impl fmt::Debug for Proxy {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "Proxy {{ tag: {}, proxy_type: {:?}, state: {:?} }}", self.tag, self.proxy_type, self.state)
  }
}

#[derive(Deserialize,Serialize,Debug)]
pub struct StoredProxy {
  pub tag:        String,
  pub proxy_type: ProxyType,
  pub state:      ConfigState,
}

impl StoredProxy {
  pub fn from_proxy(proxy: &Proxy) -> StoredProxy {
    StoredProxy {
      tag:        proxy.tag.clone(),
      proxy_type: proxy.proxy_type.clone(),
      state:      proxy.state.clone(),
    }
  }
}

#[derive(Deserialize,Serialize,Debug)]
pub struct ProxyConfiguration {
  id:      String,
  proxies: Vec<StoredProxy>,
}

pub type Tag = String;

struct CommandServer {
  sock:            UnixListener,
  buffer_size:     usize,
  max_buffer_size: usize,
  conns:           Slab<CommandClient,FrontToken>,
  proxies:         HashMap<Token, (Tag, Proxy)>,
  proxy_count:     usize,
  pub poll:        Poll,
  timer:           Timer<Token>,
}

impl CommandServer {
  fn accept(&mut self) -> io::Result<()> {
    debug!("server accepting socket");

    let acc = self.sock.accept();
    if let Ok(Some((sock, addr))) = acc {
      let conn = CommandClient::new(sock, self.buffer_size, self.max_buffer_size);
      let tok = self.conns.insert(conn)
        .ok().expect("could not add connection to slab");

      // Register the connection
      let token = self.from_front(tok);
      self.conns[tok].token = Some(token);
      let mut interest = Ready::hup();
      interest.insert(Ready::readable());
      interest.insert(Ready::writable());
      self.poll.register(&self.conns[tok].channel.sock, token, interest, PollOpt::edge())
        .ok().expect("could not register socket with event loop");

      let accept_interest = Ready::readable();
      self.poll.reregister(&self.sock, SERVER, accept_interest, PollOpt::edge());
      Ok(())
    } else {
      //FIXME: what do other cases mean, like Ok(None)?
      acc.map(|_| ())
    }
  }

  fn dispatch(&mut self, token: FrontToken, v: Vec<ConfigMessage>) {
    for message in &v {
      self.handle_client_message(token, message);
    }
  }

  fn new(srv: UnixListener, proxies_map: HashMap<String, Vec<Proxy>>, buffer_size: usize, max_buffer_size: usize, poll: Poll) -> CommandServer {
    //FIXME: verify this
    poll.register(&srv, Token(0), Ready::readable(), PollOpt::edge() | PollOpt::oneshot()).unwrap();

    let mut proxies = HashMap::new();

    let mut token_count = 0;
    for (tag, mut proxy_list) in proxies_map {
      for proxy in proxy_list.drain(..) {
        token_count += 1;
        poll.register(&proxy.channel.sock, Token(token_count), Ready::all(), PollOpt::edge()).unwrap();
        proxies.insert(Token(token_count), (tag.clone(), proxy));
      }
    }
    //let mut timer = timer::Builder::default().tick_duration(Duration::from_millis(1000)).build();
    //FIXME: registering the timer makes the timer thread spin too much
    let mut timer = timer::Timer::default();
    //poll.register(&timer, Token(1), Ready::readable(), PollOpt::edge()).unwrap();
    timer.set_timeout(Duration::from_millis(700), Token(0));
    CommandServer {
      sock:            srv,
      buffer_size:     buffer_size,
      max_buffer_size: max_buffer_size,
      conns:           Slab::with_capacity(128),
      proxies:       proxies,
      proxy_count:  token_count,
      poll:            poll,
      timer:           timer,
    }
  }

  pub fn to_front(&self, token: Token) -> FrontToken {
    FrontToken(token.0 - self.proxy_count - 1)
  }

  pub fn from_front(&self, token: FrontToken) -> Token {
    Token(token.0 + self.proxy_count + 1)
  }

}

type Message = ();

impl CommandServer {
  pub fn run(&mut self) {
    let mut events = Events::with_capacity(1024);
    let poll_timeout = Some(Duration::from_millis(1000));
    loop {
      self.poll.poll(&mut events, poll_timeout).unwrap();
      for event in events.iter() {
        self.ready(event.token(), event.kind());
      }
    }
  }

  fn ready(&mut self, token: Token, events: Ready) {
    //trace!("ready: {:?} -> {:?}", token, events);
    match token {
      Token(0) => {
        if events.is_readable() {
          self.accept().unwrap();
        } else {
          error!("received writable for token 0");
        }
      },
      Token(i) if i < self.proxy_count + 1 => {
        info!("token({}) worker got event {:?}", i, events);
        //println!("proxies:\n{:?}", self.proxies);

        let mut messages = {
          let &mut (ref tag, ref mut proxy) =  self.proxies.get_mut(&Token(i)).unwrap();
          proxy.channel.handle_events(events);
          proxy.channel.run();

          let mut messages = Vec::new();
          loop {
            let msg = proxy.channel.read_message();
            if msg.is_none() {
              break;
            } else {
              messages.push(msg.unwrap());
            }
          }

          messages
        };

        for msg in messages.drain(..) {
          self.proxy_handle_message(Token(i), msg);
        }

        {
          let &mut (ref tag, ref mut proxy) =  self.proxies.get_mut(&Token(i)).unwrap();
          proxy.channel.run();
        }

      },
      _ => {
        let conn_token = self.to_front(token);
        if self.conns.contains(conn_token) {
          self.conns[conn_token].channel.handle_events(events);
          self.conns[conn_token].channel.run();

          //FIXME: handle deconnection
          loop {
            let message = self.conns[conn_token].channel.read_message();

            // if the message was too large, we grow the buffer and retry to read if possible
            if message.is_none() {
              if self.conns[conn_token].channel.readiness.is_hup() {
                break;
              }

              if (self.conns[conn_token].channel.interest & self.conns[conn_token].channel.readiness).is_readable() {
                self.conns[conn_token].channel.run();
                continue;
              } else {
                break;
              }
            }

            let message = message.unwrap();
            self.handle_client_message(conn_token, &message);

          }

          self.conns[conn_token].channel.run();

          if self.conns[conn_token].channel.readiness.is_hup() {
            self.poll.deregister(&self.conns[conn_token].channel.sock);
            self.conns.remove(conn_token);
            trace!("closed client [{}]", token.0);
          }
        }
      }
    }
  }

  fn proxy_handle_message(&mut self, token: Token, msg: ServerMessage) {
    println!("got answer msg: {:?}", msg);
    let answer = ConfigMessageAnswer {
      id: msg.id.clone(),
      status: match msg.status {
        ServerMessageStatus::Error(_)   => ConfigMessageStatus::Error,
        ServerMessageStatus::Ok         => ConfigMessageStatus::Ok,
        ServerMessageStatus::Processing => ConfigMessageStatus::Processing,
      },
      message: match msg.status {
                 ServerMessageStatus::Error(s) => s.clone(),
                 _                             => String::new(),
               },
    };
    info!("sending: {:?}", answer);
    for client in self.conns.iter_mut() {
      if let Some(index) = client.has_message_id(&msg.id) {
        client.write_message(&answer);
        client.remove_message_id(index);
      }
    }
  }

}

pub fn start(config: Config, proxies: HashMap<String, Vec<Proxy>>) {
  let buffer_size     = config.command_buffer_size.unwrap_or(10000);
  let max_buffer_size = config.max_command_buffer_size.unwrap_or(buffer_size * 2);
  let saved_state     = config.saved_state.clone();

  let event_loop = Poll::new().unwrap();
  let addr = PathBuf::from(&config.command_socket);
  if let Err(e) = fs::remove_file(&addr) {
    match e.kind() {
      ErrorKind::NotFound => {},
      _ => {
        log!(log::LogLevel::Error, "could not delete previous socket at {:?}: {:?}", addr, e);
        return;
      }
    }
  }
  match UnixListener::bind(&addr) {
    Ok(srv) => {
      if let Err(e) =  fs::set_permissions(&addr, fs::Permissions::from_mode(0o600)) {
        log!( log::LogLevel::Error, "could not set the unix socket permissions: {:?}", e);
        fs::remove_file(&addr);
        return;
      }

      let mut server = CommandServer::new(srv, proxies, buffer_size, max_buffer_size, event_loop);

      server.load_static_application_configuration(&config);

      saved_state.as_ref().map(|state_path| {
        server.load_state("INITIALIZATION", state_path);
      });

      info!("listen for connections");
      server.run();
      //event_loop.run(&mut CommandServer::new(srv, proxies, buffer_size, max_buffer_size)).unwrap()
    },
      Err(e) => {
        log!(log::LogLevel::Error, "could not create unix socket: {:?}", e);
      }
  }
}
<commit_msg>remove some logs<commit_after>use mio::*;
use mio::timer::Timer;
use mio_uds::{UnixListener,UnixStream};
use slab::Slab;
use std::fs;
use std::fmt;
use std::path::PathBuf;
use std::io::{self,ErrorKind};
use std::os::unix::fs::PermissionsExt;
use std::collections::HashMap;
use std::time::Duration;
use log;
use libc::pid_t;
use serde_json;

use sozu::network::{ProxyOrder,ServerMessage,ServerMessageStatus};
use sozu::channel::Channel;

use config::Config;
use state::{HttpProxy,TlsProxy,ConfigState};

pub mod data;
pub mod orders;
pub mod client;

use self::data::{ConfigMessage,ConfigMessageAnswer,ConfigMessageStatus,ProxyType};
use self::client::{ConnReadError,CommandClient};

const SERVER: Token = Token(0);

#[derive(Copy,Clone,Debug,PartialEq,Eq,PartialOrd,Ord,Hash)]
pub struct FrontToken(pub usize);

impl From<usize> for FrontToken {
    fn from(val: usize) -> FrontToken {
        FrontToken(val)
    }
}

impl From<FrontToken> for usize {
    fn from(val: FrontToken) -> usize {
        val.0
    }
}

//#[derive(Serialize)]
pub struct Proxy {
  pub tag:           String,
  pub id:            u8,
  pub proxy_type:    ProxyType,
  pub channel:       Channel<ProxyOrder,ServerMessage>,
  pub state:         ConfigState,
  pub token:         Option<Token>,
  pub pid:           pid_t,
}

impl Proxy {
  pub fn new(tag: String, id: u8, pid: pid_t, proxy_type: ProxyType, ip_address: String, port: u16, channel: Channel<ProxyOrder,ServerMessage>) -> Proxy {
    let state = match proxy_type {
      ProxyType::HTTP  => ConfigState::Http(HttpProxy::new(ip_address, port)),
      ProxyType::HTTPS => ConfigState::Tls(TlsProxy::new(ip_address, port)),
      _                => unimplemented!(),
    };

    Proxy {
      tag:        tag,
      id:         id,
      proxy_type: proxy_type,
      channel:    channel,
      state:      state,
      token:      None,
      pid:        pid,
    }
  }
}

impl fmt::Debug for Proxy {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "Proxy {{ tag: {}, proxy_type: {:?}, state: {:?} }}", self.tag, self.proxy_type, self.state)
  }
}

#[derive(Deserialize,Serialize,Debug)]
pub struct StoredProxy {
  pub tag:        String,
  pub proxy_type: ProxyType,
  pub state:      ConfigState,
}

impl StoredProxy {
  pub fn from_proxy(proxy: &Proxy) -> StoredProxy {
    StoredProxy {
      tag:        proxy.tag.clone(),
      proxy_type: proxy.proxy_type.clone(),
      state:      proxy.state.clone(),
    }
  }
}

#[derive(Deserialize,Serialize,Debug)]
pub struct ProxyConfiguration {
  id:      String,
  proxies: Vec<StoredProxy>,
}

pub type Tag = String;

struct CommandServer {
  sock:            UnixListener,
  buffer_size:     usize,
  max_buffer_size: usize,
  conns:           Slab<CommandClient,FrontToken>,
  proxies:         HashMap<Token, (Tag, Proxy)>,
  proxy_count:     usize,
  pub poll:        Poll,
  timer:           Timer<Token>,
}

impl CommandServer {
  fn accept(&mut self) -> io::Result<()> {
    debug!("server accepting socket");

    let acc = self.sock.accept();
    if let Ok(Some((sock, addr))) = acc {
      let conn = CommandClient::new(sock, self.buffer_size, self.max_buffer_size);
      let tok = self.conns.insert(conn)
        .ok().expect("could not add connection to slab");

      // Register the connection
      let token = self.from_front(tok);
      self.conns[tok].token = Some(token);
      let mut interest = Ready::hup();
      interest.insert(Ready::readable());
      interest.insert(Ready::writable());
      self.poll.register(&self.conns[tok].channel.sock, token, interest, PollOpt::edge())
        .ok().expect("could not register socket with event loop");

      let accept_interest = Ready::readable();
      self.poll.reregister(&self.sock, SERVER, accept_interest, PollOpt::edge());
      Ok(())
    } else {
      //FIXME: what do other cases mean, like Ok(None)?
      acc.map(|_| ())
    }
  }

  fn dispatch(&mut self, token: FrontToken, v: Vec<ConfigMessage>) {
    for message in &v {
      self.handle_client_message(token, message);
    }
  }

  fn new(srv: UnixListener, proxies_map: HashMap<String, Vec<Proxy>>, buffer_size: usize, max_buffer_size: usize, poll: Poll) -> CommandServer {
    //FIXME: verify this
    poll.register(&srv, Token(0), Ready::readable(), PollOpt::edge() | PollOpt::oneshot()).unwrap();

    let mut proxies = HashMap::new();

    let mut token_count = 0;
    for (tag, mut proxy_list) in proxies_map {
      for proxy in proxy_list.drain(..) {
        token_count += 1;
        poll.register(&proxy.channel.sock, Token(token_count), Ready::all(), PollOpt::edge()).unwrap();
        proxies.insert(Token(token_count), (tag.clone(), proxy));
      }
    }
    //let mut timer = timer::Builder::default().tick_duration(Duration::from_millis(1000)).build();
    //FIXME: registering the timer makes the timer thread spin too much
    let mut timer = timer::Timer::default();
    //poll.register(&timer, Token(1), Ready::readable(), PollOpt::edge()).unwrap();
    timer.set_timeout(Duration::from_millis(700), Token(0));
    CommandServer {
      sock:            srv,
      buffer_size:     buffer_size,
      max_buffer_size: max_buffer_size,
      conns:           Slab::with_capacity(128),
      proxies:       proxies,
      proxy_count:  token_count,
      poll:            poll,
      timer:           timer,
    }
  }

  pub fn to_front(&self, token: Token) -> FrontToken {
    FrontToken(token.0 - self.proxy_count - 1)
  }

  pub fn from_front(&self, token: FrontToken) -> Token {
    Token(token.0 + self.proxy_count + 1)
  }

}

type Message = ();

impl CommandServer {
  pub fn run(&mut self) {
    let mut events = Events::with_capacity(1024);
    let poll_timeout = Some(Duration::from_millis(1000));
    loop {
      self.poll.poll(&mut events, poll_timeout).unwrap();
      for event in events.iter() {
        self.ready(event.token(), event.kind());
      }
    }
  }

  fn ready(&mut self, token: Token, events: Ready) {
    //trace!("ready: {:?} -> {:?}", token, events);
    match token {
      Token(0) => {
        if events.is_readable() {
          self.accept().unwrap();
        } else {
          error!("received writable for token 0");
        }
      },
      Token(i) if i < self.proxy_count + 1 => {
        let mut messages = {
          let &mut (ref tag, ref mut proxy) =  self.proxies.get_mut(&Token(i)).unwrap();
          proxy.channel.handle_events(events);
          proxy.channel.run();

          let mut messages = Vec::new();
          loop {
            let msg = proxy.channel.read_message();
            if msg.is_none() {
              break;
            } else {
              messages.push(msg.unwrap());
            }
          }

          messages
        };

        for msg in messages.drain(..) {
          self.proxy_handle_message(Token(i), msg);
        }

        {
          let &mut (ref tag, ref mut proxy) =  self.proxies.get_mut(&Token(i)).unwrap();
          proxy.channel.run();
        }

      },
      _ => {
        let conn_token = self.to_front(token);
        if self.conns.contains(conn_token) {
          self.conns[conn_token].channel.handle_events(events);
          self.conns[conn_token].channel.run();

          //FIXME: handle deconnection
          loop {
            let message = self.conns[conn_token].channel.read_message();

            // if the message was too large, we grow the buffer and retry to read if possible
            if message.is_none() {
              if self.conns[conn_token].channel.readiness.is_hup() {
                break;
              }

              if (self.conns[conn_token].channel.interest & self.conns[conn_token].channel.readiness).is_readable() {
                self.conns[conn_token].channel.run();
                continue;
              } else {
                break;
              }
            }

            let message = message.unwrap();
            self.handle_client_message(conn_token, &message);

          }

          self.conns[conn_token].channel.run();

          if self.conns[conn_token].channel.readiness.is_hup() {
            self.poll.deregister(&self.conns[conn_token].channel.sock);
            self.conns.remove(conn_token);
            trace!("closed client [{}]", token.0);
          }
        }
      }
    }
  }

  fn proxy_handle_message(&mut self, token: Token, msg: ServerMessage) {
    println!("got answer msg: {:?}", msg);
    let answer = ConfigMessageAnswer {
      id: msg.id.clone(),
      status: match msg.status {
        ServerMessageStatus::Error(_)   => ConfigMessageStatus::Error,
        ServerMessageStatus::Ok         => ConfigMessageStatus::Ok,
        ServerMessageStatus::Processing => ConfigMessageStatus::Processing,
      },
      message: match msg.status {
                 ServerMessageStatus::Error(s) => s.clone(),
                 _                             => String::new(),
               },
    };
    info!("sending: {:?}", answer);
    for client in self.conns.iter_mut() {
      if let Some(index) = client.has_message_id(&msg.id) {
        client.write_message(&answer);
        client.remove_message_id(index);
      }
    }
  }

}

pub fn start(config: Config, proxies: HashMap<String, Vec<Proxy>>) {
  let buffer_size     = config.command_buffer_size.unwrap_or(10000);
  let max_buffer_size = config.max_command_buffer_size.unwrap_or(buffer_size * 2);
  let saved_state     = config.saved_state.clone();

  let event_loop = Poll::new().unwrap();
  let addr = PathBuf::from(&config.command_socket);
  if let Err(e) = fs::remove_file(&addr) {
    match e.kind() {
      ErrorKind::NotFound => {},
      _ => {
        log!(log::LogLevel::Error, "could not delete previous socket at {:?}: {:?}", addr, e);
        return;
      }
    }
  }
  match UnixListener::bind(&addr) {
    Ok(srv) => {
      if let Err(e) =  fs::set_permissions(&addr, fs::Permissions::from_mode(0o600)) {
        log!( log::LogLevel::Error, "could not set the unix socket permissions: {:?}", e);
        fs::remove_file(&addr);
        return;
      }

      let mut server = CommandServer::new(srv, proxies, buffer_size, max_buffer_size, event_loop);

      server.load_static_application_configuration(&config);

      saved_state.as_ref().map(|state_path| {
        server.load_state("INITIALIZATION", state_path);
      });

      info!("listen for connections");
      server.run();
      //event_loop.run(&mut CommandServer::new(srv, proxies, buffer_size, max_buffer_size)).unwrap()
    },
      Err(e) => {
        log!(log::LogLevel::Error, "could not create unix socket: {:?}", e);
      }
  }
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate test;
#[macro_use] extern crate columnar_derive;

#[derive(Columnar, Debug, Default)]
struct Data {
    id: usize,
    val: f64,
    dummy: [usize; 30],
}

#[bench]
fn data_columnar(b: &mut test::Bencher) {
    let size = 1 << 20;
    let mut a = Vec::with_capacity(size);
    for i in 0..size {
        a.push(Data { id: i, val: 15., ..Data::default()});
    }
    let mut dc = DataColumnar::with_capacity(size);
    dc.extend(a);
    b.iter(|| {
        for mut e in dc.iter_mut() {
            *e.id *= 2;
        }
    })
}

#[bench]
fn data_columnar_add_assign(bench: &mut test::Bencher) {
    let size = 1 << 20;
    let mut a = Vec::with_capacity(size);
    let mut b = Vec::with_capacity(size);
    let mut r = Vec::with_capacity(size);
    for i in 0..size {
        a.push(Data { id: i, val: i as f64 * 0.6, ..Data::default()});
        b.push(Data { id: i + size, val: size as f64 + i as f64 * 0.6, ..Data::default()});
        r.push(Data { id: 0, val: 1., ..Data::default()});
    }
    let mut ca = DataColumnar::with_capacity(size);
    let mut cb = DataColumnar::with_capacity(size);
    let mut cr = DataColumnar::with_capacity(size);
    ca.extend(a);
    cb.extend(b);
    test::black_box(r.first().unwrap().dummy);
    cr.extend(r);
    bench.iter(|| {
        let zip: ::std::iter::Zip<_, _> = ca.iter().zip(cb.iter()).zip(cr.iter_mut());
        for ((ea, eb), mut er) in zip {
            *er.val /= ea.val + eb.val;
        };
    })
}

#[bench]
fn data_row_add_assign(bench: &mut test::Bencher) {
    let size = 1 << 20;
    let mut a = Vec::with_capacity(size);
    let mut b = Vec::with_capacity(size);
    let mut r = Vec::with_capacity(size);
    for i in 0..size {
        a.push(Data { id: i, val: i as f64 * 0.6, ..Data::default()});
        b.push(Data { id: i + size, val: size as f64 + i as f64 * 0.6, ..Data::default()});
        r.push(Data { id: 0, val: 1., ..Data::default()});
    }
    test::black_box(r.first().unwrap().dummy);
    bench.iter(|| {
        let zip: ::std::iter::Zip<_, _> = a.iter().zip(b.iter()).zip(r.iter_mut());
        for ((ea, eb), mut er) in zip {
            er.val /= ea.val + eb.val;
        };
    })
}

#[bench]
fn data_row(b: &mut test::Bencher) {
    let size = 1 << 20;
    let mut a = Vec::with_capacity(size);
    for i in 0..size {
        a.push(Data { id: i, val: 15., ..Data::default()});
    }
    b.iter(|| {
        for mut e in a.iter_mut() {
            e.id *= 2;
        }
    })
}
<commit_msg>bench: Fix compilation error<commit_after>#![feature(test)]

extern crate test;
extern crate columnar;
#[macro_use] extern crate columnar_derive;

#[derive(Columnar, Debug, Default)]
struct Data {
    id: usize,
    val: f64,
    dummy: [usize; 30],
}

#[bench]
fn data_columnar(b: &mut test::Bencher) {
    let size = 1 << 20;
    let mut a = Vec::with_capacity(size);
    for i in 0..size {
        a.push(Data { id: i, val: 15., ..Data::default()});
    }
    let mut dc = DataColumnar::with_capacity(size);
    dc.extend(a);
    b.iter(|| {
        for mut e in dc.iter_mut() {
            *e.id *= 2;
        }
    })
}

#[bench]
fn data_columnar_add_assign(bench: &mut test::Bencher) {
    let size = 1 << 20;
    let mut a = Vec::with_capacity(size);
    let mut b = Vec::with_capacity(size);
    let mut r = Vec::with_capacity(size);
    for i in 0..size {
        a.push(Data { id: i, val: i as f64 * 0.6, ..Data::default()});
        b.push(Data { id: i + size, val: size as f64 + i as f64 * 0.6, ..Data::default()});
        r.push(Data { id: 0, val: 1., ..Data::default()});
    }
    let mut ca = DataColumnar::with_capacity(size);
    let mut cb = DataColumnar::with_capacity(size);
    let mut cr = DataColumnar::with_capacity(size);
    ca.extend(a);
    cb.extend(b);
    test::black_box(r.first().unwrap().dummy);
    cr.extend(r);
    bench.iter(|| {
        let zip: ::std::iter::Zip<_, _> = ca.iter().zip(cb.iter()).zip(cr.iter_mut());
        for ((ea, eb), mut er) in zip {
            *er.val /= ea.val + eb.val;
        };
    })
}

#[bench]
fn data_row_add_assign(bench: &mut test::Bencher) {
    let size = 1 << 20;
    let mut a = Vec::with_capacity(size);
    let mut b = Vec::with_capacity(size);
    let mut r = Vec::with_capacity(size);
    for i in 0..size {
        a.push(Data { id: i, val: i as f64 * 0.6, ..Data::default()});
        b.push(Data { id: i + size, val: size as f64 + i as f64 * 0.6, ..Data::default()});
        r.push(Data { id: 0, val: 1., ..Data::default()});
    }
    test::black_box(r.first().unwrap().dummy);
    bench.iter(|| {
        let zip: ::std::iter::Zip<_, _> = a.iter().zip(b.iter()).zip(r.iter_mut());
        for ((ea, eb), mut er) in zip {
            er.val /= ea.val + eb.val;
        };
    })
}

#[bench]
fn data_row(b: &mut test::Bencher) {
    let size = 1 << 20;
    let mut a = Vec::with_capacity(size);
    for i in 0..size {
        a.push(Data { id: i, val: 15., ..Data::default()});
    }
    b.iter(|| {
        for mut e in a.iter_mut() {
            e.id *= 2;
        }
    })
}
<|endoftext|>


<commit_before>use syntax::ast;
use syntax::ast::{MetaItem, Expr};
use syntax::codemap::Span;
use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::ext::build::AstBuilder;
use syntax::ext::deriving::generic::{Struct, Substructure, TraitDef, ty};
use syntax::ext::deriving::generic::{combine_substructure, EnumMatching, FieldInfo, MethodDef};

pub fn expand_action_annotation(context: &mut ExtCtxt,
                                span: Span,
                                meta_item: &MetaItem,
                                item: &Annotatable,
                                push: &mut FnMut(Annotatable)) {

}<commit_msg>Add file allow annotations for warnings<commit_after>#![allow(dead_code, unused_imports, unused_variables)]

use syntax::ast;
use syntax::ast::{MetaItem, Expr};
use syntax::codemap::Span;
use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::ext::build::AstBuilder;
use syntax::ext::deriving::generic::{Struct, Substructure, TraitDef, ty};
use syntax::ext::deriving::generic::{combine_substructure, EnumMatching, FieldInfo, MethodDef};

pub fn expand_action_annotation(context: &mut ExtCtxt,
                                span: Span,
                                meta_item: &MetaItem,
                                item: &Annotatable,
                                push: &mut FnMut(Annotatable)) {

}<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::sync::Arc;
use std::fmt::Write;
use super::{Command, CommandGroup};
use ::client::Context;
use ::model::Message;
use ::utils::Colour;

fn error_embed(ctx: &Context, message: &Message, input: &str) {
    let _ = ctx.send_message(message.channel_id, |m| m
        .embed(|e| e
            .colour(Colour::dark_red())
            .description(input)));
}

pub fn with_embeds(ctx: &Context,
                   message: &Message,
                   groups: HashMap<String, Arc<CommandGroup>>,
                   args: Vec<String>) -> Result<(), String> {
    if !args.is_empty() {
        let name = args.join(" ");

        for (group_name, group) in groups {
            let mut found: Option<(&String, &Command)> = None;

            if let Some(ref prefix) = group.prefix {
                for (command_name, command) in &group.commands {
                    if name == format!("{} {}", prefix, command_name) {
                        found = Some((command_name, command));
                    }
                }
            } else {
                for (command_name, command) in &group.commands {
                    if name == command_name[..] {
                        found = Some((command_name, command));
                    }
                }
            };

            if let Some((command_name, command)) = found {
                if !command.help_available {
                    error_embed(ctx, message, "**Error**: No help available.");

                    return Ok(());
                }

                let _ = ctx.send_message(message.channel_id, |m| {
                    m.embed(|e| {
                        let mut embed = e.colour(Colour::rosewater())
                            .title(command_name);
                        if let Some(ref desc) = command.desc {
                            embed = embed.field(|f| {
                                f.name("Description")
                                    .value(desc)
                                    .inline(false)
                            });
                        }

                        if let Some(ref usage) = command.usage {
                            embed = embed.field(|f| {
                                f.name("Usage")
                                    .value(&format!("{} {}", command_name, usage))
                            });
                        }

                        if group_name != "Ungrouped" {
                            embed = embed.field(|f| {
                                f.name("Group")
                                    .value(&group_name)
                            });
                        }

                        let available = if command.dm_only {
                            "Only in DM"
                        } else if command.guild_only {
                            "Only in guilds"
                        } else {
                            "In DM and guilds"
                        };

                        embed = embed.field(|f| {
                            f.name("Available")
                                .value(available)
                        });

                        embed
                    })
                });

                return Ok(());
            }
        }

        let error_msg = format!("**Error**: Command `{}` not found.", name);
        error_embed(ctx, message, &error_msg);

        return Ok(());
    }

    let _ = ctx.send_message(message.channel_id, |m| {
        m.embed(|mut e| {
            e = e.colour(Colour::rosewater())
                .description("To get help about individual command, pass its \
                              name as an argument to this command.");

            for (group_name, group) in groups {
                let mut desc = String::new();

                if let Some(ref x) = group.prefix {
                    let _ = write!(desc, "Prefix: {}\n", x);
                }

                desc.push_str("Commands:\n");

                let mut no_commands = true;

                for (n, cmd) in &group.commands {
                    if cmd.help_available {
                        let _ = write!(desc, "`{}`\n", n);

                        no_commands = false;
                    }
                }

                if no_commands {
                    let _ = write!(desc, "*[No commands]*");
                }

                e = e.field(|f| f.name(&group_name).value(&desc));
            }

            e
        })
    });

    Ok(())
}

pub fn plain(ctx: &Context,
             _: &Message,
             groups: HashMap<String, Arc<CommandGroup>>,
             args: Vec<String>) -> Result<(), String> {
    if !args.is_empty() {
        let name = args.join(" ");

        for (group_name, group) in groups {
            let mut found: Option<(&String, &Command)> = None;

            if let Some(ref prefix) = group.prefix {
                for (command_name, command) in &group.commands {
                    if name == format!("{} {}", prefix, command_name) {
                        found = Some((command_name, command));
                    }
                }
            } else {
                for (command_name, command) in &group.commands {
                    if name == command_name[..] {
                        found = Some((command_name, command));
                    }
                }
            };

            if let Some((command_name, command)) = found {
                if !command.help_available {
                    let _ = ctx.say("**Error**: No help available.");
                    return Ok(());
                }

                let mut result = format!("**{}**\n", command_name);

                if let Some(ref desc) = command.desc {
                    let _ = write!(result, "**Description:** {}\n", desc);
                }

                if let Some(ref usage) = command.usage {
                    let _ = write!(result, "**Usage:** {}\n", usage);
                }

                if group_name != "Ungrouped" {
                    let _ = write!(result, "**Group:** {}\n", group_name);
                }

                result.push_str("**Available:** ");
                result.push_str(if command.dm_only {
                    "Only in DM"
                } else if command.guild_only {
                    "Only in guilds"
                } else {
                    "In DM and guilds"
                });
                result.push_str("\n");

                let _ = ctx.say(&result);

                return Ok(());
            }
        }

        let _ = ctx.say(&format!("**Error**: Command `{}` not found.", name));

        return Ok(());
    }

    let mut result = "**Commands**\nTo get help about individual command, pass \
                      its name as an argument to this command.\n\n"
        .to_string();

    for (group_name, group) in groups {
        let _ = write!(result, "**{}:** ", group_name);

        if let Some(ref x) = group.prefix {
            let _ = write!(result, "(prefix: `{}`): ", x);
        }

        let mut no_commands = true;

        for (n, cmd) in &group.commands {
            if cmd.help_available {
                let _ = write!(result, "`{}` ", n);

                no_commands = false;
            }
        }

        if no_commands {
            result.push_str("*[No Commands]*");
        }

        result.push('\n');
    }

    let _ = ctx.say(&result);

    Ok(())
}
<commit_msg>Fix grammar in framework help the command<commit_after>use std::collections::HashMap;
use std::sync::Arc;
use std::fmt::Write;
use super::{Command, CommandGroup};
use ::client::Context;
use ::model::Message;
use ::utils::Colour;

fn error_embed(ctx: &Context, message: &Message, input: &str) {
    let _ = ctx.send_message(message.channel_id, |m| m
        .embed(|e| e
            .colour(Colour::dark_red())
            .description(input)));
}

pub fn with_embeds(ctx: &Context,
                   message: &Message,
                   groups: HashMap<String, Arc<CommandGroup>>,
                   args: Vec<String>) -> Result<(), String> {
    if !args.is_empty() {
        let name = args.join(" ");

        for (group_name, group) in groups {
            let mut found: Option<(&String, &Command)> = None;

            if let Some(ref prefix) = group.prefix {
                for (command_name, command) in &group.commands {
                    if name == format!("{} {}", prefix, command_name) {
                        found = Some((command_name, command));
                    }
                }
            } else {
                for (command_name, command) in &group.commands {
                    if name == command_name[..] {
                        found = Some((command_name, command));
                    }
                }
            };

            if let Some((command_name, command)) = found {
                if !command.help_available {
                    error_embed(ctx, message, "**Error**: No help available.");

                    return Ok(());
                }

                let _ = ctx.send_message(message.channel_id, |m| {
                    m.embed(|e| {
                        let mut embed = e.colour(Colour::rosewater())
                            .title(command_name);
                        if let Some(ref desc) = command.desc {
                            embed = embed.field(|f| {
                                f.name("Description")
                                    .value(desc)
                                    .inline(false)
                            });
                        }

                        if let Some(ref usage) = command.usage {
                            embed = embed.field(|f| {
                                f.name("Usage")
                                    .value(&format!("{} {}", command_name, usage))
                            });
                        }

                        if group_name != "Ungrouped" {
                            embed = embed.field(|f| {
                                f.name("Group")
                                    .value(&group_name)
                            });
                        }

                        let available = if command.dm_only {
                            "Only in DM"
                        } else if command.guild_only {
                            "Only in guilds"
                        } else {
                            "In DM and guilds"
                        };

                        embed = embed.field(|f| {
                            f.name("Available")
                                .value(available)
                        });

                        embed
                    })
                });

                return Ok(());
            }
        }

        let error_msg = format!("**Error**: Command `{}` not found.", name);
        error_embed(ctx, message, &error_msg);

        return Ok(());
    }

    let _ = ctx.send_message(message.channel_id, |m| {
        m.embed(|mut e| {
            e = e.colour(Colour::rosewater())
                .description("To get help with an individual command, pass its \
                              name as an argument to this command.");

            for (group_name, group) in groups {
                let mut desc = String::new();

                if let Some(ref x) = group.prefix {
                    let _ = write!(desc, "Prefix: {}\n", x);
                }

                desc.push_str("Commands:\n");

                let mut no_commands = true;

                for (n, cmd) in &group.commands {
                    if cmd.help_available {
                        let _ = write!(desc, "`{}`\n", n);

                        no_commands = false;
                    }
                }

                if no_commands {
                    let _ = write!(desc, "*[No commands]*");
                }

                e = e.field(|f| f.name(&group_name).value(&desc));
            }

            e
        })
    });

    Ok(())
}

pub fn plain(ctx: &Context,
             _: &Message,
             groups: HashMap<String, Arc<CommandGroup>>,
             args: Vec<String>) -> Result<(), String> {
    if !args.is_empty() {
        let name = args.join(" ");

        for (group_name, group) in groups {
            let mut found: Option<(&String, &Command)> = None;

            if let Some(ref prefix) = group.prefix {
                for (command_name, command) in &group.commands {
                    if name == format!("{} {}", prefix, command_name) {
                        found = Some((command_name, command));
                    }
                }
            } else {
                for (command_name, command) in &group.commands {
                    if name == command_name[..] {
                        found = Some((command_name, command));
                    }
                }
            };

            if let Some((command_name, command)) = found {
                if !command.help_available {
                    let _ = ctx.say("**Error**: No help available.");
                    return Ok(());
                }

                let mut result = format!("**{}**\n", command_name);

                if let Some(ref desc) = command.desc {
                    let _ = write!(result, "**Description:** {}\n", desc);
                }

                if let Some(ref usage) = command.usage {
                    let _ = write!(result, "**Usage:** {}\n", usage);
                }

                if group_name != "Ungrouped" {
                    let _ = write!(result, "**Group:** {}\n", group_name);
                }

                result.push_str("**Available:** ");
                result.push_str(if command.dm_only {
                    "Only in DM"
                } else if command.guild_only {
                    "Only in guilds"
                } else {
                    "In DM and guilds"
                });
                result.push_str("\n");

                let _ = ctx.say(&result);

                return Ok(());
            }
        }

        let _ = ctx.say(&format!("**Error**: Command `{}` not found.", name));

        return Ok(());
    }

    let mut result = "**Commands**\nTo get help about individual command, pass \
                      its name as an argument to this command.\n\n"
        .to_string();

    for (group_name, group) in groups {
        let _ = write!(result, "**{}:** ", group_name);

        if let Some(ref x) = group.prefix {
            let _ = write!(result, "(prefix: `{}`): ", x);
        }

        let mut no_commands = true;

        for (n, cmd) in &group.commands {
            if cmd.help_available {
                let _ = write!(result, "`{}` ", n);

                no_commands = false;
            }
        }

        if no_commands {
            result.push_str("*[No Commands]*");
        }

        result.push('\n');
    }

    let _ = ctx.say(&result);

    Ok(())
}
<|endoftext|>


<commit_before>use std::borrow::{Borrow, BorrowMut};
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut, Range};

use super::{
    AttachmentClear, ClearValue, ClearValueRaw, CommandBuffer, CommandBufferFlags,
    CommandBufferInheritanceInfo, DescriptorSetOffset, IntoRawCommandBuffer, MultiShot, OneShot,
    Primary, RawCommandBuffer, Secondary, Shot, Submittable,
};
use crate::queue::{Capability, Graphics, Supports};
use crate::{buffer, pass, pso, query};
use crate::{Backend, DrawCount, IndexCount, InstanceCount, VertexCount, VertexOffset};

/// Specifies how commands for the following renderpasses will be recorded.
pub enum SubpassContents {
    /// Contents of the subpass will be inline in the command buffer,
    /// NOT in secondary command buffers.
    Inline,
    /// Contents of the subpass will be in secondary command buffers, and
    /// the primary command buffer will only contain `execute_command()` calls
    /// until the subpass or render pass is complete.
    SecondaryBuffers,
}

/// This struct contains all methods for all commands submittable during a subpass.
/// It is used to implement the identical portions of RenderPassInlineEncoder and SubpassCommandBuffer.
///
/// Where methods are undocumented, they are identical to the methods on the `RawCommandBuffer`
/// trait with the same names.
pub struct RenderSubpassCommon<B, C> {
    cmb: C,
    _marker: PhantomData<B>,
}

impl<B: Backend, C: BorrowMut<B::CommandBuffer>> RenderSubpassCommon<B, C> {
    unsafe fn new(cmb: C) -> Self {
        RenderSubpassCommon {
            cmb,
            _marker: PhantomData,
        }
    }

    ///
    pub unsafe fn clear_attachments<T, U>(&mut self, clears: T, rects: U)
    where
        T: IntoIterator,
        T::Item: Borrow<AttachmentClear>,
        U: IntoIterator,
        U::Item: Borrow<pso::ClearRect>,
    {
        self.cmb.borrow_mut().clear_attachments(clears, rects)
    }

    ///
    pub unsafe fn draw(&mut self, vertices: Range<VertexCount>, instances: Range<InstanceCount>) {
        self.cmb.borrow_mut().draw(vertices, instances)
    }

    ///
    pub unsafe fn draw_indexed(
        &mut self,
        indices: Range<IndexCount>,
        base_vertex: VertexOffset,
        instances: Range<InstanceCount>,
    ) {
        self.cmb
            .borrow_mut()
            .draw_indexed(indices, base_vertex, instances)
    }

    ///
    pub unsafe fn draw_indirect(
        &mut self,
        buffer: &B::Buffer,
        offset: buffer::Offset,
        draw_count: DrawCount,
        stride: u32,
    ) {
        self.cmb
            .borrow_mut()
            .draw_indirect(buffer, offset, draw_count, stride)
    }
    ///
    pub unsafe fn draw_indexed_indirect(
        &mut self,
        buffer: &B::Buffer,
        offset: buffer::Offset,
        draw_count: DrawCount,
        stride: u32,
    ) {
        self.cmb
            .borrow_mut()
            .draw_indexed_indirect(buffer, offset, draw_count, stride)
    }

    ///
    pub unsafe fn bind_index_buffer(&mut self, ibv: buffer::IndexBufferView<B>) {
        self.cmb.borrow_mut().bind_index_buffer(ibv)
    }

    ///
    pub unsafe fn bind_vertex_buffers<I, T>(&mut self, first_binding: pso::BufferIndex, buffers: I)
    where
        I: IntoIterator<Item = (T, buffer::Offset)>,
        T: Borrow<B::Buffer>,
    {
        self.cmb
            .borrow_mut()
            .bind_vertex_buffers(first_binding, buffers);
    }

    ///
    pub unsafe fn bind_graphics_pipeline(&mut self, pipeline: &B::GraphicsPipeline) {
        self.cmb.borrow_mut().bind_graphics_pipeline(pipeline)
    }

    ///
    pub unsafe fn bind_graphics_descriptor_sets<I, J>(
        &mut self,
        layout: &B::PipelineLayout,
        first_set: usize,
        sets: I,
        offsets: J,
    ) where
        I: IntoIterator,
        I::Item: Borrow<B::DescriptorSet>,
        J: IntoIterator,
        J::Item: Borrow<DescriptorSetOffset>,
    {
        self.cmb
            .borrow_mut()
            .bind_graphics_descriptor_sets(layout, first_set, sets, offsets)
    }

    ///
    pub unsafe fn set_viewports<T>(&mut self, first_viewport: u32, viewports: T)
    where
        T: IntoIterator,
        T::Item: Borrow<pso::Viewport>,
    {
        self.cmb
            .borrow_mut()
            .set_viewports(first_viewport, viewports)
    }

    ///
    pub unsafe fn set_scissors<T>(&mut self, first_scissor: u32, scissors: T)
    where
        T: IntoIterator,
        T::Item: Borrow<pso::Rect>,
    {
        self.cmb.borrow_mut().set_scissors(first_scissor, scissors)
    }

    ///
    pub unsafe fn set_stencil_reference(&mut self, faces: pso::Face, value: pso::StencilValue) {
        self.cmb.borrow_mut().set_stencil_reference(faces, value);
    }

    ///
    pub unsafe fn set_stencil_read_mask(&mut self, faces: pso::Face, value: pso::StencilValue) {
        self.cmb.borrow_mut().set_stencil_read_mask(faces, value);
    }

    ///
    pub unsafe fn set_stencil_write_mask(&mut self, faces: pso::Face, value: pso::StencilValue) {
        self.cmb.borrow_mut().set_stencil_write_mask(faces, value);
    }

    ///
    pub unsafe fn set_blend_constants(&mut self, cv: pso::ColorValue) {
        self.cmb.borrow_mut().set_blend_constants(cv)
    }

    ///
    pub unsafe fn set_depth_bounds(&mut self, bounds: Range<f32>) {
        self.cmb.borrow_mut().set_depth_bounds(bounds)
    }

    ///
    pub unsafe fn push_graphics_constants(
        &mut self,
        layout: &B::PipelineLayout,
        stages: pso::ShaderStageFlags,
        offset: u32,
        constants: &[u32],
    ) {
        self.cmb
            .borrow_mut()
            .push_graphics_constants(layout, stages, offset, constants);
    }

    ///
    pub unsafe fn set_line_width(&mut self, width: f32) {
        self.cmb.borrow_mut().set_line_width(width);
    }

    ///
    pub unsafe fn set_depth_bias(&mut self, depth_bias: pso::DepthBias) {
        self.cmb.borrow_mut().set_depth_bias(depth_bias);
    }

    // TODO: pipeline barrier (postponed)

    ///
    pub unsafe fn begin_query(&mut self, query: query::Query<B>, flags: query::ControlFlags) {
        self.cmb.borrow_mut().begin_query(query, flags)
    }

    ///
    pub unsafe fn end_query(&mut self, query: query::Query<B>) {
        self.cmb.borrow_mut().end_query(query)
    }

    ///
    pub unsafe fn write_timestamp(&mut self, stage: pso::PipelineStage, query: query::Query<B>) {
        self.cmb.borrow_mut().write_timestamp(stage, query)
    }
}

/// An object that records commands into a command buffer inline, that is,
/// without secondary command buffers.
pub struct RenderPassInlineEncoder<'a, B: Backend>(
    RenderSubpassCommon<B, &'a mut B::CommandBuffer>,
)
where
    B::CommandBuffer: 'a;

impl<'a, B: Backend> RenderPassInlineEncoder<'a, B> {
    /// Creates a new `RenderPassInlineEncoder`, starting a new render
    /// pass in the given `CommandBuffer`.
    pub unsafe fn new<C, T, S: Shot>(
        cmd_buffer: &'a mut CommandBuffer<B, C, S, Primary>,
        render_pass: &B::RenderPass,
        frame_buffer: &B::Framebuffer,
        render_area: pso::Rect,
        clear_values: T,
    ) -> Self
    where
        C: Supports<Graphics>,
        T: IntoIterator,
        T::Item: Borrow<ClearValue>,
    {
        let clear_values = clear_values
            .into_iter()
            .map(|cv| ClearValueRaw::from(*cv.borrow()));

        cmd_buffer.raw.begin_render_pass(
            render_pass,
            frame_buffer,
            render_area,
            clear_values,
            SubpassContents::Inline,
        );

        RenderPassInlineEncoder(RenderSubpassCommon::new(&mut cmd_buffer.raw))
    }

    /// Start the next subpass.
    pub fn next_subpass_inline(self) -> Self {
        unsafe {
            self.0.cmb.next_subpass(SubpassContents::Inline);
        }
        self
    }

    /// Begins recording a new subpass with secondary buffers.
    pub fn next_subpass_secondary(self) -> RenderPassSecondaryEncoder<'a, B> {
        unsafe {
            self.0.cmb.next_subpass(SubpassContents::SecondaryBuffers);
        }
        RenderPassSecondaryEncoder(self.0.cmb)
    }
}

impl<'a, B: Backend> Deref for RenderPassInlineEncoder<'a, B> {
    type Target = RenderSubpassCommon<B, &'a mut B::CommandBuffer>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<'a, B: Backend> DerefMut for RenderPassInlineEncoder<'a, B> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

impl<'a, B: Backend> Drop for RenderPassInlineEncoder<'a, B> {
    fn drop(&mut self) {
        unsafe {
            self.0.cmb.end_render_pass();
        }
    }
}

/// An object that records commands into a command buffer where each command must
/// be a call to execute a secondary command buffer.
pub struct RenderPassSecondaryEncoder<'a, B: Backend>(&'a mut B::CommandBuffer)
where
    B::CommandBuffer: 'a;

impl<'a, B: Backend> RenderPassSecondaryEncoder<'a, B> {
    /// Wraps the given `CommandBuffer` in a `RenderPassSecondaryEncoder`,
    /// starting a new render pass where the actual commands are contained in
    /// secondary command buffers.
    pub unsafe fn new<C, T, S: Shot>(
        cmd_buffer: &'a mut CommandBuffer<B, C, S, Primary>,
        render_pass: &B::RenderPass,
        frame_buffer: &B::Framebuffer,
        render_area: pso::Rect,
        clear_values: T,
    ) -> Self
    where
        C: Supports<Graphics>,
        T: IntoIterator,
        T::Item: Borrow<ClearValue>,
    {
        let clear_values = clear_values
            .into_iter()
            .map(|cv| ClearValueRaw::from(*cv.borrow()));

        cmd_buffer.raw.begin_render_pass(
            render_pass,
            frame_buffer,
            render_area,
            clear_values,
            SubpassContents::SecondaryBuffers,
        );

        RenderPassSecondaryEncoder(&mut cmd_buffer.raw)
    }

    /// Executes the given commands as a secondary command buffer.
    pub unsafe fn execute_commands<'b, T, I>(&mut self, cmd_buffers: I)
    where
        T: 'b + Submittable<B, Graphics, Secondary>,
        I: IntoIterator<Item = &'b T>,
    {
        self.0.execute_commands(cmd_buffers)
    }

    /// Starts a new subpass with inline commands.
    pub fn next_subpass_inline(self) -> RenderPassInlineEncoder<'a, B> {
        unsafe {
            self.0.next_subpass(SubpassContents::Inline);
            RenderPassInlineEncoder(RenderSubpassCommon::new(self.0))
        }
    }

    /// Starts a new subpass with secondary command buffers.
    pub fn next_subpass_secondary(self) -> Self {
        unsafe {
            self.0.next_subpass(SubpassContents::SecondaryBuffers);
        }
        self
    }
}

impl<'a, B: Backend> Drop for RenderPassSecondaryEncoder<'a, B> {
    fn drop(&mut self) {
        unsafe {
            self.0.end_render_pass();
        }
    }
}

/// A secondary command buffer recorded entirely within a subpass.
pub struct SubpassCommandBuffer<B: Backend, S: Shot, R = <B as Backend>::CommandBuffer>(
    RenderSubpassCommon<B, R>,
    PhantomData<S>,
);
impl<B: Backend, S: Shot> SubpassCommandBuffer<B, S> {
    /// Wraps the given `CommandBuffer` in a `SubpassCommandBuffer`, starting
    /// to record a new subpass.
    pub unsafe fn new(raw: B::CommandBuffer) -> Self {
        SubpassCommandBuffer(RenderSubpassCommon::new(raw), PhantomData)
    }

    /// Finish recording commands to the command buffer.
    ///
    /// The command pool must be reset to able to re-record commands.
    pub unsafe fn finish(&mut self) {
        self.0.cmb.finish();
    }
}

impl<B: Backend> SubpassCommandBuffer<B, OneShot> {
    /// Begin recording a one-shot sub-pass command buffer.
    pub unsafe fn begin<'a>(
        &mut self,
        subpass: pass::Subpass<'a, B>,
        framebuffer: Option<&'a B::Framebuffer>,
    ) {
        let flags = CommandBufferFlags::RENDER_PASS_CONTINUE | CommandBufferFlags::ONE_TIME_SUBMIT;
        let inheritance_info = CommandBufferInheritanceInfo {
            subpass: Some(subpass),
            framebuffer,
            ..CommandBufferInheritanceInfo::default()
        };
        self.0.cmb.begin(flags, inheritance_info);
    }
}

impl<B: Backend> SubpassCommandBuffer<B, MultiShot> {
    /// Begin recording a one-shot sub-pass command buffer.
    pub unsafe fn begin<'a>(
        &mut self,
        allow_pending_resubmit: bool,
        subpass: pass::Subpass<'a, B>,
        framebuffer: Option<&'a B::Framebuffer>,
    ) {
        let mut flags = CommandBufferFlags::RENDER_PASS_CONTINUE;
        if allow_pending_resubmit {
            flags |= CommandBufferFlags::SIMULTANEOUS_USE;
        }
        let inheritance_info = CommandBufferInheritanceInfo {
            subpass: Some(subpass),
            framebuffer,
            ..CommandBufferInheritanceInfo::default()
        };
        self.0.cmb.begin(flags, inheritance_info);
    }
}

impl<B: Backend, S: Shot> Deref for SubpassCommandBuffer<B, S> {
    type Target = RenderSubpassCommon<B, B::CommandBuffer>;
    fn deref(&self) -> &RenderSubpassCommon<B, B::CommandBuffer> {
        &self.0
    }
}

impl<B: Backend, S: Shot> DerefMut for SubpassCommandBuffer<B, S> {
    fn deref_mut(&mut self) -> &mut RenderSubpassCommon<B, B::CommandBuffer> {
        &mut self.0
    }
}

impl<B, S, R> Borrow<R> for SubpassCommandBuffer<B, S, R>
where
    B: Backend<CommandBuffer = R>,
    S: Shot,
    R: RawCommandBuffer<B>,
{
    fn borrow(&self) -> &R {
        &self.0.cmb
    }
}

impl<B, C, S> Submittable<B, C, Secondary> for SubpassCommandBuffer<B, S>
where
    B: Backend,
    C: Capability + Supports<Graphics>,
    S: Shot,
{
}

impl<B, S> IntoRawCommandBuffer<B, Graphics> for SubpassCommandBuffer<B, S>
where
    B: Backend,
    S: Shot,
{
    fn into_raw(self) -> B::CommandBuffer {
        self.0.cmb
    }
}
<commit_msg>Prevent render pass encoders from ending render pass multiple times.<commit_after>use std::borrow::{Borrow, BorrowMut};
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut, Range};

use super::{
    AttachmentClear, ClearValue, ClearValueRaw, CommandBuffer, CommandBufferFlags,
    CommandBufferInheritanceInfo, DescriptorSetOffset, IntoRawCommandBuffer, MultiShot, OneShot,
    Primary, RawCommandBuffer, Secondary, Shot, Submittable,
};
use crate::queue::{Capability, Graphics, Supports};
use crate::{buffer, pass, pso, query};
use crate::{Backend, DrawCount, IndexCount, InstanceCount, VertexCount, VertexOffset};

/// Specifies how commands for the following renderpasses will be recorded.
pub enum SubpassContents {
    /// Contents of the subpass will be inline in the command buffer,
    /// NOT in secondary command buffers.
    Inline,
    /// Contents of the subpass will be in secondary command buffers, and
    /// the primary command buffer will only contain `execute_command()` calls
    /// until the subpass or render pass is complete.
    SecondaryBuffers,
}

/// This struct contains all methods for all commands submittable during a subpass.
/// It is used to implement the identical portions of RenderPassInlineEncoder and SubpassCommandBuffer.
///
/// Where methods are undocumented, they are identical to the methods on the `RawCommandBuffer`
/// trait with the same names.
pub struct RenderSubpassCommon<B, C> {
    cmb: C,
    _marker: PhantomData<B>,
}

impl<B: Backend, C: BorrowMut<B::CommandBuffer>> RenderSubpassCommon<B, C> {
    unsafe fn new(cmb: C) -> Self {
        RenderSubpassCommon {
            cmb,
            _marker: PhantomData,
        }
    }

    ///
    pub unsafe fn clear_attachments<T, U>(&mut self, clears: T, rects: U)
    where
        T: IntoIterator,
        T::Item: Borrow<AttachmentClear>,
        U: IntoIterator,
        U::Item: Borrow<pso::ClearRect>,
    {
        self.cmb.borrow_mut().clear_attachments(clears, rects)
    }

    ///
    pub unsafe fn draw(&mut self, vertices: Range<VertexCount>, instances: Range<InstanceCount>) {
        self.cmb.borrow_mut().draw(vertices, instances)
    }

    ///
    pub unsafe fn draw_indexed(
        &mut self,
        indices: Range<IndexCount>,
        base_vertex: VertexOffset,
        instances: Range<InstanceCount>,
    ) {
        self.cmb
            .borrow_mut()
            .draw_indexed(indices, base_vertex, instances)
    }

    ///
    pub unsafe fn draw_indirect(
        &mut self,
        buffer: &B::Buffer,
        offset: buffer::Offset,
        draw_count: DrawCount,
        stride: u32,
    ) {
        self.cmb
            .borrow_mut()
            .draw_indirect(buffer, offset, draw_count, stride)
    }
    ///
    pub unsafe fn draw_indexed_indirect(
        &mut self,
        buffer: &B::Buffer,
        offset: buffer::Offset,
        draw_count: DrawCount,
        stride: u32,
    ) {
        self.cmb
            .borrow_mut()
            .draw_indexed_indirect(buffer, offset, draw_count, stride)
    }

    ///
    pub unsafe fn bind_index_buffer(&mut self, ibv: buffer::IndexBufferView<B>) {
        self.cmb.borrow_mut().bind_index_buffer(ibv)
    }

    ///
    pub unsafe fn bind_vertex_buffers<I, T>(&mut self, first_binding: pso::BufferIndex, buffers: I)
    where
        I: IntoIterator<Item = (T, buffer::Offset)>,
        T: Borrow<B::Buffer>,
    {
        self.cmb
            .borrow_mut()
            .bind_vertex_buffers(first_binding, buffers);
    }

    ///
    pub unsafe fn bind_graphics_pipeline(&mut self, pipeline: &B::GraphicsPipeline) {
        self.cmb.borrow_mut().bind_graphics_pipeline(pipeline)
    }

    ///
    pub unsafe fn bind_graphics_descriptor_sets<I, J>(
        &mut self,
        layout: &B::PipelineLayout,
        first_set: usize,
        sets: I,
        offsets: J,
    ) where
        I: IntoIterator,
        I::Item: Borrow<B::DescriptorSet>,
        J: IntoIterator,
        J::Item: Borrow<DescriptorSetOffset>,
    {
        self.cmb
            .borrow_mut()
            .bind_graphics_descriptor_sets(layout, first_set, sets, offsets)
    }

    ///
    pub unsafe fn set_viewports<T>(&mut self, first_viewport: u32, viewports: T)
    where
        T: IntoIterator,
        T::Item: Borrow<pso::Viewport>,
    {
        self.cmb
            .borrow_mut()
            .set_viewports(first_viewport, viewports)
    }

    ///
    pub unsafe fn set_scissors<T>(&mut self, first_scissor: u32, scissors: T)
    where
        T: IntoIterator,
        T::Item: Borrow<pso::Rect>,
    {
        self.cmb.borrow_mut().set_scissors(first_scissor, scissors)
    }

    ///
    pub unsafe fn set_stencil_reference(&mut self, faces: pso::Face, value: pso::StencilValue) {
        self.cmb.borrow_mut().set_stencil_reference(faces, value);
    }

    ///
    pub unsafe fn set_stencil_read_mask(&mut self, faces: pso::Face, value: pso::StencilValue) {
        self.cmb.borrow_mut().set_stencil_read_mask(faces, value);
    }

    ///
    pub unsafe fn set_stencil_write_mask(&mut self, faces: pso::Face, value: pso::StencilValue) {
        self.cmb.borrow_mut().set_stencil_write_mask(faces, value);
    }

    ///
    pub unsafe fn set_blend_constants(&mut self, cv: pso::ColorValue) {
        self.cmb.borrow_mut().set_blend_constants(cv)
    }

    ///
    pub unsafe fn set_depth_bounds(&mut self, bounds: Range<f32>) {
        self.cmb.borrow_mut().set_depth_bounds(bounds)
    }

    ///
    pub unsafe fn push_graphics_constants(
        &mut self,
        layout: &B::PipelineLayout,
        stages: pso::ShaderStageFlags,
        offset: u32,
        constants: &[u32],
    ) {
        self.cmb
            .borrow_mut()
            .push_graphics_constants(layout, stages, offset, constants);
    }

    ///
    pub unsafe fn set_line_width(&mut self, width: f32) {
        self.cmb.borrow_mut().set_line_width(width);
    }

    ///
    pub unsafe fn set_depth_bias(&mut self, depth_bias: pso::DepthBias) {
        self.cmb.borrow_mut().set_depth_bias(depth_bias);
    }

    // TODO: pipeline barrier (postponed)

    ///
    pub unsafe fn begin_query(&mut self, query: query::Query<B>, flags: query::ControlFlags) {
        self.cmb.borrow_mut().begin_query(query, flags)
    }

    ///
    pub unsafe fn end_query(&mut self, query: query::Query<B>) {
        self.cmb.borrow_mut().end_query(query)
    }

    ///
    pub unsafe fn write_timestamp(&mut self, stage: pso::PipelineStage, query: query::Query<B>) {
        self.cmb.borrow_mut().write_timestamp(stage, query)
    }
}

/// An object that records commands into a command buffer inline, that is,
/// without secondary command buffers.
pub struct RenderPassInlineEncoder<'a, B: Backend>(
    RenderSubpassCommon<B, &'a mut B::CommandBuffer>,
)
where
    B::CommandBuffer: 'a;

impl<'a, B: Backend> RenderPassInlineEncoder<'a, B> {
    /// Creates a new `RenderPassInlineEncoder`, starting a new render
    /// pass in the given `CommandBuffer`.
    pub unsafe fn new<C, T, S: Shot>(
        cmd_buffer: &'a mut CommandBuffer<B, C, S, Primary>,
        render_pass: &B::RenderPass,
        frame_buffer: &B::Framebuffer,
        render_area: pso::Rect,
        clear_values: T,
    ) -> Self
    where
        C: Supports<Graphics>,
        T: IntoIterator,
        T::Item: Borrow<ClearValue>,
    {
        let clear_values = clear_values
            .into_iter()
            .map(|cv| ClearValueRaw::from(*cv.borrow()));

        cmd_buffer.raw.begin_render_pass(
            render_pass,
            frame_buffer,
            render_area,
            clear_values,
            SubpassContents::Inline,
        );

        RenderPassInlineEncoder(RenderSubpassCommon::new(&mut cmd_buffer.raw))
    }

    /// Start the next subpass.
    pub fn next_subpass_inline(self) -> Self {
        unsafe {
            self.0.cmb.next_subpass(SubpassContents::Inline);
        }
        self
    }

    /// Begins recording a new subpass with secondary buffers.
    pub fn next_subpass_secondary(mut self) -> RenderPassSecondaryEncoder<'a, B> {
        unsafe {
            self.0.cmb.next_subpass(SubpassContents::SecondaryBuffers);
            let cmb = std::ptr::read(&mut self.0.cmb);
            std::mem::forget(self); // Prevent `end_render_pass`
            RenderPassSecondaryEncoder(cmb)
        }
    }
}

impl<'a, B: Backend> Deref for RenderPassInlineEncoder<'a, B> {
    type Target = RenderSubpassCommon<B, &'a mut B::CommandBuffer>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<'a, B: Backend> DerefMut for RenderPassInlineEncoder<'a, B> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

impl<'a, B: Backend> Drop for RenderPassInlineEncoder<'a, B> {
    fn drop(&mut self) {
        unsafe {
            self.0.cmb.end_render_pass();
        }
    }
}

/// An object that records commands into a command buffer where each command must
/// be a call to execute a secondary command buffer.
pub struct RenderPassSecondaryEncoder<'a, B: Backend>(&'a mut B::CommandBuffer)
where
    B::CommandBuffer: 'a;

impl<'a, B: Backend> RenderPassSecondaryEncoder<'a, B> {
    /// Wraps the given `CommandBuffer` in a `RenderPassSecondaryEncoder`,
    /// starting a new render pass where the actual commands are contained in
    /// secondary command buffers.
    pub unsafe fn new<C, T, S: Shot>(
        cmd_buffer: &'a mut CommandBuffer<B, C, S, Primary>,
        render_pass: &B::RenderPass,
        frame_buffer: &B::Framebuffer,
        render_area: pso::Rect,
        clear_values: T,
    ) -> Self
    where
        C: Supports<Graphics>,
        T: IntoIterator,
        T::Item: Borrow<ClearValue>,
    {
        let clear_values = clear_values
            .into_iter()
            .map(|cv| ClearValueRaw::from(*cv.borrow()));

        cmd_buffer.raw.begin_render_pass(
            render_pass,
            frame_buffer,
            render_area,
            clear_values,
            SubpassContents::SecondaryBuffers,
        );

        RenderPassSecondaryEncoder(&mut cmd_buffer.raw)
    }

    /// Executes the given commands as a secondary command buffer.
    pub unsafe fn execute_commands<'b, T, I>(&mut self, cmd_buffers: I)
    where
        T: 'b + Submittable<B, Graphics, Secondary>,
        I: IntoIterator<Item = &'b T>,
    {
        self.0.execute_commands(cmd_buffers)
    }

    /// Starts a new subpass with inline commands.
    pub fn next_subpass_inline(mut self) -> RenderPassInlineEncoder<'a, B> {
        unsafe {
            self.0.next_subpass(SubpassContents::Inline);
            let cmb = std::ptr::read(&mut self.0);
            std::mem::forget(self); // Prevent `end_render_pass`
            RenderPassInlineEncoder(RenderSubpassCommon::new(cmb))
        }
    }

    /// Starts a new subpass with secondary command buffers.
    pub fn next_subpass_secondary(self) -> Self {
        unsafe {
            self.0.next_subpass(SubpassContents::SecondaryBuffers);
        }
        self
    }
}

impl<'a, B: Backend> Drop for RenderPassSecondaryEncoder<'a, B> {
    fn drop(&mut self) {
        unsafe {
            self.0.end_render_pass();
        }
    }
}

/// A secondary command buffer recorded entirely within a subpass.
pub struct SubpassCommandBuffer<B: Backend, S: Shot, R = <B as Backend>::CommandBuffer>(
    RenderSubpassCommon<B, R>,
    PhantomData<S>,
);
impl<B: Backend, S: Shot> SubpassCommandBuffer<B, S> {
    /// Wraps the given `CommandBuffer` in a `SubpassCommandBuffer`, starting
    /// to record a new subpass.
    pub unsafe fn new(raw: B::CommandBuffer) -> Self {
        SubpassCommandBuffer(RenderSubpassCommon::new(raw), PhantomData)
    }

    /// Finish recording commands to the command buffer.
    ///
    /// The command pool must be reset to able to re-record commands.
    pub unsafe fn finish(&mut self) {
        self.0.cmb.finish();
    }
}

impl<B: Backend> SubpassCommandBuffer<B, OneShot> {
    /// Begin recording a one-shot sub-pass command buffer.
    pub unsafe fn begin<'a>(
        &mut self,
        subpass: pass::Subpass<'a, B>,
        framebuffer: Option<&'a B::Framebuffer>,
    ) {
        let flags = CommandBufferFlags::RENDER_PASS_CONTINUE | CommandBufferFlags::ONE_TIME_SUBMIT;
        let inheritance_info = CommandBufferInheritanceInfo {
            subpass: Some(subpass),
            framebuffer,
            ..CommandBufferInheritanceInfo::default()
        };
        self.0.cmb.begin(flags, inheritance_info);
    }
}

impl<B: Backend> SubpassCommandBuffer<B, MultiShot> {
    /// Begin recording a one-shot sub-pass command buffer.
    pub unsafe fn begin<'a>(
        &mut self,
        allow_pending_resubmit: bool,
        subpass: pass::Subpass<'a, B>,
        framebuffer: Option<&'a B::Framebuffer>,
    ) {
        let mut flags = CommandBufferFlags::RENDER_PASS_CONTINUE;
        if allow_pending_resubmit {
            flags |= CommandBufferFlags::SIMULTANEOUS_USE;
        }
        let inheritance_info = CommandBufferInheritanceInfo {
            subpass: Some(subpass),
            framebuffer,
            ..CommandBufferInheritanceInfo::default()
        };
        self.0.cmb.begin(flags, inheritance_info);
    }
}

impl<B: Backend, S: Shot> Deref for SubpassCommandBuffer<B, S> {
    type Target = RenderSubpassCommon<B, B::CommandBuffer>;
    fn deref(&self) -> &RenderSubpassCommon<B, B::CommandBuffer> {
        &self.0
    }
}

impl<B: Backend, S: Shot> DerefMut for SubpassCommandBuffer<B, S> {
    fn deref_mut(&mut self) -> &mut RenderSubpassCommon<B, B::CommandBuffer> {
        &mut self.0
    }
}

impl<B, S, R> Borrow<R> for SubpassCommandBuffer<B, S, R>
where
    B: Backend<CommandBuffer = R>,
    S: Shot,
    R: RawCommandBuffer<B>,
{
    fn borrow(&self) -> &R {
        &self.0.cmb
    }
}

impl<B, C, S> Submittable<B, C, Secondary> for SubpassCommandBuffer<B, S>
where
    B: Backend,
    C: Capability + Supports<Graphics>,
    S: Shot,
{
}

impl<B, S> IntoRawCommandBuffer<B, Graphics> for SubpassCommandBuffer<B, S>
where
    B: Backend,
    S: Shot,
{
    fn into_raw(self) -> B::CommandBuffer {
        self.0.cmb
    }
}
<|endoftext|>


<commit_before>//! Utility wrappers to simplify writing OpenGL code.
//!
//! This crate aspires to provide an abstraction over OpenGL's raw API in order to simplify the
//! task of writing higher-level rendering code for OpenGL. `gl-util` is much in the vein of
//! [glutin](https://github.com/tomaka/glium) and [gfx-rs](https://github.com/gfx-rs/gfx) before
//! it, the main difference being that it is much more poorly constructed and is being developed by
//! someone much less experienced with OpenGL.

extern crate bootstrap_gl as gl;

use gl::{BufferName, BufferTarget, BufferUsage, ClearBufferMask, DrawMode, GlType, VertexArrayName};
use std::mem;

pub use gl::{AttributeLocation};
pub use gl::platform::swap_buffers;

/// Initializes global OpenGL state and creates the OpenGL context needed to perform rendering.
pub fn init() {
    gl::create_context();
}

/// TODO: Take clear mask (and values) as parameters.
pub fn clear() {
    unsafe { gl::clear(ClearBufferMask::Color); }
}

/// Represents a buffer of vertex data and the layout of that data.
///
/// Wraps a vertex buffer object and vertex array object into one struct.
#[derive(Debug)]
pub struct VertexBuffer {
    buffer_name: BufferName,
    vertex_array_name: VertexArrayName,
}

impl VertexBuffer {
    /// Creates a new `VertexBuffer` object.
    pub fn new() -> VertexBuffer {
        let mut buffer_name = BufferName::null();
        let mut vertex_array_name = VertexArrayName::null();
        unsafe {
            gl::gen_buffers(1, &mut buffer_name);
            gl::gen_vertex_arrays(1, &mut vertex_array_name);
        }

        VertexBuffer {
            buffer_name: buffer_name,
            vertex_array_name: vertex_array_name,
        }
    }

    /// Fills the buffer with the contents of the data slice.
    pub fn set_data(&mut self, data: &[f32]) {
        let data_ptr = data.as_ptr() as *const ();
        let byte_count = data.len() * mem::size_of::<f32>();

        unsafe {
            gl::bind_buffer(BufferTarget::Array, self.buffer_name);
            gl::buffer_data(
                BufferTarget::Array,
                byte_count as isize,
                data_ptr,
                BufferUsage::StaticDraw);
            gl::bind_buffer(BufferTarget::Array, BufferName::null());
        }
    }

    /// Specifies how the data for a particular vertex attribute is laid out in the buffer.
    pub fn set_attrib(
        &mut self,
        attrib: AttributeLocation,
        elements: usize,
        stride: usize,
        offset: usize
    ) {
        unsafe {
            gl::bind_buffer(BufferTarget::Array, self.buffer_name);
            gl::bind_vertex_array(self.vertex_array_name);

            gl::enable_vertex_attrib_array(AttributeLocation::from_index(0));
            gl::vertex_attrib_pointer(
                attrib,
                elements as i32,
                GlType::Float,
                false,
                stride as i32,
                offset);

            gl::bind_vertex_array(VertexArrayName::null());
            gl::bind_buffer(BufferTarget::Array, BufferName::null());
        }
    }

    /// Draws the contents of the vertex buffer to the screen.
    pub fn draw(&self) {
        unsafe {
            gl::bind_buffer(BufferTarget::Array, self.buffer_name);
            gl::bind_vertex_array(self.vertex_array_name);

            gl::draw_arrays(DrawMode::Triangles, 0, 3);

            gl::bind_vertex_array(VertexArrayName::null());
            gl::bind_buffer(BufferTarget::Array, BufferName::null());
        }
    }
}

impl Drop for VertexBuffer {
    fn drop(&mut self) {
        unsafe {
            gl::delete_buffers(1, &mut self.buffer_name);
            gl::delete_vertex_arrays(1, &mut self.vertex_array_name);
        }
    }
}
<commit_msg>Add Type Info For VertexBuffer Methods<commit_after>//! Utility wrappers to simplify writing OpenGL code.
//!
//! This crate aspires to provide an abstraction over OpenGL's raw API in order to simplify the
//! task of writing higher-level rendering code for OpenGL. `gl-util` is much in the vein of
//! [glutin](https://github.com/tomaka/glium) and [gfx-rs](https://github.com/gfx-rs/gfx) before
//! it, the main difference being that it is much more poorly constructed and is being developed by
//! someone much less experienced with OpenGL.

extern crate bootstrap_gl as gl;

use gl::{BufferName, BufferTarget, BufferUsage, ClearBufferMask, DrawMode, GlType, VertexArrayName};
use std::mem;

pub use gl::{AttributeLocation};
pub use gl::platform::swap_buffers;

/// Initializes global OpenGL state and creates the OpenGL context needed to perform rendering.
pub fn init() {
    gl::create_context();
}

/// TODO: Take clear mask (and values) as parameters.
pub fn clear() {
    unsafe { gl::clear(ClearBufferMask::Color); }
}

/// Represents a buffer of vertex data and the layout of that data.
///
/// Wraps a vertex buffer object and vertex array object into one struct.
#[derive(Debug)]
pub struct VertexBuffer {
    buffer_name: BufferName,
    vertex_array_name: VertexArrayName,
}

impl VertexBuffer {
    /// Creates a new `VertexBuffer` object.
    pub fn new() -> VertexBuffer {
        let mut buffer_name = BufferName::null();
        let mut vertex_array_name = VertexArrayName::null();
        unsafe {
            gl::gen_buffers(1, &mut buffer_name);
            gl::gen_vertex_arrays(1, &mut vertex_array_name);
        }

        VertexBuffer {
            buffer_name: buffer_name,
            vertex_array_name: vertex_array_name,
        }
    }

    /// Fills the buffer with the contents of the data slice.
    pub fn set_data_f32(&mut self, data: &[f32]) {
        let data_ptr = data.as_ptr() as *const ();
        let byte_count = data.len() * mem::size_of::<f32>();

        unsafe {
            gl::bind_buffer(BufferTarget::Array, self.buffer_name);
            gl::buffer_data(
                BufferTarget::Array,
                byte_count as isize,
                data_ptr,
                BufferUsage::StaticDraw);
            gl::bind_buffer(BufferTarget::Array, BufferName::null());
        }
    }

    /// Specifies how the data for a particular vertex attribute is laid out in the buffer.
    pub fn set_attrib_f32(
        &mut self,
        attrib: AttributeLocation,
        elements: usize,
        stride: usize,
        offset: usize
    ) {
        unsafe {
            gl::bind_buffer(BufferTarget::Array, self.buffer_name);
            gl::bind_vertex_array(self.vertex_array_name);

            gl::enable_vertex_attrib_array(AttributeLocation::from_index(0));
            gl::vertex_attrib_pointer(
                attrib,
                elements as i32,
                GlType::Float,
                false,
                stride as i32,
                offset);

            gl::bind_vertex_array(VertexArrayName::null());
            gl::bind_buffer(BufferTarget::Array, BufferName::null());
        }
    }

    /// Draws the contents of the vertex buffer to the screen.
    pub fn draw(&self) {
        unsafe {
            gl::bind_buffer(BufferTarget::Array, self.buffer_name);
            gl::bind_vertex_array(self.vertex_array_name);

            gl::draw_arrays(DrawMode::Triangles, 0, 3);

            gl::bind_vertex_array(VertexArrayName::null());
            gl::bind_buffer(BufferTarget::Array, BufferName::null());
        }
    }
}

impl Drop for VertexBuffer {
    fn drop(&mut self) {
        unsafe {
            gl::delete_buffers(1, &mut self.buffer_name);
            gl::delete_vertex_arrays(1, &mut self.vertex_array_name);
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>allow next/prev grapheme offset from non codepoint boundaries<commit_after><|endoftext|>


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

//! Generating numbers between two others.

// this is surprisingly complicated to be both generic & correct

use core::prelude::PartialOrd;

use Rng;
use distributions::{Sample, IndependentSample};

/// Sample values uniformly between two bounds.
///
/// This gives a uniform distribution (assuming the RNG used to sample
/// it is itself uniform & the `SampleRange` implementation for the
/// given type is correct), even for edge cases like `low = 0`,
/// `high = 170`, for which a naive modulo operation would return
/// numbers less than 85 with double the probability to those greater
/// than 85.
///
/// Types should attempt to sample in `[low, high)`, i.e., not
/// including `high`, but this may be very difficult. All the
/// primitive integer types satisfy this property, and the float types
/// normally satisfy it, but rounding may mean `high` can occur.
pub struct Range<X> {
    low: X,
    range: X,
    accept_zone: X
}

impl<X: SampleRange + PartialOrd> Range<X> {
    /// Create a new `Range` instance that samples uniformly from
    /// `[low, high)`. Panics if `low >= high`.
    pub fn new(low: X, high: X) -> Range<X> {
        assert!(low < high, "Range::new called with `low >= high`");
        SampleRange::construct_range(low, high)
    }
}

impl<Sup: SampleRange> Sample<Sup> for Range<Sup> {
    #[inline]
    fn sample<R: Rng>(&mut self, rng: &mut R) -> Sup { self.ind_sample(rng) }
}
impl<Sup: SampleRange> IndependentSample<Sup> for Range<Sup> {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> Sup {
        SampleRange::sample_range(self, rng)
    }
}

/// The helper trait for types that have a sensible way to sample
/// uniformly between two values. This should not be used directly,
/// and is only to facilitate `Range`.
pub trait SampleRange {
    /// Construct the `Range` object that `sample_range`
    /// requires. This should not ever be called directly, only via
    /// `Range::new`, which will check that `low < high`, so this
    /// function doesn't have to repeat the check.
    fn construct_range(low: Self, high: Self) -> Range<Self>;

    /// Sample a value from the given `Range` with the given `Rng` as
    /// a source of randomness.
    fn sample_range<R: Rng>(r: &Range<Self>, rng: &mut R) -> Self;
}

macro_rules! integer_impl {
    ($ty:ident, $unsigned:ident) => {
        impl SampleRange for $ty {
            // we play free and fast with unsigned vs signed here
            // (when $ty is signed), but that's fine, since the
            // contract of this macro is for $ty and $unsigned to be
            // "bit-equal", so casting between them is a no-op & a
            // bijection.

            fn construct_range(low: $ty, high: $ty) -> Range<$ty> {
                let range = (high as $unsigned).wrapping_sub(low as $unsigned);
                let unsigned_max: $unsigned = $unsigned::max_value();

                // this is the largest number that fits into $unsigned
                // that `range` divides evenly, so, if we've sampled
                // `n` uniformly from this region, then `n % range` is
                // uniform in [0, range)
                let zone = unsigned_max - unsigned_max % range;

                Range {
                    low: low,
                    range: range as $ty,
                    accept_zone: zone as $ty
                }
            }
            #[inline]
            fn sample_range<R: Rng>(r: &Range<$ty>, rng: &mut R) -> $ty {
                loop {
                    // rejection sample
                    let v = rng.gen::<$unsigned>();
                    // until we find something that fits into the
                    // region which r.range evenly divides (this will
                    // be uniformly distributed)
                    if v < r.accept_zone as $unsigned {
                        // and return it, with some adjustments
                        return r.low.wrapping_add((v % r.range as $unsigned) as $ty);
                    }
                }
            }
        }
    }
}

integer_impl! { i8, u8 }
integer_impl! { i16, u16 }
integer_impl! { i32, u32 }
integer_impl! { i64, u64 }
integer_impl! { isize, usize }
integer_impl! { u8, u8 }
integer_impl! { u16, u16 }
integer_impl! { u32, u32 }
integer_impl! { u64, u64 }
integer_impl! { usize, usize }

macro_rules! float_impl {
    ($ty:ty) => {
        impl SampleRange for $ty {
            fn construct_range(low: $ty, high: $ty) -> Range<$ty> {
                Range {
                    low: low,
                    range: high - low,
                    accept_zone: 0.0 // unused
                }
            }
            fn sample_range<R: Rng>(r: &Range<$ty>, rng: &mut R) -> $ty {
                r.low + r.range * rng.gen::<$ty>()
            }
        }
    }
}

float_impl! { f32 }
float_impl! { f64 }

#[cfg(test)]
mod tests {
    use std::prelude::v1::*;
    use distributions::{Sample, IndependentSample};
    use super::Range as Range;

    #[should_panic]
    #[test]
    fn test_range_bad_limits_equal() {
        Range::new(10, 10);
    }
    #[should_panic]
    #[test]
    fn test_range_bad_limits_flipped() {
        Range::new(10, 5);
    }

    #[test]
    fn test_integers() {
        let mut rng = ::test::rng();
        macro_rules! t {
            ($($ty:ident),*) => {{
                $(
                   let v: &[($ty, $ty)] = &[(0, 10),
                                            (10, 127),
                                            ($ty::min_value(), $ty::max_value())];
                   for &(low, high) in v {
                        let mut sampler: Range<$ty> = Range::new(low, high);
                        for _ in 0..1000 {
                            let v = sampler.sample(&mut rng);
                            assert!(low <= v && v < high);
                            let v = sampler.ind_sample(&mut rng);
                            assert!(low <= v && v < high);
                        }
                    }
                 )*
            }}
        }
        t!(i8, i16, i32, i64, isize,
           u8, u16, u32, u64, usize)
    }

    #[test]
    fn test_floats() {
        let mut rng = ::test::rng();
        macro_rules! t {
            ($($ty:ty),*) => {{
                $(
                   let v: &[($ty, $ty)] = &[(0.0, 100.0),
                                            (-1e35, -1e25),
                                            (1e-35, 1e-25),
                                            (-1e35, 1e35)];
                   for &(low, high) in v {
                        let mut sampler: Range<$ty> = Range::new(low, high);
                        for _ in 0..1000 {
                            let v = sampler.sample(&mut rng);
                            assert!(low <= v && v < high);
                            let v = sampler.ind_sample(&mut rng);
                            assert!(low <= v && v < high);
                        }
                    }
                 )*
            }}
        }

        t!(f32, f64)
    }

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

//! Generating numbers between two others.

// this is surprisingly complicated to be both generic & correct

use core::prelude::PartialOrd;

use Rng;
use distributions::{Sample, IndependentSample};

/// Sample values uniformly between two bounds.
///
/// This gives a uniform distribution (assuming the RNG used to sample
/// it is itself uniform & the `SampleRange` implementation for the
/// given type is correct), even for edge cases like `low = 0`,
/// `high = 170`, for which a naive modulo operation would return
/// numbers less than 85 with double the probability to those greater
/// than 85.
///
/// Types should attempt to sample in `[low, high)`, i.e., not
/// including `high`, but this may be very difficult. All the
/// primitive integer types satisfy this property, and the float types
/// normally satisfy it, but rounding may mean `high` can occur.
pub struct Range<X> {
    low: X,
    range: X,
    accept_zone: X
}

impl<X: SampleRange + PartialOrd> Range<X> {
    /// Create a new `Range` instance that samples uniformly from
    /// `[low, high)`. Panics if `low >= high`.
    pub fn new(low: X, high: X) -> Range<X> {
        assert!(low < high, "Range::new called with `low >= high`");
        SampleRange::construct_range(low, high)
    }
}

impl<Sup: SampleRange> Sample<Sup> for Range<Sup> {
    #[inline]
    fn sample<R: Rng>(&mut self, rng: &mut R) -> Sup { self.ind_sample(rng) }
}
impl<Sup: SampleRange> IndependentSample<Sup> for Range<Sup> {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> Sup {
        SampleRange::sample_range(self, rng)
    }
}

/// The helper trait for types that have a sensible way to sample
/// uniformly between two values. This should not be used directly,
/// and is only to facilitate `Range`.
#[doc(hidden)]
pub trait SampleRange {
    /// Construct the `Range` object that `sample_range`
    /// requires. This should not ever be called directly, only via
    /// `Range::new`, which will check that `low < high`, so this
    /// function doesn't have to repeat the check.
    fn construct_range(low: Self, high: Self) -> Range<Self>;

    /// Sample a value from the given `Range` with the given `Rng` as
    /// a source of randomness.
    fn sample_range<R: Rng>(r: &Range<Self>, rng: &mut R) -> Self;
}

macro_rules! integer_impl {
    ($ty:ident, $unsigned:ident) => {
        impl SampleRange for $ty {
            // we play free and fast with unsigned vs signed here
            // (when $ty is signed), but that's fine, since the
            // contract of this macro is for $ty and $unsigned to be
            // "bit-equal", so casting between them is a no-op & a
            // bijection.

            fn construct_range(low: $ty, high: $ty) -> Range<$ty> {
                let range = (high as $unsigned).wrapping_sub(low as $unsigned);
                let unsigned_max: $unsigned = $unsigned::max_value();

                // this is the largest number that fits into $unsigned
                // that `range` divides evenly, so, if we've sampled
                // `n` uniformly from this region, then `n % range` is
                // uniform in [0, range)
                let zone = unsigned_max - unsigned_max % range;

                Range {
                    low: low,
                    range: range as $ty,
                    accept_zone: zone as $ty
                }
            }
            #[inline]
            fn sample_range<R: Rng>(r: &Range<$ty>, rng: &mut R) -> $ty {
                loop {
                    // rejection sample
                    let v = rng.gen::<$unsigned>();
                    // until we find something that fits into the
                    // region which r.range evenly divides (this will
                    // be uniformly distributed)
                    if v < r.accept_zone as $unsigned {
                        // and return it, with some adjustments
                        return r.low.wrapping_add((v % r.range as $unsigned) as $ty);
                    }
                }
            }
        }
    }
}

integer_impl! { i8, u8 }
integer_impl! { i16, u16 }
integer_impl! { i32, u32 }
integer_impl! { i64, u64 }
integer_impl! { isize, usize }
integer_impl! { u8, u8 }
integer_impl! { u16, u16 }
integer_impl! { u32, u32 }
integer_impl! { u64, u64 }
integer_impl! { usize, usize }

macro_rules! float_impl {
    ($ty:ty) => {
        impl SampleRange for $ty {
            fn construct_range(low: $ty, high: $ty) -> Range<$ty> {
                Range {
                    low: low,
                    range: high - low,
                    accept_zone: 0.0 // unused
                }
            }
            fn sample_range<R: Rng>(r: &Range<$ty>, rng: &mut R) -> $ty {
                r.low + r.range * rng.gen::<$ty>()
            }
        }
    }
}

float_impl! { f32 }
float_impl! { f64 }

#[cfg(test)]
mod tests {
    use std::prelude::v1::*;
    use distributions::{Sample, IndependentSample};
    use super::Range as Range;

    #[should_panic]
    #[test]
    fn test_range_bad_limits_equal() {
        Range::new(10, 10);
    }
    #[should_panic]
    #[test]
    fn test_range_bad_limits_flipped() {
        Range::new(10, 5);
    }

    #[test]
    fn test_integers() {
        let mut rng = ::test::rng();
        macro_rules! t {
            ($($ty:ident),*) => {{
                $(
                   let v: &[($ty, $ty)] = &[(0, 10),
                                            (10, 127),
                                            ($ty::min_value(), $ty::max_value())];
                   for &(low, high) in v {
                        let mut sampler: Range<$ty> = Range::new(low, high);
                        for _ in 0..1000 {
                            let v = sampler.sample(&mut rng);
                            assert!(low <= v && v < high);
                            let v = sampler.ind_sample(&mut rng);
                            assert!(low <= v && v < high);
                        }
                    }
                 )*
            }}
        }
        t!(i8, i16, i32, i64, isize,
           u8, u16, u32, u64, usize)
    }

    #[test]
    fn test_floats() {
        let mut rng = ::test::rng();
        macro_rules! t {
            ($($ty:ty),*) => {{
                $(
                   let v: &[($ty, $ty)] = &[(0.0, 100.0),
                                            (-1e35, -1e25),
                                            (1e-35, 1e-25),
                                            (-1e35, 1e35)];
                   for &(low, high) in v {
                        let mut sampler: Range<$ty> = Range::new(low, high);
                        for _ in 0..1000 {
                            let v = sampler.sample(&mut rng);
                            assert!(low <= v && v < high);
                            let v = sampler.ind_sample(&mut rng);
                            assert!(low <= v && v < high);
                        }
                    }
                 )*
            }}
        }

        t!(f32, f64)
    }

}
<|endoftext|>