<commit_before>//! Issues interface

use std::io::Result;
use self::super::{Github, SortDirection, State};
use rep::{Issue, IssueReq, Label};
use rustc_serialize::json;
use std::fmt;
use std::default::Default;

pub enum Filter {
  Assigned,
  Created,
  Mentioned,
  Subscribed,
  All
}

impl fmt::Display for Filter {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{}", match *self {
      Filter::Assigned => "assigned",
      Filter::Created => "created",
      Filter::Mentioned => "mentioned",
      Filter::Subscribed => "subscribed",
      Filter::All => "all"
    })
  }
}

impl Default for Filter {
  fn default() -> Filter {
    Filter::Assigned
  }
}

pub enum Sort {
  Created,
  Updated,
  Comments
}

impl fmt::Display for Sort {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{}", match *self {
      Sort::Created => "created",
      Sort::Updated => "updated",
      Sort::Comments => "comments"
    })
  }
}

impl Default for Sort {
  fn default() -> Sort {
    Sort::Created
  }
}

pub struct IssueLabels<'a> {
  github: &'a Github<'a>,
  owner: &'static str,
  repo: &'static str,
  number: &'static i64
}

impl<'a> IssueLabels<'a> {
  pub fn new(github: &'a Github<'a>, owner: &'static str, repo: &'static str, number: &'static i64) -> IssueLabels<'a> {
    IssueLabels {
      github: github,
      owner: owner,
      repo: repo,
      number: number
    }
  }

  fn path(&self, more: &str) -> String {
    format!("/repos/{}/{}/issues/{}/labels{}", self.owner, self.repo, self.number, more)
  }

  /// add a set of labels to this issue ref
  pub fn add(&self, labels: Vec<&str>) -> Result<Vec<Label>> {
    let body = try!(self.github.post(
      &self.path(""),
      json::encode(&labels).unwrap().as_bytes()
    ));
    Ok(json::decode::<Vec<Label>>(&body).unwrap())
  }

  /// remove a label from this issue
  pub fn remove(&self, label: &'static str) -> Result<()> {
    self.github.delete(
      &self.path(
        &format!("/{}", label)
      )
    ).map(|_| ())
  }

  /// replace all labels associated with this issue with a new set.
  /// providing an empty set of labels is the same as clearing the
  /// current labels
  pub fn set(&self, labels: Vec<&str>) -> Result<Vec<Label>> {
    let body = try!(self.github.patch(
      &self.path(""),
      json::encode(&labels).unwrap().as_bytes()
    ));
    Ok(json::decode::<Vec<Label>>(&body).unwrap())
  }

  /// remove all labels from an issue
  pub fn clear(&self) -> Result<()> {
    self.github.delete(
      &self.path("")
    ).map(|_| ())
  }
}

pub struct IssueRef<'a> {
  github: &'a Github<'a>,
  owner: &'static str,
  repo: &'static str,
  number: &'static i64
}

impl<'a> IssueRef<'a> {
  /// create a new instance of a github repo issue ref
  pub fn new(
    github: &'a Github<'a>, owner: &'static str, repo: &'static str,
    number: &'static i64) -> IssueRef<'a> {
    IssueRef {
      github: github,
      owner: owner,
      repo: repo,
      number: number
    }
  }

  fn path(&self, more: &str) -> String {
    format!("/repos/{}/{}/issues/{}{}", self.owner, self.repo, self.number, more)
  }

  pub fn labels(&self) -> IssueLabels {
    IssueLabels::new(self.github, self.owner, self.repo, self.number)
  }

  pub fn edit(&self, is: &IssueReq) -> Result<Issue> {
    let data = json::encode(&is).unwrap();
    let body = try!(
      self.github.patch(
        &self.path(""),
        data.as_bytes()
      )
    );
    Ok(json::decode::<Issue>(&body).unwrap())
  }
}

pub struct Issues<'a> {
  github: &'a Github<'a>,
  owner: &'static str,
  repo: &'static str
}

/// an mutable issue list builder
pub struct ListBuilder<'a> {
  issues: &'a Issues<'a>,
  state: State,
  sort: Sort,
  direction: SortDirection,
  assignee: Option<&'static str>,
  creator: Option<&'static str>,
  mentioned: Option<&'static str>,
  labels: Vec<&'static str>,
  since: Option<&'static str>
}

impl<'a> ListBuilder<'a> {

  pub fn new(is: &'a Issues<'a>) -> ListBuilder<'a> {
    ListBuilder {
      issues: is,
      state: Default::default(),
      sort: Default::default(),
      direction: Default::default(),
      assignee: None,
      creator: None,
      mentioned: None,
      labels: vec![],
      since: None
    }
  }

  pub fn state(&mut self, state: State) -> &mut ListBuilder<'a> {
    self.state = state;
    self
  }

  pub fn sort(&mut self, sort: Sort) -> &mut ListBuilder<'a> {
    self.sort = sort;
    self
  }

  pub fn direction(&mut self, direction: SortDirection) -> &mut ListBuilder<'a> {
    self.direction = direction;
    self
  }

  pub fn assignee(&mut self, assignee: &'static str) -> &mut ListBuilder<'a> {
    self.assignee = Some(assignee);
    self
  }

  pub fn creator(&mut self, creator: &'static str) -> &mut ListBuilder<'a> {
    self.creator = Some(creator);
    self
  }

  pub fn mentioned(&mut self, mentioned: &'static str) -> &mut ListBuilder<'a> {
    self.mentioned = Some(mentioned);
    self
  }

  pub fn labels(&mut self, labels: Vec<&'static str>) -> &mut ListBuilder<'a> {
    self.labels = labels;
    self
  }

  pub fn since(&mut self, since: &'static str) -> &mut ListBuilder<'a> {
    self.since = Some(since);
    self
  }

  pub fn get(&self) -> Result<Vec<Issue>> {
    let mut params = Vec::new();
    params.push(format!("state={}", self.state));
    params.push(format!("sort={}", self.sort));
    params.push(format!("direction={}", self.direction));
    if let Some(a) = self.assignee {
      params.push(format!("assignee={}", a));
    }
    if let Some(c) = self.creator {
      params.push(format!("creator={}", c));
    }
    if let Some(m) = self.mentioned {
      params.push(format!("mentioned={}", m));
    }
    if let Some(s) = self.since {
      params.push(format!("since={}", s));
    }
    if !self.labels.is_empty() {
      params.push(format!("labels={}", self.labels.connect(",")));
    }
    println!("params {:?}", params);
    let url = self.issues.path(
      &format!("?{}", params.connect("&"))
    );
    let body = try!(
      self.issues.github.get(
        &url
      )
    );
    Ok(json::decode::<Vec<Issue>>(&body).unwrap())
  }

}

impl<'a> Issues<'a> {
  /// create a new instance of a github repo issue ref
  pub fn new(
    github: &'a Github<'a>, owner: &'static str, repo: &'static str) -> Issues<'a> {
    Issues {
      github: github,
      owner: owner,
      repo: repo
    }
  }

  fn path(&self, more: &str) -> String {
    format!("/repos/{}/{}/issues{}", self.owner, self.repo, more)
  }

  pub fn get(&self, number: &'static i64) -> IssueRef {
    IssueRef::new(self.github, self.owner, self.repo, number)
  }

  pub fn create(&self, is: &IssueReq) -> Result<Issue> {
    let data = json::encode(&is).unwrap();
    let body = try!(
      self.github.post(
        &self.path(""),
        data.as_bytes()
      )
    );
    Ok(json::decode::<Issue>(&body).unwrap())
  }

  pub fn list(&self) -> ListBuilder {
    ListBuilder::new(self)
  }
}
<commit_msg>spacing<commit_after>//! Issues interface

use std::io::Result;
use self::super::{Github, SortDirection, State};
use rep::{Issue, IssueReq, Label};
use rustc_serialize::json;
use std::fmt;
use std::default::Default;

pub enum Filter {
  Assigned,
  Created,
  Mentioned,
  Subscribed,
  All
}

impl fmt::Display for Filter {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{}", match *self {
      Filter::Assigned => "assigned",
      Filter::Created => "created",
      Filter::Mentioned => "mentioned",
      Filter::Subscribed => "subscribed",
      Filter::All => "all"
    })
  }
}

impl Default for Filter {
  fn default() -> Filter {
    Filter::Assigned
  }
}

pub enum Sort {
  Created,
  Updated,
  Comments
}

impl fmt::Display for Sort {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{}", match *self {
      Sort::Created => "created",
      Sort::Updated => "updated",
      Sort::Comments => "comments"
    })
  }
}

impl Default for Sort {
  fn default() -> Sort {
    Sort::Created
  }
}

pub struct IssueLabels<'a> {
  github: &'a Github<'a>,
  owner: &'static str,
  repo: &'static str,
  number: &'static i64
}

impl<'a> IssueLabels<'a> {
  pub fn new(
    github: &'a Github<'a>,
    owner: &'static str,
    repo: &'static str,
    number: &'static i64) -> IssueLabels<'a> {
    IssueLabels {
      github: github,
      owner: owner,
      repo: repo,
      number: number
    }
  }

  fn path(&self, more: &str) -> String {
    format!("/repos/{}/{}/issues/{}/labels{}", self.owner, self.repo, self.number, more)
  }

  /// add a set of labels to this issue ref
  pub fn add(&self, labels: Vec<&str>) -> Result<Vec<Label>> {
    let body = try!(self.github.post(
      &self.path(""),
      json::encode(&labels).unwrap().as_bytes()
    ));
    Ok(json::decode::<Vec<Label>>(&body).unwrap())
  }

  /// remove a label from this issue
  pub fn remove(&self, label: &'static str) -> Result<()> {
    self.github.delete(
      &self.path(
        &format!("/{}", label)
      )
    ).map(|_| ())
  }

  /// replace all labels associated with this issue with a new set.
  /// providing an empty set of labels is the same as clearing the
  /// current labels
  pub fn set(&self, labels: Vec<&str>) -> Result<Vec<Label>> {
    let body = try!(self.github.patch(
      &self.path(""),
      json::encode(&labels).unwrap().as_bytes()
    ));
    Ok(json::decode::<Vec<Label>>(&body).unwrap())
  }

  /// remove all labels from an issue
  pub fn clear(&self) -> Result<()> {
    self.github.delete(
      &self.path("")
    ).map(|_| ())
  }
}

pub struct IssueRef<'a> {
  github: &'a Github<'a>,
  owner: &'static str,
  repo: &'static str,
  number: &'static i64
}

impl<'a> IssueRef<'a> {
  /// create a new instance of a github repo issue ref
  pub fn new(
    github: &'a Github<'a>, owner: &'static str, repo: &'static str,
    number: &'static i64) -> IssueRef<'a> {
    IssueRef {
      github: github,
      owner: owner,
      repo: repo,
      number: number
    }
  }

  fn path(&self, more: &str) -> String {
    format!("/repos/{}/{}/issues/{}{}", self.owner, self.repo, self.number, more)
  }

  pub fn labels(&self) -> IssueLabels {
    IssueLabels::new(self.github, self.owner, self.repo, self.number)
  }

  pub fn edit(&self, is: &IssueReq) -> Result<Issue> {
    let data = json::encode(&is).unwrap();
    let body = try!(
      self.github.patch(
        &self.path(""),
        data.as_bytes()
      )
    );
    Ok(json::decode::<Issue>(&body).unwrap())
  }
}

pub struct Issues<'a> {
  github: &'a Github<'a>,
  owner: &'static str,
  repo: &'static str
}

/// an mutable issue list builder
pub struct ListBuilder<'a> {
  issues: &'a Issues<'a>,
  state: State,
  sort: Sort,
  direction: SortDirection,
  assignee: Option<&'static str>,
  creator: Option<&'static str>,
  mentioned: Option<&'static str>,
  labels: Vec<&'static str>,
  since: Option<&'static str>
}

impl<'a> ListBuilder<'a> {

  pub fn new(is: &'a Issues<'a>) -> ListBuilder<'a> {
    ListBuilder {
      issues: is,
      state: Default::default(),
      sort: Default::default(),
      direction: Default::default(),
      assignee: None,
      creator: None,
      mentioned: None,
      labels: vec![],
      since: None
    }
  }

  pub fn state(&mut self, state: State) -> &mut ListBuilder<'a> {
    self.state = state;
    self
  }

  pub fn sort(&mut self, sort: Sort) -> &mut ListBuilder<'a> {
    self.sort = sort;
    self
  }

  pub fn direction(&mut self, direction: SortDirection) -> &mut ListBuilder<'a> {
    self.direction = direction;
    self
  }

  pub fn assignee(&mut self, assignee: &'static str) -> &mut ListBuilder<'a> {
    self.assignee = Some(assignee);
    self
  }

  pub fn creator(&mut self, creator: &'static str) -> &mut ListBuilder<'a> {
    self.creator = Some(creator);
    self
  }

  pub fn mentioned(&mut self, mentioned: &'static str) -> &mut ListBuilder<'a> {
    self.mentioned = Some(mentioned);
    self
  }

  pub fn labels(&mut self, labels: Vec<&'static str>) -> &mut ListBuilder<'a> {
    self.labels = labels;
    self
  }

  pub fn since(&mut self, since: &'static str) -> &mut ListBuilder<'a> {
    self.since = Some(since);
    self
  }

  pub fn get(&self) -> Result<Vec<Issue>> {
    let mut params = Vec::new();
    params.push(format!("state={}", self.state));
    params.push(format!("sort={}", self.sort));
    params.push(format!("direction={}", self.direction));
    if let Some(a) = self.assignee {
      params.push(format!("assignee={}", a));
    }
    if let Some(c) = self.creator {
      params.push(format!("creator={}", c));
    }
    if let Some(m) = self.mentioned {
      params.push(format!("mentioned={}", m));
    }
    if let Some(s) = self.since {
      params.push(format!("since={}", s));
    }
    if !self.labels.is_empty() {
      params.push(format!("labels={}", self.labels.connect(",")));
    }
    println!("params {:?}", params);
    let url = self.issues.path(
      &format!("?{}", params.connect("&"))
    );
    let body = try!(
      self.issues.github.get(
        &url
      )
    );
    Ok(json::decode::<Vec<Issue>>(&body).unwrap())
  }

}

impl<'a> Issues<'a> {
  /// create a new instance of a github repo issue ref
  pub fn new(
    github: &'a Github<'a>, owner: &'static str, repo: &'static str) -> Issues<'a> {
    Issues {
      github: github,
      owner: owner,
      repo: repo
    }
  }

  fn path(&self, more: &str) -> String {
    format!("/repos/{}/{}/issues{}", self.owner, self.repo, more)
  }

  pub fn get(&self, number: &'static i64) -> IssueRef {
    IssueRef::new(self.github, self.owner, self.repo, number)
  }

  pub fn create(&self, is: &IssueReq) -> Result<Issue> {
    let data = json::encode(&is).unwrap();
    let body = try!(
      self.github.post(
        &self.path(""),
        data.as_bytes()
      )
    );
    Ok(json::decode::<Issue>(&body).unwrap())
  }

  pub fn list(&self) -> ListBuilder {
    ListBuilder::new(self)
  }
}
<|endoftext|>


<commit_before>use collections::borrow::ToOwned;
use collections::String;

use common::time::Duration;

#[derive(Copy, Clone)]
pub enum LogLevel {
    Critical,
    Error,
    Warning,
    Info,
    Debug,
}

/// Add message to kernel logs with format
#[macro_export]
macro_rules! syslog {
    ($level:expr, $($arg:tt)*) => ({
        $crate::logging::syslog_inner($level, format!($($arg)*));
    });
}

#[macro_export]
macro_rules! syslog_debug {
    ($($arg:tt)*) => ({
        $crate::logging::syslog_inner($crate::logging::LogLevel::Debug, format!($($arg)*));
    });
}

#[macro_export]
macro_rules! syslog_info {
    ($($arg:tt)*) => ({
        $crate::logging::syslog_inner($crate::logging::LogLevel::Info, format!($($arg)*));
    });
}

#[macro_export]
macro_rules! syslog_warning {
    ($($arg:tt)*) => ({
        $crate::logging::syslog_inner($crate::logging::LogLevel::Warning, format!($($arg)*));
    });
}

#[macro_export]
macro_rules! syslog_critical {
    ($($arg:tt)*) => ({
        $crate::logging::syslog_inner($crate::logging::LogLevel::Critical, format!($($arg)*));
    });
}

#[macro_export]
macro_rules! syslog_error {
    ($($arg:tt)*) => ({
        $crate::logging::syslog_inner($crate::logging::LogLevel::Error, format!($($arg)*));
    });
}

/// Add `message` to the kernel logs, with a priority level of `level`
pub fn syslog(level: LogLevel, message: &str) {
    syslog_inner(level, message.to_owned());
}

//TODO: Limit log message size
pub fn syslog_inner(level: LogLevel, message: String) {
    let time = Duration::monotonic();
    let logs = unsafe { &mut *::env().logs.get() };
    while logs.len() >= 4096 {
        logs.pop_front();
    }
    logs.push_back((time, level, message));
    //TODO: Print messages that are above priority
}
<commit_msg>Print out syslog messages<commit_after>use collections::borrow::ToOwned;
use collections::String;

use common::time::Duration;

#[derive(Copy, Clone)]
pub enum LogLevel {
    Critical,
    Error,
    Warning,
    Info,
    Debug,
}

/// Add message to kernel logs with format
#[macro_export]
macro_rules! syslog {
    ($level:expr, $($arg:tt)*) => ({
        $crate::logging::syslog_inner($level, format!($($arg)*));
    });
}

#[macro_export]
macro_rules! syslog_debug {
    ($($arg:tt)*) => ({
        $crate::logging::syslog_inner($crate::logging::LogLevel::Debug, format!($($arg)*));
    });
}

#[macro_export]
macro_rules! syslog_info {
    ($($arg:tt)*) => ({
        $crate::logging::syslog_inner($crate::logging::LogLevel::Info, format!($($arg)*));
    });
}

#[macro_export]
macro_rules! syslog_warning {
    ($($arg:tt)*) => ({
        $crate::logging::syslog_inner($crate::logging::LogLevel::Warning, format!($($arg)*));
    });
}

#[macro_export]
macro_rules! syslog_critical {
    ($($arg:tt)*) => ({
        $crate::logging::syslog_inner($crate::logging::LogLevel::Critical, format!($($arg)*));
    });
}

#[macro_export]
macro_rules! syslog_error {
    ($($arg:tt)*) => ({
        $crate::logging::syslog_inner($crate::logging::LogLevel::Error, format!($($arg)*));
    });
}

/// Add `message` to the kernel logs, with a priority level of `level`
pub fn syslog(level: LogLevel, message: &str) {
    syslog_inner(level, message.to_owned());
}

//TODO: Limit log message size
pub fn syslog_inner(level: LogLevel, message: String) {
    let time = Duration::monotonic();

    let prefix: &str = match level {
        LogLevel::Debug    => "DEBUG ",
        LogLevel::Info     => "INFO  ",
        LogLevel::Warning  => "WARN  ",
        LogLevel::Error    => "ERROR ",
        LogLevel::Critical => "CRIT  ",
    };
    debugln!("[{}.{:>03}] {}{}", time.secs, time.nanos/1000000, prefix, message);

    let logs = unsafe { &mut *::env().logs.get() };
    while logs.len() >= 4096 {
        logs.pop_front();
    }
    logs.push_back((time, level, message));
}
<|endoftext|>


<commit_before>use iron::typemap::Key;
use postgres;
use r2d2;
use r2d2_postgres;
use regex;
use serde_json;
use std::collections::HashMap;
use std::convert::From;
use std::fmt;
use std::iter;
use uuid::Uuid;

error_chain! {
    errors {
        UniqueViolation
        NoTestQuery(cmd: String)
        NoTestExecute(cmd: String)
        PostgresError(cmd: String)
    }
    foreign_links {
        R2D2Error(r2d2::Error);
    }
}

#[derive(Debug)]
pub struct HexSlice(Vec<u8>);

impl HexSlice {
    pub fn new(data: Vec<u8>) -> HexSlice {
        HexSlice(data)
    }

    pub fn sql(&self) -> String {
        format!("decode('{}', 'hex')", self)
    }
}

impl fmt::Display for HexSlice {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for byte in self.0.iter() {
            write!(f, "{:02X}", byte)?;
        }
        Ok(())
    }
}

pub trait FromSql {}
impl<T: FromSql> FromSql for Option<T> {}
impl FromSql for u32 {}
impl FromSql for Uuid {}
impl FromSql for String {}
impl<'a> FromSql for &'a str {}
impl FromSql for Vec<u8> {}
impl FromSql for serde_json::Value {}

#[derive(Debug, Clone)]
pub enum SqlValue {
    Null,
    U32(u32),
    UUID(Uuid),
    String(String),
    U8Bytes(Vec<u8>),
    JSON(serde_json::Value),
}

impl From<u32> for SqlValue {
    fn from(i: u32) -> SqlValue {
        SqlValue::U32(i)
    }
}

#[derive(Hash, Eq, PartialEq, Clone, Debug)]
pub enum ValueIndex {
    U32(u32),
    String(String),
}

impl<'a> From<&'a str> for ValueIndex {
    fn from(s: &str) -> ValueIndex {
        ValueIndex::String(String::from(s))
    }
}

pub trait RowIndex {
    fn val(&self) -> ValueIndex;
}
impl RowIndex for u32 {
    fn val(&self) -> ValueIndex {
        ValueIndex::U32(*self)
    }
}
impl RowIndex for String {
    fn val(&self) -> ValueIndex {
        ValueIndex::String(self.clone())
    }
}
impl<'a> RowIndex for &'a str {
    fn val(&self) -> ValueIndex {
        ValueIndex::String(String::from(*self))
    }
}

#[derive(Debug, Clone)]
pub struct TestRow {
    data: HashMap<ValueIndex, SqlValue>,
}

pub trait GetRow<T> {
    fn get<R>(&self, id: R) -> T
        where T: FromSql,
              R: RowIndex + fmt::Display;
}

impl TestRow {
    pub fn new() -> TestRow {
        TestRow { data: HashMap::new() }
    }

    pub fn insert<K, V>(&mut self, k: K, v: V) -> Option<SqlValue>
        where K: Into<ValueIndex>,
              V: Into<SqlValue>
    {
        self.data.insert(k.into(), v.into())
    }
}

macro_rules! get_row {
    ($type: ty, $kind: path) => (
    impl GetRow<$type> for TestRow {
        fn get<R>(&self, id: R) -> $type where R: RowIndex + fmt::Display {
            if !self.data.contains_key(&id.val()) {
                panic!(format!("Can't find key {} in row", id));
            }
            match self.data[&id.val()] {
                $kind(ref val) => val.clone(),
                _ => panic!()
            }
        }
    }

    impl GetRow<Option<$type>> for TestRow {
        fn get<R>(&self, id: R) -> Option<$type> where R: RowIndex + fmt::Display {
            if !self.data.contains_key(&id.val()) {
                panic!(format!("Can't find key {} in row", id));
            }
            match self.data[&id.val()] {
                $kind(ref val) => Some(val.clone()),
                SqlValue::Null => None,
                _ => panic!()
            }
        }
    }
)}

get_row!(u32, SqlValue::U32);
get_row!(Uuid, SqlValue::UUID);
get_row!(String, SqlValue::String);
get_row!(serde_json::Value, SqlValue::JSON);
get_row!(Vec<u8>, SqlValue::U8Bytes);

#[derive(Debug)]
pub enum Row<'a> {
    Postgres(postgres::rows::Row<'a>),
    Test(&'a TestRow),
}
impl<'a> Row<'a> {
    pub fn get<T, R>(&self, id: R) -> T
        where T: FromSql + postgres::types::FromSql,
              R: RowIndex + postgres::rows::RowIndex + fmt::Display + fmt::Debug,
              TestRow: GetRow<T>
    {
        match self {
            &Row::Postgres(ref rows) => rows.get(id),
            &Row::Test(ref rows) => rows.get(id),
        }
    }
    pub fn get_opt<T, R>(&self, _id: R) -> Option<Result<T>>
        where T: FromSql,
              R: RowIndex
    {
        unimplemented!();
    }
}

#[derive(Debug)]
pub struct TestRowIterator<'a> {
    rows: &'a Vec<TestRow>,
    location: usize,
}

impl<'a> TestRowIterator<'a> {
    fn new(r: &'a Vec<TestRow>) -> TestRowIterator<'a> {
        TestRowIterator {
            rows: r,
            location: 0,
        }
    }

    fn next(&mut self) -> Option<&'a TestRow> {
        self.location += 1;
        if self.location < self.rows.len() {
            Some(&self.rows[self.location])
        } else {
            None
        }
    }
}

pub enum RowIterator<'a> {
    Postgres(postgres::rows::Iter<'a>),
    Test(TestRowIterator<'a>),
}

impl<'a> fmt::Debug for RowIterator<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &RowIterator::Postgres(_) => write!(f, "RowIterator(PostgresRows)"),
            &RowIterator::Test(ref rows) => write!(f, "RowIterator({:?})", rows)
        }
    }
}

impl<'a> Iterator for RowIterator<'a> {
    type Item = Row<'a>;

    fn next(&mut self) -> Option<Row<'a>> {
        match self {
            &mut RowIterator::Postgres(ref mut rows) => rows.next().map(|r| Row::Postgres(r)),
            &mut RowIterator::Test(ref mut rows) => rows.next().map(|r| Row::Test(r)),
        }
    }
}

#[derive(Debug)]
pub enum Rows {
    Postgres(postgres::rows::Rows),
    Test(Vec<TestRow>),
}

impl<'stmt> Rows {
    pub fn get<'a>(&'a self, id: usize) -> Row<'a> {
        match self {
            &Rows::Postgres(ref rows) => Row::Postgres(rows.get(id)),
            &Rows::Test(ref rows) => Row::Test(rows.get(id).unwrap()),
        }
    }
    pub fn is_empty(&self) -> bool {
        match self {
            &Rows::Postgres(ref rows) => rows.is_empty(),
            &Rows::Test(ref rows) => rows.is_empty(),
        }
    }
    pub fn len(&self) -> usize {
        match self {
            &Rows::Postgres(ref rows) => rows.len(),
            &Rows::Test(ref rows) => rows.len(),
        }
    }
    pub fn iter<'a>(&'a self) -> RowIterator<'a> {
        match self {
            &Rows::Postgres(ref rows) => RowIterator::Postgres(rows.iter()),
            &Rows::Test(ref rows) => RowIterator::Test(TestRowIterator::new(rows)),
        }
    }
}

impl<'a> iter::IntoIterator for &'a Rows {
    type Item = Row<'a>;
    type IntoIter = RowIterator<'a>;
    fn into_iter(self) -> RowIterator<'a> {
        self.iter()
    }
}

#[derive(Debug, Clone)]
pub struct TestConnection {
    query_results: Vec<(regex::Regex, Vec<TestRow>)>,
    execute_results: Vec<(regex::Regex, u64)>,
}

impl TestConnection {
    pub fn new() -> TestConnection {
        TestConnection {
            query_results: Vec::new(),
            execute_results: Vec::new(),
        }
    }

    pub fn add_test_query(&mut self, cmd: &str, results: Vec<TestRow>) {
        self.query_results
            .push((regex::Regex::new(cmd).unwrap(), results));
    }

    pub fn add_test_execute(&mut self, cmd: &str, results: u64) {
        self.execute_results
            .push((regex::Regex::new(cmd).unwrap(), results));
    }

    fn get_rows(&self, cmd: &str) -> Result<Vec<TestRow>> {
        for &(ref patt, ref res) in self.query_results.iter() {
            if patt.is_match(cmd) {
                return Ok(res.clone());
            }
        }
        Err(Error::from(ErrorKind::NoTestQuery(String::from(cmd))))
    }
    fn execute(&self, cmd: &str) -> Result<u64> {
        for &(ref patt, res) in self.execute_results.iter() {
            if patt.is_match(cmd) {
                return Ok(res);
            }
        }
        Err(Error::from(ErrorKind::NoTestExecute(String::from(cmd))))
    }
}

#[derive(Debug)]
pub enum Connection {
    Postgres(r2d2::PooledConnection<r2d2_postgres::PostgresConnectionManager>),
    Test(TestConnection),
}
impl<'conn> Connection {
    pub fn query(&'conn self, query: &str) -> Result<Rows> {
        match self {
            &Connection::Postgres(ref conn) => {
                Ok(Rows::Postgres(conn.query(query, &[])
                                      .map_err(|e| Error::with_chain(e, ErrorKind::PostgresError(query.to_string())))?))
            }
            &Connection::Test(ref conn) => Ok(Rows::Test(conn.get_rows(query)?)),
        }
    }
    pub fn execute(&self, equery: &str) -> Result<u64> {
        match self {
            &Connection::Postgres(ref conn) => {
                conn.execute(equery, &[])
                    .map_err(|e| Error::with_chain(e, ErrorKind::PostgresError(equery.to_string())))
            }
            &Connection::Test(ref conn) => conn.execute(equery),
        }
    }
}

#[derive(Clone, Debug)]
pub enum Pool {
    Postgres(r2d2::Pool<r2d2_postgres::PostgresConnectionManager>),
    TestPool(TestConnection),
}

impl Pool {
    pub fn get(&self) -> Result<Connection> {
        match self {
            &Pool::Postgres(ref pool) => {
                let conn = pool.get()?;
                Ok(Connection::Postgres(conn))
            }
            &Pool::TestPool(ref conn) => Ok(Connection::Test(conn.clone())),
        }
    }
}

#[derive(Clone, Copy, Debug)]
pub struct PoolKey;

impl Key for PoolKey {
    type Value = Pool;
}

// Gets a connection from the pool from the given request or returns a 500
#[macro_export]
macro_rules! get_db_connection {
    ($req:expr) => (match $req.extensions.get::<persistent::Read<db::PoolKey>>() {
        Some(pool) => match pool.get() {
            Ok(conn) => {
                conn
            }
            Err(_) => {
                println!("Couldn't get a connection to pg!");
                return Ok(Response::with(status::InternalServerError));
            }
        },
        None => {
            println!("Couldn't get the pg pool from the request!");
            return Ok(Response::with(status::InternalServerError));
        }
    })
}
<commit_msg>Forgot to reformat after fixing RowIterator debug<commit_after>use iron::typemap::Key;
use postgres;
use r2d2;
use r2d2_postgres;
use regex;
use serde_json;
use std::collections::HashMap;
use std::convert::From;
use std::fmt;
use std::iter;
use uuid::Uuid;

error_chain! {
    errors {
        UniqueViolation
        NoTestQuery(cmd: String)
        NoTestExecute(cmd: String)
        PostgresError(cmd: String)
    }
    foreign_links {
        R2D2Error(r2d2::Error);
    }
}

#[derive(Debug)]
pub struct HexSlice(Vec<u8>);

impl HexSlice {
    pub fn new(data: Vec<u8>) -> HexSlice {
        HexSlice(data)
    }

    pub fn sql(&self) -> String {
        format!("decode('{}', 'hex')", self)
    }
}

impl fmt::Display for HexSlice {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for byte in self.0.iter() {
            write!(f, "{:02X}", byte)?;
        }
        Ok(())
    }
}

pub trait FromSql {}
impl<T: FromSql> FromSql for Option<T> {}
impl FromSql for u32 {}
impl FromSql for Uuid {}
impl FromSql for String {}
impl<'a> FromSql for &'a str {}
impl FromSql for Vec<u8> {}
impl FromSql for serde_json::Value {}

#[derive(Debug, Clone)]
pub enum SqlValue {
    Null,
    U32(u32),
    UUID(Uuid),
    String(String),
    U8Bytes(Vec<u8>),
    JSON(serde_json::Value),
}

impl From<u32> for SqlValue {
    fn from(i: u32) -> SqlValue {
        SqlValue::U32(i)
    }
}

#[derive(Hash, Eq, PartialEq, Clone, Debug)]
pub enum ValueIndex {
    U32(u32),
    String(String),
}

impl<'a> From<&'a str> for ValueIndex {
    fn from(s: &str) -> ValueIndex {
        ValueIndex::String(String::from(s))
    }
}

pub trait RowIndex {
    fn val(&self) -> ValueIndex;
}
impl RowIndex for u32 {
    fn val(&self) -> ValueIndex {
        ValueIndex::U32(*self)
    }
}
impl RowIndex for String {
    fn val(&self) -> ValueIndex {
        ValueIndex::String(self.clone())
    }
}
impl<'a> RowIndex for &'a str {
    fn val(&self) -> ValueIndex {
        ValueIndex::String(String::from(*self))
    }
}

#[derive(Debug, Clone)]
pub struct TestRow {
    data: HashMap<ValueIndex, SqlValue>,
}

pub trait GetRow<T> {
    fn get<R>(&self, id: R) -> T
        where T: FromSql,
              R: RowIndex + fmt::Display;
}

impl TestRow {
    pub fn new() -> TestRow {
        TestRow { data: HashMap::new() }
    }

    pub fn insert<K, V>(&mut self, k: K, v: V) -> Option<SqlValue>
        where K: Into<ValueIndex>,
              V: Into<SqlValue>
    {
        self.data.insert(k.into(), v.into())
    }
}

macro_rules! get_row {
    ($type: ty, $kind: path) => (
    impl GetRow<$type> for TestRow {
        fn get<R>(&self, id: R) -> $type where R: RowIndex + fmt::Display {
            if !self.data.contains_key(&id.val()) {
                panic!(format!("Can't find key {} in row", id));
            }
            match self.data[&id.val()] {
                $kind(ref val) => val.clone(),
                _ => panic!()
            }
        }
    }

    impl GetRow<Option<$type>> for TestRow {
        fn get<R>(&self, id: R) -> Option<$type> where R: RowIndex + fmt::Display {
            if !self.data.contains_key(&id.val()) {
                panic!(format!("Can't find key {} in row", id));
            }
            match self.data[&id.val()] {
                $kind(ref val) => Some(val.clone()),
                SqlValue::Null => None,
                _ => panic!()
            }
        }
    }
)}

get_row!(u32, SqlValue::U32);
get_row!(Uuid, SqlValue::UUID);
get_row!(String, SqlValue::String);
get_row!(serde_json::Value, SqlValue::JSON);
get_row!(Vec<u8>, SqlValue::U8Bytes);

#[derive(Debug)]
pub enum Row<'a> {
    Postgres(postgres::rows::Row<'a>),
    Test(&'a TestRow),
}
impl<'a> Row<'a> {
    pub fn get<T, R>(&self, id: R) -> T
        where T: FromSql + postgres::types::FromSql,
              R: RowIndex + postgres::rows::RowIndex + fmt::Display + fmt::Debug,
              TestRow: GetRow<T>
    {
        match self {
            &Row::Postgres(ref rows) => rows.get(id),
            &Row::Test(ref rows) => rows.get(id),
        }
    }
    pub fn get_opt<T, R>(&self, _id: R) -> Option<Result<T>>
        where T: FromSql,
              R: RowIndex
    {
        unimplemented!();
    }
}

#[derive(Debug)]
pub struct TestRowIterator<'a> {
    rows: &'a Vec<TestRow>,
    location: usize,
}

impl<'a> TestRowIterator<'a> {
    fn new(r: &'a Vec<TestRow>) -> TestRowIterator<'a> {
        TestRowIterator {
            rows: r,
            location: 0,
        }
    }

    fn next(&mut self) -> Option<&'a TestRow> {
        self.location += 1;
        if self.location < self.rows.len() {
            Some(&self.rows[self.location])
        } else {
            None
        }
    }
}

pub enum RowIterator<'a> {
    Postgres(postgres::rows::Iter<'a>),
    Test(TestRowIterator<'a>),
}

impl<'a> fmt::Debug for RowIterator<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &RowIterator::Postgres(_) => write!(f, "RowIterator(PostgresRows)"),
            &RowIterator::Test(ref rows) => write!(f, "RowIterator({:?})", rows),
        }
    }
}

impl<'a> Iterator for RowIterator<'a> {
    type Item = Row<'a>;

    fn next(&mut self) -> Option<Row<'a>> {
        match self {
            &mut RowIterator::Postgres(ref mut rows) => rows.next().map(|r| Row::Postgres(r)),
            &mut RowIterator::Test(ref mut rows) => rows.next().map(|r| Row::Test(r)),
        }
    }
}

#[derive(Debug)]
pub enum Rows {
    Postgres(postgres::rows::Rows),
    Test(Vec<TestRow>),
}

impl<'stmt> Rows {
    pub fn get<'a>(&'a self, id: usize) -> Row<'a> {
        match self {
            &Rows::Postgres(ref rows) => Row::Postgres(rows.get(id)),
            &Rows::Test(ref rows) => Row::Test(rows.get(id).unwrap()),
        }
    }
    pub fn is_empty(&self) -> bool {
        match self {
            &Rows::Postgres(ref rows) => rows.is_empty(),
            &Rows::Test(ref rows) => rows.is_empty(),
        }
    }
    pub fn len(&self) -> usize {
        match self {
            &Rows::Postgres(ref rows) => rows.len(),
            &Rows::Test(ref rows) => rows.len(),
        }
    }
    pub fn iter<'a>(&'a self) -> RowIterator<'a> {
        match self {
            &Rows::Postgres(ref rows) => RowIterator::Postgres(rows.iter()),
            &Rows::Test(ref rows) => RowIterator::Test(TestRowIterator::new(rows)),
        }
    }
}

impl<'a> iter::IntoIterator for &'a Rows {
    type Item = Row<'a>;
    type IntoIter = RowIterator<'a>;
    fn into_iter(self) -> RowIterator<'a> {
        self.iter()
    }
}

#[derive(Debug, Clone)]
pub struct TestConnection {
    query_results: Vec<(regex::Regex, Vec<TestRow>)>,
    execute_results: Vec<(regex::Regex, u64)>,
}

impl TestConnection {
    pub fn new() -> TestConnection {
        TestConnection {
            query_results: Vec::new(),
            execute_results: Vec::new(),
        }
    }

    pub fn add_test_query(&mut self, cmd: &str, results: Vec<TestRow>) {
        self.query_results
            .push((regex::Regex::new(cmd).unwrap(), results));
    }

    pub fn add_test_execute(&mut self, cmd: &str, results: u64) {
        self.execute_results
            .push((regex::Regex::new(cmd).unwrap(), results));
    }

    fn get_rows(&self, cmd: &str) -> Result<Vec<TestRow>> {
        for &(ref patt, ref res) in self.query_results.iter() {
            if patt.is_match(cmd) {
                return Ok(res.clone());
            }
        }
        Err(Error::from(ErrorKind::NoTestQuery(String::from(cmd))))
    }
    fn execute(&self, cmd: &str) -> Result<u64> {
        for &(ref patt, res) in self.execute_results.iter() {
            if patt.is_match(cmd) {
                return Ok(res);
            }
        }
        Err(Error::from(ErrorKind::NoTestExecute(String::from(cmd))))
    }
}

#[derive(Debug)]
pub enum Connection {
    Postgres(r2d2::PooledConnection<r2d2_postgres::PostgresConnectionManager>),
    Test(TestConnection),
}
impl<'conn> Connection {
    pub fn query(&'conn self, query: &str) -> Result<Rows> {
        match self {
            &Connection::Postgres(ref conn) => {
                Ok(Rows::Postgres(conn.query(query, &[])
                                      .map_err(|e| Error::with_chain(e, ErrorKind::PostgresError(query.to_string())))?))
            }
            &Connection::Test(ref conn) => Ok(Rows::Test(conn.get_rows(query)?)),
        }
    }
    pub fn execute(&self, equery: &str) -> Result<u64> {
        match self {
            &Connection::Postgres(ref conn) => {
                conn.execute(equery, &[])
                    .map_err(|e| Error::with_chain(e, ErrorKind::PostgresError(equery.to_string())))
            }
            &Connection::Test(ref conn) => conn.execute(equery),
        }
    }
}

#[derive(Clone, Debug)]
pub enum Pool {
    Postgres(r2d2::Pool<r2d2_postgres::PostgresConnectionManager>),
    TestPool(TestConnection),
}

impl Pool {
    pub fn get(&self) -> Result<Connection> {
        match self {
            &Pool::Postgres(ref pool) => {
                let conn = pool.get()?;
                Ok(Connection::Postgres(conn))
            }
            &Pool::TestPool(ref conn) => Ok(Connection::Test(conn.clone())),
        }
    }
}

#[derive(Clone, Copy, Debug)]
pub struct PoolKey;

impl Key for PoolKey {
    type Value = Pool;
}

// Gets a connection from the pool from the given request or returns a 500
#[macro_export]
macro_rules! get_db_connection {
    ($req:expr) => (match $req.extensions.get::<persistent::Read<db::PoolKey>>() {
        Some(pool) => match pool.get() {
            Ok(conn) => {
                conn
            }
            Err(_) => {
                println!("Couldn't get a connection to pg!");
                return Ok(Response::with(status::InternalServerError));
            }
        },
        None => {
            println!("Couldn't get the pg pool from the request!");
            return Ok(Response::with(status::InternalServerError));
        }
    })
}
<|endoftext|>


<commit_before>//! [PUT /_matrix/client/r0/rooms/{roomId}/state/{eventType}/{stateKey}](https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-rooms-roomid-state-eventtype-statekey)

use ruma_api::ruma_api;
use ruma_events::{AnyStateEventContent, EventContent as _};
use ruma_identifiers::{EventId, RoomId};
use ruma_serde::Raw;

ruma_api! {
    metadata: {
        description: "Send a state event to a room associated with a given state key.",
        method: PUT,
        name: "send_state_event",
        path: "/_matrix/client/r0/rooms/:room_id/state/:event_type/:state_key",
        rate_limited: false,
        authentication: AccessToken,
    }

    request: {
        /// The room to set the state in.
        #[ruma_api(path)]
        pub room_id: &'a RoomId,

        /// The type of event to send.
        #[ruma_api(path)]
        pub event_type: &'a str,

        /// The state_key for the state to send.
        #[ruma_api(path)]
        pub state_key: &'a str,

        /// The event content to send.
        #[ruma_api(body)]
        pub body: Raw<AnyStateEventContent>,
    }

    response: {
        /// A unique identifier for the event.
        pub event_id: EventId,
    }

    error: crate::Error
}

impl<'a> Request<'a> {
    /// Creates a new `Request` with the given room id, state key and event content.
    pub fn new(room_id: &'a RoomId, state_key: &'a str, content: &'a AnyStateEventContent) -> Self {
        Self { room_id, event_type: content.event_type(), body: content.into(), state_key }
    }

    /// Creates a new `Request` with the given room id, event type, state key and raw event content.
    pub fn new_raw(
        room_id: &'a RoomId,
        event_type: &'a str,
        state_key: &'a str,
        body: Raw<AnyStateEventContent>,
    ) -> Self {
        Self { room_id, event_type, state_key, body }
    }
}

impl Response {
    /// Creates a new `Response` with the given event id.
    pub fn new(event_id: EventId) -> Self {
        Self { event_id }
    }
}
<commit_msg>client-api: Implement request traits for send_state_event manually<commit_after>//! [PUT /_matrix/client/r0/rooms/{roomId}/state/{eventType}/{stateKey}](https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-rooms-roomid-state-eventtype-statekey)

use bytes::BufMut;
use ruma_api::{ruma_api, SendAccessToken};
use ruma_events::{AnyStateEventContent, EventContent as _};
use ruma_identifiers::{EventId, RoomId};
use ruma_serde::{Outgoing, Raw};

ruma_api! {
    metadata: {
        description: "Send a state event to a room associated with a given state key.",
        method: PUT,
        name: "send_state_event",
        path: "/_matrix/client/r0/rooms/:room_id/state/:event_type/:state_key",
        rate_limited: false,
        authentication: AccessToken,
    }

    response: {
        /// A unique identifier for the event.
        pub event_id: EventId,
    }

    error: crate::Error
}

/// Data for a request to the `send_state_event` API endpoint.
///
/// Send a state event to a room associated with a given state key.
#[derive(Clone, Debug, Outgoing)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[incoming_derive(!Deserialize)]
pub struct Request<'a> {
    /// The room to set the state in.
    pub room_id: &'a RoomId,

    /// The type of event to send.
    pub event_type: &'a str,

    /// The state_key for the state to send.
    pub state_key: &'a str,

    /// The event content to send.
    pub body: Raw<AnyStateEventContent>,
}

impl<'a> Request<'a> {
    /// Creates a new `Request` with the given room id, state key and event content.
    pub fn new(room_id: &'a RoomId, state_key: &'a str, content: &'a AnyStateEventContent) -> Self {
        Self { room_id, event_type: content.event_type(), body: content.into(), state_key }
    }

    /// Creates a new `Request` with the given room id, event type, state key and raw event content.
    pub fn new_raw(
        room_id: &'a RoomId,
        event_type: &'a str,
        state_key: &'a str,
        body: Raw<AnyStateEventContent>,
    ) -> Self {
        Self { room_id, event_type, state_key, body }
    }
}

impl Response {
    /// Creates a new `Response` with the given event id.
    pub fn new(event_id: EventId) -> Self {
        Self { event_id }
    }
}

#[cfg(feature = "client")]
impl<'a> ruma_api::OutgoingRequest for Request<'a> {
    type EndpointError = crate::Error;
    type IncomingResponse = Response;

    const METADATA: ruma_api::Metadata = METADATA;

    fn try_into_http_request<T: Default + BufMut>(
        self,
        base_url: &str,
        access_token: SendAccessToken<'_>,
    ) -> Result<http::Request<T>, ruma_api::error::IntoHttpError> {
        use std::borrow::Cow;

        use http::header::{self, HeaderValue};
        use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};

        let mut url = format!(
            "{}/_matrix/client/r0/rooms/{}/state/{}",
            base_url.strip_suffix('/').unwrap_or(base_url),
            utf8_percent_encode(self.room_id.as_str(), NON_ALPHANUMERIC),
            utf8_percent_encode(self.event_type, NON_ALPHANUMERIC),
        );

        // Last URL segment is optional, that is why this trait impl is not generated.
        if !self.state_key.is_empty() {
            url.push('/');
            url.push_str(&Cow::from(utf8_percent_encode(&self.state_key, NON_ALPHANUMERIC)));
        }

        let http_request = http::Request::builder()
            .method(http::Method::PUT)
            .uri(url)
            .header(header::CONTENT_TYPE, "application/json")
            .header(
                header::AUTHORIZATION,
                HeaderValue::from_str(&format!(
                    "Bearer {}",
                    access_token
                        .get_required_for_endpoint()
                        .ok_or(ruma_api::error::IntoHttpError::NeedsAuthentication)?
                ))?,
            )
            .body(ruma_serde::json_to_buf(&self.body)?)?;

        Ok(http_request)
    }
}

#[cfg(feature = "server")]
impl ruma_api::IncomingRequest for IncomingRequest {
    type EndpointError = crate::Error;
    type OutgoingResponse = Response;

    const METADATA: ruma_api::Metadata = METADATA;

    fn try_from_http_request<T: AsRef<[u8]>>(
        request: http::Request<T>,
    ) -> Result<Self, ruma_api::error::FromHttpRequestError> {
        use std::{borrow::Cow, convert::TryFrom};

        let path_segments: Vec<&str> = request.uri().path()[1..].split('/').collect();

        let room_id = {
            let decoded =
                percent_encoding::percent_decode(path_segments[4].as_bytes()).decode_utf8()?;

            RoomId::try_from(&*decoded)?
        };

        let event_type = percent_encoding::percent_decode(path_segments[6].as_bytes())
            .decode_utf8()?
            .into_owned();

        let state_key = path_segments
            .get(7)
            .map(|segment| percent_encoding::percent_decode(segment.as_bytes()).decode_utf8())
            .transpose()?
            // Last URL segment is optional, but not present is the same semantically as empty
            .unwrap_or(Cow::Borrowed(""))
            .into_owned();

        let body = serde_json::from_slice(request.body().as_ref())?;

        Ok(Self { room_id, event_type, state_key, body })
    }
}
<|endoftext|>


<commit_before>/// Macro to print the current stats of ArrayFire's memory manager.
///
/// `mem_info!` print 4 values:
///
///  Name                    | Description
/// -------------------------|-------------------------
///  Allocated Bytes         | Total number of bytes allocated by the memory manager
///  Allocated Buffers       | Total number of buffers allocated
///  Locked (In Use) Bytes   | Number of bytes that are in use by active arrays
///  Locked (In Use) Buffers | Number of buffers that are in use by active arrays
///
///  The `Allocated Bytes` is always a multiple of the memory step size. The
///  default step size is 1024 bytes. This means when a buffer is to be
///  allocated, the size is always rounded up to a multiple of the step size.
///  You can use [get_mem_step_size](./fn.get_mem_step_size.html) to check the
///  current step size and [set_mem_step_size](./fn.set_mem_step_size.html) to
///  set a custom resolution size.
///
///  The `Allocated Buffers` is the number of buffers that use up the allocated
///  bytes. This includes buffers currently in scope, as well as buffers marked
///  as free, ie, from arrays gone out of scope. The free buffers are available
///  for use by new arrays that might be created.
///
///  The `Locked Bytes` is the number of bytes in use that cannot be
///  reallocated at the moment. The difference of Allocated Bytes and Locked
///  Bytes is the total bytes available for reallocation.
///
///  The `Locked Buffers` is the number of buffer in use that cannot be
///  reallocated at the moment. The difference of Allocated Buffers and Locked
///  Buffers is the number of buffers available for reallocation.
///
/// # Parameters
///
/// - `msg` is the message that is printed to screen before printing stats
///
/// # Examples
///
/// ```rust
/// use arrayfire::{Dim4, device_mem_info, print, randu, mem_info};
///
/// let dims = Dim4::new(&[5, 5, 1, 1]);
/// let a = randu::<f32>(dims);
/// print(&a);
/// mem_info!("Hello!");
/// ```
///
/// Sample Output:
///
/// ```text
/// AF Memory: Here
/// Allocated [ Bytes | Buffers ] = [ 4096 | 4 ]
/// In Use    [ Bytes | Buffers ] = [ 2048 | 2 ]
/// ```
#[macro_export]
macro_rules! mem_info {
    [$msg: expr] => {
        {
            let (abytes, abuffs, lbytes, lbuffs) = device_mem_info();
            println!("AF Memory: {:?}", $msg);
            println!("Allocated [Bytes | Buffers] = [ {} | {} ]", abytes, abuffs);
            println!("In Use    [Bytes | Buffers] = [ {} | {} ]", lbytes, lbuffs);
        }
    };
}

/// Join multiple Arrays along a given dimension
///
/// All the Arrays provided to this macro should be of type `&Array`
///
/// # Examples
///
/// ```rust
/// use arrayfire::{Dim4, join_many, print, randu};
///
/// let a = &randu::<f32>(Dim4::new(&[5, 3, 1, 1]));
/// let b = &randu::<f32>(Dim4::new(&[5, 3, 1, 1]));
/// let c = &randu::<f32>(Dim4::new(&[5, 3, 1, 1]));
/// let d = join_many![2; a, b, c];
/// print(&d);
/// ```
///
/// # Panics
///
/// This macro just calls [join_many](./fn.join_many.html) function after collecting all
/// the input arrays into a vector.
// Using macro to implement join many wrapper
#[macro_export]
macro_rules! join_many {
    [$dim: expr; $($x:expr),+] => {
        {
            let mut temp_vec = Vec::new();
            $(
                temp_vec.push($x);
             )*
            join_many($dim, temp_vec)
        }
    };
}

/// Print given message before printing out the Array to standard output
///
/// # Examples
///
/// ```rust
/// use arrayfire::{Dim4, print_gen, randu, af_print};
/// let dims = Dim4::new(&[3, 1, 1, 1]);
/// let a = randu::<f32>(dims);
/// af_print!("Create a 5-by-3 matrix of random floats on the GPU", a);
/// ```
///
#[macro_export]
macro_rules! af_print {
    [$msg: expr, $x: expr] => {
        {
            print_gen(String::from($msg), &$x, Some(4));
        }
    };
}

/// Evaluate arbitrary number of arrays
#[macro_export]
macro_rules! eval {
    [$($x:expr),+] => {
        {
            let mut temp_vec = Vec::new();
            $(
                temp_vec.push($x);
             )*
            eval_multiple(temp_vec)
        }
    };
}
<commit_msg>Fix crate qualifier for fns used inside macros<commit_after>/// Macro to print the current stats of ArrayFire's memory manager.
///
/// `mem_info!` print 4 values:
///
///  Name                    | Description
/// -------------------------|-------------------------
///  Allocated Bytes         | Total number of bytes allocated by the memory manager
///  Allocated Buffers       | Total number of buffers allocated
///  Locked (In Use) Bytes   | Number of bytes that are in use by active arrays
///  Locked (In Use) Buffers | Number of buffers that are in use by active arrays
///
///  The `Allocated Bytes` is always a multiple of the memory step size. The
///  default step size is 1024 bytes. This means when a buffer is to be
///  allocated, the size is always rounded up to a multiple of the step size.
///  You can use [get_mem_step_size](./fn.get_mem_step_size.html) to check the
///  current step size and [set_mem_step_size](./fn.set_mem_step_size.html) to
///  set a custom resolution size.
///
///  The `Allocated Buffers` is the number of buffers that use up the allocated
///  bytes. This includes buffers currently in scope, as well as buffers marked
///  as free, ie, from arrays gone out of scope. The free buffers are available
///  for use by new arrays that might be created.
///
///  The `Locked Bytes` is the number of bytes in use that cannot be
///  reallocated at the moment. The difference of Allocated Bytes and Locked
///  Bytes is the total bytes available for reallocation.
///
///  The `Locked Buffers` is the number of buffer in use that cannot be
///  reallocated at the moment. The difference of Allocated Buffers and Locked
///  Buffers is the number of buffers available for reallocation.
///
/// # Parameters
///
/// - `msg` is the message that is printed to screen before printing stats
///
/// # Examples
///
/// ```rust
/// use arrayfire::{Dim4, device_mem_info, print, randu, mem_info};
///
/// let dims = Dim4::new(&[5, 5, 1, 1]);
/// let a = randu::<f32>(dims);
/// print(&a);
/// mem_info!("Hello!");
/// ```
///
/// Sample Output:
///
/// ```text
/// AF Memory: Here
/// Allocated [ Bytes | Buffers ] = [ 4096 | 4 ]
/// In Use    [ Bytes | Buffers ] = [ 2048 | 2 ]
/// ```
#[macro_export]
macro_rules! mem_info {
    [$msg: expr] => {
        {
            let (abytes, abuffs, lbytes, lbuffs) = $crate::device_mem_info();
            println!("AF Memory: {:?}", $msg);
            println!("Allocated [Bytes | Buffers] = [ {} | {} ]", abytes, abuffs);
            println!("In Use    [Bytes | Buffers] = [ {} | {} ]", lbytes, lbuffs);
        }
    };
}

/// Join multiple Arrays along a given dimension
///
/// All the Arrays provided to this macro should be of type `&Array`
///
/// # Examples
///
/// ```rust
/// use arrayfire::{Dim4, join_many, print, randu};
///
/// let a = &randu::<f32>(Dim4::new(&[5, 3, 1, 1]));
/// let b = &randu::<f32>(Dim4::new(&[5, 3, 1, 1]));
/// let c = &randu::<f32>(Dim4::new(&[5, 3, 1, 1]));
/// let d = join_many![2; a, b, c];
/// print(&d);
/// ```
///
/// # Panics
///
/// This macro just calls [join_many](./fn.join_many.html) function after collecting all
/// the input arrays into a vector.
// Using macro to implement join many wrapper
#[macro_export]
macro_rules! join_many {
    [$dim: expr; $($x:expr),+] => {
        {
            let mut temp_vec = Vec::new();
            $(
                temp_vec.push($x);
             )*
            $crate::join_many($dim, temp_vec)
        }
    };
}

/// Print given message before printing out the Array to standard output
///
/// # Examples
///
/// ```rust
/// use arrayfire::{Dim4, print_gen, randu, af_print};
/// let dims = Dim4::new(&[3, 1, 1, 1]);
/// let a = randu::<f32>(dims);
/// af_print!("Create a 5-by-3 matrix of random floats on the GPU", a);
/// ```
///
#[macro_export]
macro_rules! af_print {
    [$msg: expr, $x: expr] => {
        {
            $crate::print_gen(String::from($msg), &$x, Some(4));
        }
    };
}

/// Evaluate arbitrary number of arrays
#[macro_export]
macro_rules! eval {
    [$($x:expr),+] => {
        {
            let mut temp_vec = Vec::new();
            $(
                temp_vec.push($x);
             )*
            eval_multiple(temp_vec)
        }
    };
}
<|endoftext|>


<commit_before>#![crate_id = "rustful_macros#0.1-pre"]

#![comment = "Macros for rustful"]
#![license = "MIT"]
#![crate_type = "dylib"]

#![doc(html_root_url = "http://ogeon.github.io/rustful/doc/")]

#![feature(macro_rules, plugin_registrar, managed_boxes, quote, phase)]

//!This crate provides some helpful macros for rustful, including `router!` and `routes!`.
//!
//!#`router!`
//!The `router!` macro generates a `Router` containing the provided handlers and routing tree.
//!This can be useful to lower the risk of typing errors, among other things.
//!
//!##Example 1
//!
//!```rust
//!#![feature(phase)]
//!#[phase(plugin)]
//!extern crate rustful_macros;
//!
//!extern crate rustful;
//!
//!...
//!
//!
//!let router = router!{
//!	"/about" => Get: about_us,
//!	"/user/:user" => Get: show_user,
//!	"/product/:name" => Get: show_product,
//!	"/*" => Get: show_error,
//!	"/" => Get: show_welcome
//!};
//!```
//!
//!##Example 2
//!
//!```rust
//!#![feature(phase)]
//!#[phase(plugin)]
//!extern crate rustful_macros;
//!
//!extern crate rustful;
//!
//!...
//!
//!
//!let router = router!{
//!	"/" => Get: show_home,
//!	"home" => Get: show_home,
//!	"user/:username" => {Get: show_user, Post: save_user},
//!	"product" => {
//!		Get: show_all_products,
//!
//!		"json" => Get: send_all_product_data
//!		":id" => {
//!			Get: show_product,
//!			Post | Delete: edit_product,
//!
//!			"json" => Get: send_product_data
//!		}
//!	}
//!};
//!```
//!
//!#`routes!`
//!
//!The `routes!` macro generates a vector of routes, which can be used to create a `Router`.
//!It has the same syntax as `routes!`.
//!
//!```rust
//!#![feature(phase)]
//!#[phase(plugin)]
//!extern crate rustful_macros;
//!
//!extern crate rustful;
//!
//!...
//!
//!
//!let routes = routes!{
//!	"/" => Get: show_home,
//!	"home" => Get: show_home,
//!	"user/:username" => {Get: show_user, Post: save_user},
//!	"product" => {
//!		Get: show_all_products,
//!
//!		"json" => Get: send_all_product_data
//!		":id" => {
//!			Get: show_product,
//!			Post | Delete: edit_product,
//!
//!			"json" => Get: send_product_data
//!		}
//!	}
//!};
//!
//!let router = Router::from_routes(routes);
//!```

extern crate syntax;
extern crate rustc;

use std::path::BytesContainer;

use syntax::{ast, codemap};
use syntax::ext::base::{
	ExtCtxt, MacResult, MacExpr,
	NormalTT, BasicMacroExpander
};
use syntax::ext::build::AstBuilder;
use syntax::ext::quote::rt::ExtParseUtils;
use syntax::parse;
use syntax::parse::token;
use syntax::parse::parser;
use syntax::parse::parser::Parser;
//use syntax::print::pprust;

use rustc::plugin::Registry;

#[plugin_registrar]
#[doc(hidden)]
pub fn macro_registrar(reg: &mut Registry) {
	let expander = box BasicMacroExpander{expander: expand_router, span: None};
	reg.register_syntax_extension(token::intern("router"), NormalTT(expander, None));

	let expander = box BasicMacroExpander{expander: expand_routes, span: None};
	reg.register_syntax_extension(token::intern("routes"), NormalTT(expander, None));
}

fn expand_router(cx: &mut ExtCtxt, sp: codemap::Span, tts: &[ast::TokenTree]) -> Box<MacResult> {
	let router_ident = cx.ident_of("router");
	let insert_method = cx.ident_of("insert_item");

	let mut calls: Vec<@ast::Stmt> = vec!(
		cx.stmt_let(sp, true, router_ident, quote_expr!(&cx, ::rustful::Router::new()))
	);

	for (path, method, handler) in parse_routes(cx, tts).move_iter() {
		let path_expr = cx.parse_expr(format!("\"{}\"", path));
		let method_expr = cx.expr_path(method);
		calls.push(cx.stmt_expr(
			cx.expr_method_call(sp, cx.expr_ident(sp, router_ident), insert_method, vec!(method_expr, path_expr, handler))
		));
	}

	let block = cx.expr_block(cx.block(sp, calls, Some(cx.expr_ident(sp, router_ident))));

	MacExpr::new(block)
}

fn expand_routes(cx: &mut ExtCtxt, sp: codemap::Span, tts: &[ast::TokenTree]) -> Box<MacResult> {
	let routes = parse_routes(cx, tts).move_iter().map(|(path, method, handler)| {
		let path_expr = cx.parse_expr(format!("\"{}\"", path));
		let method_expr = cx.expr_path(method);
		mk_tup(sp, vec!(method_expr, path_expr, handler))
	}).collect();

	MacExpr::new(cx.expr_vec(sp, routes))
}

fn parse_routes(cx: &mut ExtCtxt, tts: &[ast::TokenTree]) -> Vec<(String, ast::Path, @ast::Expr)> {

	let mut parser = parse::new_parser_from_tts(
		cx.parse_sess(), cx.cfg(), Vec::from_slice(tts)
	);

	parse_subroutes("", cx, &mut parser)
}

fn parse_subroutes(base: &str, cx: &mut ExtCtxt, parser: &mut Parser) -> Vec<(String, ast::Path, @ast::Expr)> {
	let mut routes = Vec::new();

	while !parser.eat(&token::EOF) {
		match parser.parse_optional_str() {
			Some((ref s, _)) => {
				if !parser.eat(&token::FAT_ARROW) {
					parser.expect(&token::FAT_ARROW);
					break;
				}

				let mut new_base = base.to_string();
				match s.container_as_str() {
					Some(s) => {
						new_base.push_str(s.trim_chars('/'));
						new_base.push_str("/");
					},
					None => cx.span_err(parser.span, "invalid path")
				}

				if parser.eat(&token::EOF) {
					cx.span_err(parser.span, "unexpected end of routing tree");
				}

				if parser.eat(&token::LBRACE) {
					let subroutes = parse_subroutes(new_base.as_slice(), cx, parser);
					routes.push_all(subroutes.as_slice());

					if parser.eat(&token::RBRACE) {
						if !parser.eat(&token::COMMA) {
							break;
						}
					} else {
						parser.expect_one_of([token::COMMA, token::RBRACE], []);
					}
				} else {
					for (method, handler) in parse_handler(parser).move_iter() {
						routes.push((new_base.clone(), method, handler))
					}

					if !parser.eat(&token::COMMA) {
						break;
					}
				}
			},
			None => {
				for (method, handler) in parse_handler(parser).move_iter() {
					routes.push((base.to_string(), method, handler))
				}

				if !parser.eat(&token::COMMA) {
					break;
				}
			}
		}
	}

	routes
}

fn parse_handler(parser: &mut Parser) -> Vec<(ast::Path, @ast::Expr)> {
	let mut methods = Vec::new();

	loop {
		methods.push(parser.parse_path(parser::NoTypesAllowed).path);

		if parser.eat(&token::COLON) {
			break;
		}

		if !parser.eat(&token::BINOP(token::OR)) {
			parser.expect_one_of([token::COLON, token::BINOP(token::OR)], []);
		}
	}

	let handler = parser.parse_expr();

	methods.move_iter().map(|m| (m, handler.clone())).collect()
}

fn mk_tup(sp: codemap::Span, content: Vec<@ast::Expr>) -> @ast::Expr {
	dummy_expr(sp, ast::ExprTup(content))
}

fn dummy_expr(sp: codemap::Span, e: ast::Expr_) -> @ast::Expr {
	@ast::Expr {
		id: ast::DUMMY_NODE_ID,
		node: e,
		span: sp,
	}
}

/**
A macro for assigning content types.

It takes a main type, a sub type and a parameter list. Instead of this:

```
response.headers.content_type = Some(MediaType {
	type_: String::from_str("text"),
	subtype: String::from_str("html"),
	parameters: vec!((String::from_str("charset"), String::from_str("UTF-8")))
});
```

it can be written like this:

```
response.headers.content_type = content_type!("text", "html", "charset": "UTF-8");
```

The `"charset": "UTF-8"` part defines the parameter list for the content type.
It may contain more than one parameter, or be omitted:

```
response.headers.content_type = content_type!("application", "octet-stream", "type": "image/gif", "padding": "4");
```

```
response.headers.content_type = content_type!("image", "png");
```
**/
#[macro_export]
macro_rules! content_type(
	($main_type:expr, $sub_type:expr) => ({
		Some(::http::headers::content_type::MediaType {
			type_: String::from_str($main_type),
			subtype: String::from_str($sub_type),
			parameters: Vec::new()
		})
	});

	($main_type:expr, $sub_type:expr, $($param:expr: $value:expr),+) => ({
		Some(::http::headers::content_type::MediaType {
			type_: String::from_str($main_type),
			subtype: String::from_str($sub_type),
			parameters: vec!( $( (String::from_str($param), String::from_str($value)) ),+ )
		})
	});
)<commit_msg>@T -> Gc<T><commit_after>#![crate_id = "rustful_macros#0.1-pre"]

#![comment = "Macros for rustful"]
#![license = "MIT"]
#![crate_type = "dylib"]

#![doc(html_root_url = "http://ogeon.github.io/rustful/doc/")]

#![feature(macro_rules, plugin_registrar, quote, phase)]

//!This crate provides some helpful macros for rustful, including `router!` and `routes!`.
//!
//!#`router!`
//!The `router!` macro generates a `Router` containing the provided handlers and routing tree.
//!This can be useful to lower the risk of typing errors, among other things.
//!
//!##Example 1
//!
//!```rust
//!#![feature(phase)]
//!#[phase(plugin)]
//!extern crate rustful_macros;
//!
//!extern crate rustful;
//!
//!...
//!
//!
//!let router = router!{
//!	"/about" => Get: about_us,
//!	"/user/:user" => Get: show_user,
//!	"/product/:name" => Get: show_product,
//!	"/*" => Get: show_error,
//!	"/" => Get: show_welcome
//!};
//!```
//!
//!##Example 2
//!
//!```rust
//!#![feature(phase)]
//!#[phase(plugin)]
//!extern crate rustful_macros;
//!
//!extern crate rustful;
//!
//!...
//!
//!
//!let router = router!{
//!	"/" => Get: show_home,
//!	"home" => Get: show_home,
//!	"user/:username" => {Get: show_user, Post: save_user},
//!	"product" => {
//!		Get: show_all_products,
//!
//!		"json" => Get: send_all_product_data
//!		":id" => {
//!			Get: show_product,
//!			Post | Delete: edit_product,
//!
//!			"json" => Get: send_product_data
//!		}
//!	}
//!};
//!```
//!
//!#`routes!`
//!
//!The `routes!` macro generates a vector of routes, which can be used to create a `Router`.
//!It has the same syntax as `routes!`.
//!
//!```rust
//!#![feature(phase)]
//!#[phase(plugin)]
//!extern crate rustful_macros;
//!
//!extern crate rustful;
//!
//!...
//!
//!
//!let routes = routes!{
//!	"/" => Get: show_home,
//!	"home" => Get: show_home,
//!	"user/:username" => {Get: show_user, Post: save_user},
//!	"product" => {
//!		Get: show_all_products,
//!
//!		"json" => Get: send_all_product_data
//!		":id" => {
//!			Get: show_product,
//!			Post | Delete: edit_product,
//!
//!			"json" => Get: send_product_data
//!		}
//!	}
//!};
//!
//!let router = Router::from_routes(routes);
//!```

extern crate syntax;
extern crate rustc;

use std::path::BytesContainer;
use std::gc::{Gc, GC};

use syntax::{ast, codemap};
use syntax::ext::base::{
	ExtCtxt, MacResult, MacExpr,
	NormalTT, BasicMacroExpander
};
use syntax::ext::build::AstBuilder;
use syntax::ext::quote::rt::ExtParseUtils;
use syntax::parse;
use syntax::parse::token;
use syntax::parse::parser;
use syntax::parse::parser::Parser;
//use syntax::print::pprust;

use rustc::plugin::Registry;

#[plugin_registrar]
#[doc(hidden)]
pub fn macro_registrar(reg: &mut Registry) {
	let expander = box BasicMacroExpander{expander: expand_router, span: None};
	reg.register_syntax_extension(token::intern("router"), NormalTT(expander, None));

	let expander = box BasicMacroExpander{expander: expand_routes, span: None};
	reg.register_syntax_extension(token::intern("routes"), NormalTT(expander, None));
}

fn expand_router(cx: &mut ExtCtxt, sp: codemap::Span, tts: &[ast::TokenTree]) -> Box<MacResult> {
	let router_ident = cx.ident_of("router");
	let insert_method = cx.ident_of("insert_item");

	let mut calls: Vec<Gc<ast::Stmt>> = vec!(
		cx.stmt_let(sp, true, router_ident, quote_expr!(&cx, ::rustful::Router::new()))
	);

	for (path, method, handler) in parse_routes(cx, tts).move_iter() {
		let path_expr = cx.parse_expr(format!("\"{}\"", path));
		let method_expr = cx.expr_path(method);
		calls.push(cx.stmt_expr(
			cx.expr_method_call(sp, cx.expr_ident(sp, router_ident), insert_method, vec!(method_expr, path_expr, handler))
		));
	}

	let block = cx.expr_block(cx.block(sp, calls, Some(cx.expr_ident(sp, router_ident))));

	MacExpr::new(block)
}

fn expand_routes(cx: &mut ExtCtxt, sp: codemap::Span, tts: &[ast::TokenTree]) -> Box<MacResult> {
	let routes = parse_routes(cx, tts).move_iter().map(|(path, method, handler)| {
		let path_expr = cx.parse_expr(format!("\"{}\"", path));
		let method_expr = cx.expr_path(method);
		mk_tup(sp, vec!(method_expr, path_expr, handler))
	}).collect();

	MacExpr::new(cx.expr_vec(sp, routes))
}

fn parse_routes(cx: &mut ExtCtxt, tts: &[ast::TokenTree]) -> Vec<(String, ast::Path, Gc<ast::Expr>)> {

	let mut parser = parse::new_parser_from_tts(
		cx.parse_sess(), cx.cfg(), Vec::from_slice(tts)
	);

	parse_subroutes("", cx, &mut parser)
}

fn parse_subroutes(base: &str, cx: &mut ExtCtxt, parser: &mut Parser) -> Vec<(String, ast::Path, Gc<ast::Expr>)> {
	let mut routes = Vec::new();

	while !parser.eat(&token::EOF) {
		match parser.parse_optional_str() {
			Some((ref s, _)) => {
				if !parser.eat(&token::FAT_ARROW) {
					parser.expect(&token::FAT_ARROW);
					break;
				}

				let mut new_base = base.to_string();
				match s.container_as_str() {
					Some(s) => {
						new_base.push_str(s.trim_chars('/'));
						new_base.push_str("/");
					},
					None => cx.span_err(parser.span, "invalid path")
				}

				if parser.eat(&token::EOF) {
					cx.span_err(parser.span, "unexpected end of routing tree");
				}

				if parser.eat(&token::LBRACE) {
					let subroutes = parse_subroutes(new_base.as_slice(), cx, parser);
					routes.push_all(subroutes.as_slice());

					if parser.eat(&token::RBRACE) {
						if !parser.eat(&token::COMMA) {
							break;
						}
					} else {
						parser.expect_one_of([token::COMMA, token::RBRACE], []);
					}
				} else {
					for (method, handler) in parse_handler(parser).move_iter() {
						routes.push((new_base.clone(), method, handler))
					}

					if !parser.eat(&token::COMMA) {
						break;
					}
				}
			},
			None => {
				for (method, handler) in parse_handler(parser).move_iter() {
					routes.push((base.to_string(), method, handler))
				}

				if !parser.eat(&token::COMMA) {
					break;
				}
			}
		}
	}

	routes
}

fn parse_handler(parser: &mut Parser) -> Vec<(ast::Path, Gc<ast::Expr>)> {
	let mut methods = Vec::new();

	loop {
		methods.push(parser.parse_path(parser::NoTypesAllowed).path);

		if parser.eat(&token::COLON) {
			break;
		}

		if !parser.eat(&token::BINOP(token::OR)) {
			parser.expect_one_of([token::COLON, token::BINOP(token::OR)], []);
		}
	}

	let handler = parser.parse_expr();

	methods.move_iter().map(|m| (m, handler.clone())).collect()
}

fn mk_tup(sp: codemap::Span, content: Vec<Gc<ast::Expr>>) -> Gc<ast::Expr> {
	dummy_expr(sp, ast::ExprTup(content))
}

fn dummy_expr(sp: codemap::Span, e: ast::Expr_) -> Gc<ast::Expr> {
	box(GC) ast::Expr {
		id: ast::DUMMY_NODE_ID,
		node: e,
		span: sp,
	}
}

/**
A macro for assigning content types.

It takes a main type, a sub type and a parameter list. Instead of this:

```
response.headers.content_type = Some(MediaType {
	type_: String::from_str("text"),
	subtype: String::from_str("html"),
	parameters: vec!((String::from_str("charset"), String::from_str("UTF-8")))
});
```

it can be written like this:

```
response.headers.content_type = content_type!("text", "html", "charset": "UTF-8");
```

The `"charset": "UTF-8"` part defines the parameter list for the content type.
It may contain more than one parameter, or be omitted:

```
response.headers.content_type = content_type!("application", "octet-stream", "type": "image/gif", "padding": "4");
```

```
response.headers.content_type = content_type!("image", "png");
```
**/
#[macro_export]
macro_rules! content_type(
	($main_type:expr, $sub_type:expr) => ({
		Some(::http::headers::content_type::MediaType {
			type_: String::from_str($main_type),
			subtype: String::from_str($sub_type),
			parameters: Vec::new()
		})
	});

	($main_type:expr, $sub_type:expr, $($param:expr: $value:expr),+) => ({
		Some(::http::headers::content_type::MediaType {
			type_: String::from_str($main_type),
			subtype: String::from_str($sub_type),
			parameters: vec!( $( (String::from_str($param), String::from_str($value)) ),+ )
		})
	});
)<|endoftext|>


<commit_before>/** Utility macro for implementing `OptionReflect` and generating loading functions.

## `option`-statment

Statement for regular options.

Possible forms:

```rust
option $ty { name: $name }
option $ty;
```

Fields:

* `$ty`: the type `OptionReflect` will be implemented for
* `$name`: the `&'static str` that will be returned by `OptionReflect`, defaults to `stringify!($ty)`

## `alternative`-statment

Statement for regular alternatives.

Possible forms:

```rust
alternative($opt) $ty { name: $name, init: $init }
alternative($opt) $ty { init: $init, name: $name }
alternative($opt) $ty { init: $init }
alternative($opt) $ty { name: $name }
alternative($opt) $ty;
```

Fields:

* `$ty`:
* `$opt`: the option the alternative will be added to
* `$name`: the name of the alternative
* `$init`: the `obj`-value that will be passed to `RegisterModifier::add_alternative`, defaults to
  `box <$ty as Default>::default() as Box<$opt>`

## `single`-statment

Statement for single alternative options.

Possible forms:

```rust
single $ty { name: $name, init: $init }
single $ty { init: $init, name: $name }
single $ty { init: $init }
single $ty { name: $name }
single $ty;
```

Fields:

* `$ty`: the type `OptionReflect` will be implemented for
* `$name`: the `&'static str` that will be returned by `OptionReflect`, defaults to `stringify!($ty)`
* `$init`: the `obj`-value that will be passed to `RegisterModifier::add_single`, defaults to
* `<$ty as Default>::default()`

# Example

```rust
qregister_load_fns!{

    fn load_stores(&mut RegisterModifier<Store>) => {

        single PositionStore;

        single physics::LinearVelocityStore{
            name: "LinearVelocityStore"
        }

        single ScoreStore{
            init: ScoreStore::from_file(cfg.get("score_file"))
        }

    }

    fn load_services(&mut RegisterModifier<Service>) => {

        single Timing;

        option Physics;

        alternative(Physics) nphysics::Physics{
            name: "NPhysicsPhysics"
        }

        alternative(Physics) LegacyPhysics{
            init: LegacyPhysics::new("0.1.0")
        }

    }
}

pub fn load_module(regs: &mut MyRegisters, cfg: &Cfg){

    load_stores(&mut regs.stores, cfg);
    load_services(&mut regs.services);

    register.wire_alternative("Physics", Some("LegacyPhysics"));
}
```
**/
#[macro_export]
macro_rules! qregister_load_fns {

    // 1.0 endpoint
    ($col:ident <-) => {};

    // 1.1 expansion
    ($col:ident <- single $ty:ty { name: $name:expr, init: $init:expr } $($ff:tt)*) => {
        {
            impl OptionReflect for $ty {
                fn option_name() -> &'static str { $name }
            }

            $col.singles.push(({$name}.to_string(), Box::new($init)));

            qregister_load_fns!($col <- $($ff)*);
        }
    };

    // 1.1 variant: $init and $name permutated
    ($col:ident <- single $ty:ty { init: $init:expr, name: $name:expr } $($ff:tt)*) => {
        qregister_load_fns!{
            $col <- single $ty { name: $name, init: $init }
            $($ff)*
        }
    };

    // 1.1 variant: $name omitted, default to type-name
    ($col:ident <- single $ty:ty { init: $init:expr } $($ff:tt)*) => {
        qregister_load_fns!{
            $col <- single $ty { name: stringify!($ty), init: $init }
            $($ff)*
        }
    };

    // 1.1 variant: $init ommited, default to default-ctor
    ($col:ident <- single $ty:ty { name: $name:expr } $($ff:tt)*) => {
        qregister_load_fns!{
            $col <- single $ty { name: $name, init: <$ty as Default>::default() }
            $($ff)*
        }
    };

    // 1.1 variant: $name and $init ommitted, default type-name and default-ctor
    ($col:ident <- single $ty:ty; $($ff:tt)*) => {
        qregister_load_fns!{
            $col <- single $ty { name: stringify!($ty) }
            $($ff)*
        }
    };

    // 1.2 expansion
    ($col:ident <- option $ty:ty { name: $name:expr } $($ff:tt)*) => {
        {
            impl OptionReflect for Box<$ty> {
                fn option_name() -> &'static str { $name }
            }

            $col.options.push({$name}.to_string());

            qregister_load_fns!($col <- $($ff)*);
        }
    };

    // 1.2 variant: $name omitted, default to type-name
    ($col:ident <- option $ty:ty; $($ff:tt)*) => {
        qregister_load_fns!{
            $col <- option $ty { name: stringify!($ty) }
            $($ff)*
        }
    };

    // 1.3 expansion
    ($col:ident <- alternative($opt:ty) $ty:ty { name: $name:expr, init: $init:expr } $($ff:tt)*) => {
        {
            // utility to ensure that `t` is of type `T` (useful for compile-errors)
            fn _echo<T>(t: T) -> T { t }

            $col.alternatives.push((<Box<$opt> as ::qregister::OptionReflect>::option_name(),
                                    {$name}.to_string(),
                                    Box::new(_echo::<Box<$opt>>($init))));

            qregister_load_fns!($col <- $($ff)*);
        }
    };

    // 1.3 variant: $init and $name permutated
    ($col:ident <- alternative($opt:ty) $ty:ty { init: $init:expr, name: $name:expr } $($ff:tt)*) => {
        qregister_load_fns!{
            $col <- alternative($opt) $ty { name: $name, init: $init }
            $($ff)*
        }
    };

    // 1.3 variant: $name omitted, default to type-name
    ($col:ident <- alternative($opt:ty) $ty:ty { init: $init:expr } $($ff:tt)*) => {
        qregister_load_fns!{
            $col <- alternative($opt) $ty { name: stringify!($ty), init: $init }
            $($ff)*
        }
    };

    // 1.3 variant: $init ommited, default to default-ctor
    ($col:ident <- alternative($opt:ty) $ty:ty { name: $name:expr } $($ff:tt)*) => {
        qregister_load_fns!{
            $col <- alternative($opt) $ty { name: $name, init: Box::new(<$ty as Default>::default()) as Box<$opt> }
            $($ff)*
        }
    };

    // 1.3 variant: $name and $init ommitted, default to type-name and default-ctor
    ($col:ident <- alternative($opt:ty) $ty:ty; $($ff:tt)*) => {
        qregister_load_fns!{
            $col <- alternative($opt) $ty { name: stringify!($ty) }
            $($ff)*
        }
    };

    // 2.0 endpoint
    () => {};

    // 2.1 expansion
    ($(#[$mmm:meta])* fn $name:ident($reg_type:ty, $($args:ident: $arg_types:ty),*) => { $($stmts:tt)+ } $($ff:tt)*) => {
        $(#[$mmm])*
        #[allow(unused)]
        fn $name(reg: $reg_type, $($args: $arg_types),*){
            use qregister::OptionReflect;
            use std::any::Any;

            struct Collect<Base: Any + ?Sized> {
                singles: Vec<(String, Box<Base>)>,
                options: Vec<String>,
                alternatives: Vec<(&'static str, String, Box<Base>)>,
            }
            let mut col = Collect{ singles: vec![], options: vec![], alternatives: vec![] };

            qregister_load_fns!(col <- $($stmts)+);

            for (name, obj) in col.singles {
                reg.add_single(name, obj);
            }
            for name in col.options {
                reg.add_option(name);
            }
            for (opt_name, alt_name, obj) in col.alternatives {
                reg.add_alternative(opt_name, alt_name, obj);
            }
        }
        qregister_load_fns!($($ff)*);
    };

    // 2.1 variant: no `,` after $reg_type
    ($(#[$mmm:meta])* fn $name:ident($reg_type:ty) => { $($stmts:tt)+ } $($ff:tt)*) => {
        qregister_load_fns!{
            $(#[$mmm])*
            fn $name($reg_type,) => {
                $($stmts)+
            }
            $($ff)*
        }
    };
}

/*
use std::any::Any;
pub trait Base: Any + 'static {}
impl<B: ?Sized + Base> Base for Box<B> {}

pub trait SecondBase: Base {}

#[derive(Default)]
pub struct Foo;
impl Base for Foo {}

#[derive(Default)]
pub struct Bar;
impl Base for Bar {}
impl SecondBase for Bar {}

/*#[test]
pub fn test(){

    qregister_load_fns!{
        col <- single Foo{ init: Foo }
        col <- option SecondBase{ name: "2ndBase" }
        col <- alternative(SecondBase) Bar;
    }
}*/

#[derive(Default)]
pub struct Arb;
impl Base for Arb {}
impl SecondBase for Arb {}

qregister_load_fns!{
    fn test(&mut ::qregister::RegisterModifier<Base>, lel: i8) => {
        single Foo{ init: {lel + 2; Foo } }

        option SecondBase;

        alternative(SecondBase) Bar;
    }
    fn test_two(&mut ::qregister::RegisterModifier<SecondBase>) => {
        single Arb;
    }
}*/
<commit_msg>update macro<commit_after>/** Utility macro for implementing `OptionReflect` and generating loading functions.

## `option`-statment

Statement for regular options.

Possible forms:

```rust
option $ty { name: $name }
option $ty;
```

Fields:

* `$ty`: the type `OptionReflect` will be implemented for
* `$name`: the `&'static str` that will be returned by `OptionReflect`, defaults to `stringify!($ty)`

## `alternative`-statment

Statement for regular alternatives.

Possible forms:

```rust
alternative($opt) $ty { name: $name, init: $init }
alternative($opt) $ty { init: $init, name: $name }
alternative($opt) $ty { init: $init }
alternative($opt) $ty { name: $name }
alternative($opt) $ty;
```

Fields:

* `$ty`:
* `$opt`: the option the alternative will be added to
* `$name`: the name of the alternative
* `$init`: the `obj`-value that will be passed to `RegisterModifier::add_alternative`, defaults to
  `box <$ty as Default>::default() as Box<$opt>`

## `single`-statment

Statement for single alternative options.

Possible forms:

```rust
single $ty { name: $name, init: $init }
single $ty { init: $init, name: $name }
single $ty { init: $init }
single $ty { name: $name }
single $ty;
```

Fields:

* `$ty`: the type `OptionReflect` will be implemented for
* `$name`: the `&'static str` that will be returned by `OptionReflect`, defaults to `stringify!($ty)`
* `$init`: the `obj`-value that will be passed to `RegisterModifier::add_single`, defaults to
* `<$ty as Default>::default()`

# Example

```rust
qregister_load_fns!{

    fn load_stores(&mut RegisterModifier<Store>) => {

        single PositionStore;

        single physics::LinearVelocityStore{
            name: "LinearVelocityStore"
        }

        single ScoreStore{
            init: ScoreStore::from_file(cfg.get("score_file"))
        }

    }

    fn load_services(&mut RegisterModifier<Service>) => {

        single Timing;

        option Physics;

        alternative(Physics) nphysics::Physics{
            name: "NPhysicsPhysics"
        }

        alternative(Physics) LegacyPhysics{
            init: LegacyPhysics::new("0.1.0")
        }

    }
}

pub fn load_module(regs: &mut MyRegisters, cfg: &Cfg){

    load_stores(&mut regs.stores, cfg);
    load_services(&mut regs.services);

    register.wire_alternative("Physics", Some("LegacyPhysics"));
}
```
**/
#[macro_export]
macro_rules! qregister_load_fns {

    // 1.0 endpoint
    ($col:ident <-) => {};

    // 1.1 expansion
    ($col:ident <- single $ty:ty { name: $name:expr, init: $init:expr } $($ff:tt)*) => {
        {
            impl OptionReflect for $ty {
                fn option_name() -> &'static str { $name }
            }

            $col.singles.push(({$name}.to_string(), Box::new($init)));

            qregister_load_fns!($col <- $($ff)*);
        }
    };

    // 1.1 variant: $init and $name permutated
    ($col:ident <- single $ty:ty { init: $init:expr, name: $name:expr } $($ff:tt)*) => {
        qregister_load_fns!{
            $col <- single $ty { name: $name, init: $init }
            $($ff)*
        }
    };

    // 1.1 variant: $name omitted, default to type-name
    ($col:ident <- single $ty:ty { init: $init:expr } $($ff:tt)*) => {
        qregister_load_fns!{
            $col <- single $ty { name: stringify!($ty), init: $init }
            $($ff)*
        }
    };

    // 1.1 variant: $init ommited, default to default-ctor
    ($col:ident <- single $ty:ty { name: $name:expr } $($ff:tt)*) => {
        qregister_load_fns!{
            $col <- single $ty { name: $name, init: <$ty as Default>::default() }
            $($ff)*
        }
    };

    // 1.1 variant: $name and $init ommitted, default type-name and default-ctor
    ($col:ident <- single $ty:ty; $($ff:tt)*) => {
        qregister_load_fns!{
            $col <- single $ty { name: stringify!($ty) }
            $($ff)*
        }
    };

    // 1.2 expansion
    ($col:ident <- option $ty:ty { name: $name:expr } $($ff:tt)*) => {
        {
            impl OptionReflect for Box<$ty> {
                fn option_name() -> &'static str { $name }
            }

            $col.options.push({$name}.to_string());

            qregister_load_fns!($col <- $($ff)*);
        }
    };

    // 1.2 variant: $name omitted, default to type-name
    ($col:ident <- option $ty:ty; $($ff:tt)*) => {
        qregister_load_fns!{
            $col <- option $ty { name: stringify!($ty) }
            $($ff)*
        }
    };

    // 1.3 expansion
    ($col:ident <- alternative($opt:ty) $ty:ty { name: $name:expr, init: $init:expr } $($ff:tt)*) => {
        {

            $col.alternatives.push((<Box<$opt> as ::qregister::OptionReflect>::option_name(),
                                    {$name}.to_string(),
                                    Box::new(Box::new($init) as Box<$opt>)));

            qregister_load_fns!($col <- $($ff)*);
        }
    };

    // 1.3 variant: $init and $name permutated
    ($col:ident <- alternative($opt:ty) $ty:ty { init: $init:expr, name: $name:expr } $($ff:tt)*) => {
        qregister_load_fns!{
            $col <- alternative($opt) $ty { name: $name, init: $init }
            $($ff)*
        }
    };

    // 1.3 variant: $name omitted, default to type-name
    ($col:ident <- alternative($opt:ty) $ty:ty { init: $init:expr } $($ff:tt)*) => {
        qregister_load_fns!{
            $col <- alternative($opt) $ty { name: stringify!($ty), init: $init }
            $($ff)*
        }
    };

    // 1.3 variant: $init ommited, default to default-ctor
    ($col:ident <- alternative($opt:ty) $ty:ty { name: $name:expr } $($ff:tt)*) => {
        qregister_load_fns!{
            $col <- alternative($opt) $ty { name: $name, init: <$ty as Default>::default() }
            $($ff)*
        }
    };

    // 1.3 variant: $name and $init ommitted, default to type-name and default-ctor
    ($col:ident <- alternative($opt:ty) $ty:ty; $($ff:tt)*) => {
        qregister_load_fns!{
            $col <- alternative($opt) $ty { name: stringify!($ty) }
            $($ff)*
        }
    };

    // 2.0 endpoint
    () => {};

    // 2.1 expansion
    ($(#[$mmm:meta])* fn $name:ident($reg_type:ty, $($args:ident: $arg_types:ty),*) => { $($stmts:tt)+ } $($ff:tt)*) => {
        $(#[$mmm])*
        #[allow(unused)]
        fn $name(reg: $reg_type, $($args: $arg_types),*){
            use qregister::OptionReflect;
            use std::any::Any;

            struct Collect<Base: Any + ?Sized> {
                singles: Vec<(String, Box<Base>)>,
                options: Vec<String>,
                alternatives: Vec<(&'static str, String, Box<Base>)>,
            }
            let mut col = Collect{ singles: vec![], options: vec![], alternatives: vec![] };

            qregister_load_fns!(col <- $($stmts)+);

            for (name, obj) in col.singles {
                reg.add_single(name, obj);
            }
            for name in col.options {
                reg.add_option(name);
            }
            for (opt_name, alt_name, obj) in col.alternatives {
                reg.add_alternative(opt_name, alt_name, obj);
            }
        }
        qregister_load_fns!($($ff)*);
    };

    // 2.1 variant: no `,` after $reg_type
    ($(#[$mmm:meta])* fn $name:ident($reg_type:ty) => { $($stmts:tt)+ } $($ff:tt)*) => {
        qregister_load_fns!{
            $(#[$mmm])*
            fn $name($reg_type,) => {
                $($stmts)+
            }
            $($ff)*
        }
    };
}

/*
use std::any::Any;
pub trait Base: Any + 'static {}
impl<B: ?Sized + Base> Base for Box<B> {}

pub trait SecondBase: Base {}

#[derive(Default)]
pub struct Foo;
impl Base for Foo {}

#[derive(Default)]
pub struct Bar;
impl Base for Bar {}
impl SecondBase for Bar {}

/*#[test]
pub fn test(){

    qregister_load_fns!{
        col <- single Foo{ init: Foo }
        col <- option SecondBase{ name: "2ndBase" }
        col <- alternative(SecondBase) Bar;
    }
}*/

#[derive(Default)]
pub struct Arb;
impl Base for Arb {}
impl SecondBase for Arb {}

qregister_load_fns!{
    fn test(&mut ::qregister::RegisterModifier<Base>, lel: i8) => {
        single Foo{ init: {lel + 2; Foo } }

        option SecondBase;

        alternative(SecondBase) Bar;
    }
    fn test_two(&mut ::qregister::RegisterModifier<SecondBase>) => {
        single Arb;
    }
}*/
<|endoftext|>


<commit_before>use std::mem::zeroed;
use std::ops::*;

pub type Row = [f32; 4];

#[derive(PartialEq, Clone, Debug)]
pub struct Matrix { m: [Row; 4] }

impl Matrix {
    pub fn zero() -> Self { unsafe { zeroed() } }

    pub fn new(
        m00: f32, m01: f32, m02: f32, m03: f32,
        m10: f32, m11: f32, m12: f32, m13: f32,
        m20: f32, m21: f32, m22: f32, m23: f32,
        m30: f32, m31: f32, m32: f32, m33: f32,
    ) -> Self {
        Matrix {
            m: [
                [ m00, m01, m02, m03 ],
                [ m10, m11, m12, m13 ],
                [ m20, m21, m22, m23 ],
                [ m30, m31, m32, m33 ],
            ]
        }
    }

    pub fn identity() -> Self {
        Matrix {
            m: [
                [1.0, 0.0, 0.0, 0.0],
                [0.0, 1.0, 0.0, 0.0],
                [0.0, 0.0, 1.0, 0.0],
                [0.0, 0.0, 0.0, 1.0],
            ]
        }
    }

    pub fn rotation_x(rad: f32) -> Self {
        let (sin, cos) = rad.sin_cos();

        Matrix {
            m: [
                [1.0,  0.0, 0.0, 0.0],
                [0.0,  cos, sin, 0.0],
                [0.0, -sin, cos, 0.0],
                [0.0,  0.0, 0.0, 1.0],
            ]
        }
    }

    pub fn rotation_y(rad: f32) -> Self {
        let (sin, cos) = rad.sin_cos();

        Matrix {
            m: [
                [cos, 0.0, -sin, 0.0],
                [0.0, 1.0,  0.0, 0.0],
                [sin, 0.0,  cos, 0.0],
                [0.0, 0.0,  0.0, 1.0],
            ]
        }
    }

    pub fn rotation_z(rad: f32) -> Self {
        let (sin, cos) = rad.sin_cos();

        Matrix {
            m: [
                [ cos, sin, 0.0, 0.0],
                [-sin, cos, 0.0, 0.0],
                [ 0.0, 0.0, 1.0, 0.0],
                [ 0.0, 0.0, 0.0, 1.0],
            ]
        }
    }

    pub fn orthographic(view_width: f32, view_height: f32, near_z: f32, far_z: f32) -> Self {
        // assert(!XMScalarNearEqual(ViewWidth, 0.0f, 0.00001f));
        // assert(!XMScalarNearEqual(ViewHeight, 0.0f, 0.00001f));
        // assert(!XMScalarNearEqual(FarZ, NearZ, 0.00001f));
        let f_range = 1.0/(near_z - far_z);
        Matrix {
            m: [
                [2.0/view_width, 0.0, 0.0, 0.0],
                [0.0, 2.0/view_height, 0.0, 0.0],
                [0.0, 0.0, f_range, 0.0],
                [0.0, 0.0, f_range*near_z, 1.0],
            ]
        }

    }

    pub fn orthographic_off_center(view_left: f32, view_right: f32, view_bottom: f32, view_top: f32, near_z: f32, far_z: f32) -> Self {
        // reciprocal width and height
        let r_width = 1.0/(view_right - view_left);
        let r_height = 1.0/(view_top - view_bottom);
        let range = 1.0/(near_z-far_z);

        Matrix {
            m: [
                [r_width + r_width, 0.0, 0.0, 0.0],
                [0.0, r_height + r_height, 0.0, 0.0],
                [0.0, 0.0, range, 0.0],
                [-(view_left + view_right)*r_width, -(view_top + view_bottom)*r_height, range*near_z, 1.0],
            ]
        }
    }

    pub fn perspective(width: f32, height: f32, near_z: f32, far_z: f32) -> Self {
        let two_near_z = near_z + near_z;
        let range = far_z/(near_z - far_z);

        Matrix {
            m: [
                [two_near_z/width, 0.0, 0.0, 0.0],
                [0.0, two_near_z/height, 0.0, 0.0],
                [0.0, 0.0, range, -1.0],
                [0.0, 0.0, range*near_z, 0.0],
            ]
        }
    }

    /// aspect: Width / Height
    pub fn perspective_fov(fov: f32, aspect: f32, near_z: f32, far_z: f32) -> Self {
        let (sin, cos) = (0.5 * fov).sin_cos();
        let f = cos/sin;
        let range = far_z/(near_z - far_z);

        Matrix {
            m: [
                [f/aspect, 0.0, 0.0, 0.0],
                [0.0, f, 0.0, 0.0],
                [0.0, 0.0, range, -1.0],
                [0.0, 0.0, range*near_z, 0.0],
            ]
        }
    }

    pub fn translation(ox: f32, oy: f32, oz: f32) -> Self {
        Matrix {
            m: [
                [1.0, 0.0, 0.0, 0.0],
                [0.0, 1.0, 0.0, 0.0],
                [0.0, 0.0, 1.0, 0.0],
                [ox,  oy,  oz,  1.0],
            ]
        }
    }

    pub fn transpose(self) -> Self {
        Matrix {
            m: [
                [self.m[0][0], self.m[1][0], self.m[2][0], self.m[3][0]],
                [self.m[0][1], self.m[1][1], self.m[2][1], self.m[3][1]],
                [self.m[0][2], self.m[1][2], self.m[2][2], self.m[3][2]],
                [self.m[0][3], self.m[1][3], self.m[2][3], self.m[3][3]],
            ]
        }
    }
}

impl Mul for Matrix {
    type Output = Matrix;
    fn mul(self, rhs: Matrix) -> Matrix { &self * &rhs }
}

impl<'a> Mul<Matrix> for &'a Matrix {
    type Output = Matrix;
    fn mul(self, rhs: Matrix) -> Matrix { self * &rhs }
}

impl<'a> Mul<&'a Matrix> for Matrix {
    type Output = Matrix;
    fn mul(self, rhs: &'a Matrix) -> Matrix { &self * rhs }
}

impl<'a, 'b> Mul<&'a Matrix> for &'b Matrix {
    type Output = Matrix;

    fn mul(self, rhs: &'a Matrix) -> Matrix {
        macro_rules! row {
            ($col:expr) => ({
                let x = self.m[$col][0];
                let y = self.m[$col][1];
                let z = self.m[$col][2];
                let w = self.m[$col][3];
                [
                    (rhs.m[0][0]*x)+(rhs.m[1][0]*y)+(rhs.m[2][0]*z)+(rhs.m[3][0]*w),
                    (rhs.m[0][1]*x)+(rhs.m[1][1]*y)+(rhs.m[2][1]*z)+(rhs.m[3][1]*w),
                    (rhs.m[0][2]*x)+(rhs.m[1][2]*y)+(rhs.m[2][2]*z)+(rhs.m[3][2]*w),
                    (rhs.m[0][3]*x)+(rhs.m[1][3]*y)+(rhs.m[2][3]*z)+(rhs.m[3][3]*w),
                ]
            })
        }

        Matrix { m: [ row!(0), row!(1), row!(2), row!(3) ] }
    }
}

impl Index<usize> for Matrix {
    type Output = [f32;4];
    fn index<'a>(&'a self, index: usize) -> &'a Self::Output {
        &self.m[index]
    }
}

#[cfg(feature = "glium-support")]
mod glium_support {
    use super::Matrix;
    use glium::uniforms::{AsUniformValue, UniformValue};

    impl AsUniformValue for Matrix {
        fn as_uniform_value(&self) -> UniformValue<'static> {
            UniformValue::Mat4(self.m)
        }
    }
}
<commit_msg>Implement Into<[[f32;4];4]> for matrix<commit_after>use std::mem::zeroed;
use std::ops::*;

pub type Row = [f32; 4];

#[derive(PartialEq, Clone, Debug)]
pub struct Matrix { m: [Row; 4] }

impl Matrix {
    pub fn zero() -> Self { unsafe { zeroed() } }

    pub fn new(
        m00: f32, m01: f32, m02: f32, m03: f32,
        m10: f32, m11: f32, m12: f32, m13: f32,
        m20: f32, m21: f32, m22: f32, m23: f32,
        m30: f32, m31: f32, m32: f32, m33: f32,
    ) -> Self {
        Matrix {
            m: [
                [ m00, m01, m02, m03 ],
                [ m10, m11, m12, m13 ],
                [ m20, m21, m22, m23 ],
                [ m30, m31, m32, m33 ],
            ]
        }
    }

    pub fn identity() -> Self {
        Matrix {
            m: [
                [1.0, 0.0, 0.0, 0.0],
                [0.0, 1.0, 0.0, 0.0],
                [0.0, 0.0, 1.0, 0.0],
                [0.0, 0.0, 0.0, 1.0],
            ]
        }
    }

    pub fn rotation_x(rad: f32) -> Self {
        let (sin, cos) = rad.sin_cos();

        Matrix {
            m: [
                [1.0,  0.0, 0.0, 0.0],
                [0.0,  cos, sin, 0.0],
                [0.0, -sin, cos, 0.0],
                [0.0,  0.0, 0.0, 1.0],
            ]
        }
    }

    pub fn rotation_y(rad: f32) -> Self {
        let (sin, cos) = rad.sin_cos();

        Matrix {
            m: [
                [cos, 0.0, -sin, 0.0],
                [0.0, 1.0,  0.0, 0.0],
                [sin, 0.0,  cos, 0.0],
                [0.0, 0.0,  0.0, 1.0],
            ]
        }
    }

    pub fn rotation_z(rad: f32) -> Self {
        let (sin, cos) = rad.sin_cos();

        Matrix {
            m: [
                [ cos, sin, 0.0, 0.0],
                [-sin, cos, 0.0, 0.0],
                [ 0.0, 0.0, 1.0, 0.0],
                [ 0.0, 0.0, 0.0, 1.0],
            ]
        }
    }

    pub fn orthographic(view_width: f32, view_height: f32, near_z: f32, far_z: f32) -> Self {
        // assert(!XMScalarNearEqual(ViewWidth, 0.0f, 0.00001f));
        // assert(!XMScalarNearEqual(ViewHeight, 0.0f, 0.00001f));
        // assert(!XMScalarNearEqual(FarZ, NearZ, 0.00001f));
        let f_range = 1.0/(near_z - far_z);
        Matrix {
            m: [
                [2.0/view_width, 0.0, 0.0, 0.0],
                [0.0, 2.0/view_height, 0.0, 0.0],
                [0.0, 0.0, f_range, 0.0],
                [0.0, 0.0, f_range*near_z, 1.0],
            ]
        }

    }

    pub fn orthographic_off_center(view_left: f32, view_right: f32, view_bottom: f32, view_top: f32, near_z: f32, far_z: f32) -> Self {
        // reciprocal width and height
        let r_width = 1.0/(view_right - view_left);
        let r_height = 1.0/(view_top - view_bottom);
        let range = 1.0/(near_z-far_z);

        Matrix {
            m: [
                [r_width + r_width, 0.0, 0.0, 0.0],
                [0.0, r_height + r_height, 0.0, 0.0],
                [0.0, 0.0, range, 0.0],
                [-(view_left + view_right)*r_width, -(view_top + view_bottom)*r_height, range*near_z, 1.0],
            ]
        }
    }

    pub fn perspective(width: f32, height: f32, near_z: f32, far_z: f32) -> Self {
        let two_near_z = near_z + near_z;
        let range = far_z/(near_z - far_z);

        Matrix {
            m: [
                [two_near_z/width, 0.0, 0.0, 0.0],
                [0.0, two_near_z/height, 0.0, 0.0],
                [0.0, 0.0, range, -1.0],
                [0.0, 0.0, range*near_z, 0.0],
            ]
        }
    }

    /// aspect: Width / Height
    pub fn perspective_fov(fov: f32, aspect: f32, near_z: f32, far_z: f32) -> Self {
        let (sin, cos) = (0.5 * fov).sin_cos();
        let f = cos/sin;
        let range = far_z/(near_z - far_z);

        Matrix {
            m: [
                [f/aspect, 0.0, 0.0, 0.0],
                [0.0, f, 0.0, 0.0],
                [0.0, 0.0, range, -1.0],
                [0.0, 0.0, range*near_z, 0.0],
            ]
        }
    }

    pub fn translation(ox: f32, oy: f32, oz: f32) -> Self {
        Matrix {
            m: [
                [1.0, 0.0, 0.0, 0.0],
                [0.0, 1.0, 0.0, 0.0],
                [0.0, 0.0, 1.0, 0.0],
                [ox,  oy,  oz,  1.0],
            ]
        }
    }

    pub fn transpose(self) -> Self {
        Matrix {
            m: [
                [self.m[0][0], self.m[1][0], self.m[2][0], self.m[3][0]],
                [self.m[0][1], self.m[1][1], self.m[2][1], self.m[3][1]],
                [self.m[0][2], self.m[1][2], self.m[2][2], self.m[3][2]],
                [self.m[0][3], self.m[1][3], self.m[2][3], self.m[3][3]],
            ]
        }
    }
}

impl Mul for Matrix {
    type Output = Matrix;
    fn mul(self, rhs: Matrix) -> Matrix { &self * &rhs }
}

impl<'a> Mul<Matrix> for &'a Matrix {
    type Output = Matrix;
    fn mul(self, rhs: Matrix) -> Matrix { self * &rhs }
}

impl<'a> Mul<&'a Matrix> for Matrix {
    type Output = Matrix;
    fn mul(self, rhs: &'a Matrix) -> Matrix { &self * rhs }
}

impl<'a, 'b> Mul<&'a Matrix> for &'b Matrix {
    type Output = Matrix;

    fn mul(self, rhs: &'a Matrix) -> Matrix {
        macro_rules! row {
            ($col:expr) => ({
                let x = self.m[$col][0];
                let y = self.m[$col][1];
                let z = self.m[$col][2];
                let w = self.m[$col][3];
                [
                    (rhs.m[0][0]*x)+(rhs.m[1][0]*y)+(rhs.m[2][0]*z)+(rhs.m[3][0]*w),
                    (rhs.m[0][1]*x)+(rhs.m[1][1]*y)+(rhs.m[2][1]*z)+(rhs.m[3][1]*w),
                    (rhs.m[0][2]*x)+(rhs.m[1][2]*y)+(rhs.m[2][2]*z)+(rhs.m[3][2]*w),
                    (rhs.m[0][3]*x)+(rhs.m[1][3]*y)+(rhs.m[2][3]*z)+(rhs.m[3][3]*w),
                ]
            })
        }

        Matrix { m: [ row!(0), row!(1), row!(2), row!(3) ] }
    }
}

impl Index<usize> for Matrix {
    type Output = [f32;4];
    fn index<'a>(&'a self, index: usize) -> &'a Self::Output {
        &self.m[index]
    }
}

/// glium_text support
impl Into<[[f32; 4]; 4]> for Matrix {
    fn into(self) -> [[f32; 4]; 4] { self.m }
}

#[cfg(feature = "glium-support")]
mod glium_support {
    use super::Matrix;
    use glium::uniforms::{AsUniformValue, UniformValue};

    impl AsUniformValue for Matrix {
        fn as_uniform_value(&self) -> UniformValue<'static> {
            UniformValue::Mat4(self.m)
        }
    }
}
<|endoftext|>