<commit_before>// pest. The Elegant Parser
// Copyright (C) 2017  Dragoș Tiselice
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

//! # pest. The Elegant Parser
//!
//! pest is a [PEG](https://en.wikipedia.org/wiki/Parsing_expression_grammar) parser built with
//! *simplicity* and *speed* in mind.
//!
//! This crate works in conjunction with the [`pest` crate](https://docs.rs/pest) by
//! deriving a grammar implementation based on a provided grammar.
//!
//! ## `.pest` files
//!
//! Grammar definitions reside in custom `.pest` files located in the `src` directory. Their path is
//! relative to `src` and is specified between the `derive` attribute and empty `struct` that
//! `Parser` will be derived on.
//!
//! Because of a limitation in procedural macros, there is no way for Cargo to know that a module
//! needs to be recompiled based on the file that the procedural macro is opening. This leads to the
//! case where modifying a `.pest` file without touching the file where the `derive` is does not
//! recompile it if it already has a working binary in the cache. To avoid this issue, the grammar
//! file can be included in a dummy `const` definition while debugging.
//!
//! ```ignore
//! const _GRAMMAR: &'static = include_str!("path/to/my_grammar.pest"); // relative to this file
//!
//! #[derive(Parser)]
//! #[grammar = "path/to/my_grammar.pest"] // relative to src
//! struct MyParser;
//! ```
//!
//! ## Grammar
//!
//! A grammar is a series of rules separated by whitespace, possibly containing comments.
//!
//! ### Comments
//!
//! Comments start with `//` and end at the end of the line.
//!
//! ```text
//! // a comment
//! ```
//!
//! ### Rules
//!
//! Rules have the following form:
//!
//! ```text
//! name = optional_modifier { expression }
//! ```
//!
//! The name of the rule is formed from alphanumeric characters or `_` with the condition that the
//! first character is not a digit and is used to create token pairs. When the rule starts being
//! parsed, the starting part of the token is being produced, with the ending part being produced
//! when the rule finishes parsing.
//!
//! The following token pair notation `a(b(), c())` denotes the tokens: start `a`, start `b`, end
//! `b`, start `c`, end `c`, end `a`.
//!
//! #### Modifiers
//!
//! Modifiers are optional and can be one of `_`, `@`, `$`, or `!`. These modifiers change the
//! behavior of the rules.
//!
//! 1. Silent (`_`)
//!
//!     Silent rules do not create token pairs during parsing, nor are they error-reported.
//!
//!     ```text
//!     a = _{ "a" }
//!     b =  { a ~ "b" }
//!     ```
//!
//!     Parsing `"ab"` produces the token pair `b()`.
//!
//! 2. Atomic (`@`)
//!
//!     Atomic rules do not accept whitespace or comments between within their expressions and have a
//!     cascading effect on any rule they call. I.e. rules that are not atomic but are called by atomic
//!     rules behave atomically.
//!
//!     Any rules called by atomic rules do not generate token pairs.
//!
//!     ```text
//!     a =  { "a" }
//!     b = @{ a ~ "b" }
//!
//!     whitespace = _{ " " }
//!     ```
//!
//!     Parsing `"ab"` produces the token pair `b()`, while `"a   b"` produces an error.
//!
//! 3. Compound-atomic (`$`)
//!
//!     Compound-atomic are identical to atomic rules with the exception that rules called by them are
//!     not forbidden from generating token pairs.
//!
//!     ```text
//!     a =  { "a" }
//!     b = ${ a ~ "b" }
//!
//!     whitespace = _{ " " }
//!     ```
//!
//!     Parsing `"ab"` produces the token pairs `b(a())`, while `"a   b"` produces an error.
//!
//! 4. Non-atomic (`!`)
//!
//!     Non-atomic are identical to normal rules with the exception that they stop the cascading effect
//!     of atomic and compound-atomic rules.
//!
//!     ```text
//!     a =  { "a" }
//!     b = !{ a ~ "b" }
//!     c = @{ b }
//!
//!     whitespace = _{ " " }
//!     ```
//!
//!     Parsing both `"ab"` and `"a   b"` produce the token pairs `c(b(a()))`.
//!
//! #### Expressions
//!
//! Expressions can be either terminals or non-terminals.
//!
//! 1. Terminals
//!
//!     | Terminal   | Usage                                                          |
//!     |------------|----------------------------------------------------------------|
//!     | `"a"`      | matches the exact string `"a"`                                 |
//!     | `^"a"`     | matches the exact string `"a"` case insensitively (ASCII only) |
//!     | `'a'..'z'` | matches one character between `'a'` and `'z'`                  |
//!     | `a`        | matches rule `a`                                               |
//!
//! 2. Non-terminals
//!
//!     | Non-terminal | Usage                                                      |
//!     |--------------|------------------------------------------------------------|
//!     | `(e)`        | matches `e`                                                |
//!     | `e1 ~ e2`    | matches the sequence `e1` `e2`                             |
//!     | `e1 | e2`    | matches either `e1` or `e1`                                |
//!     | `e*`         | matches `e` zero or more times                             |
//!     | `e+`         | matches `e` one or more times                              |
//!     | `e?`         | optionally matches `e`                                     |
//!     | `&e`         | matches `e` without making progress                        |
//!     | `!e`         | matches if `e` doesn't match without making progress       |
//!     | `push(e)`    | matches `e` and pushes it's captured string down the stack |
//!
//!     where `e`, `e1`, and `e2` are expressions.
//!
//! ## Special rules
//!
//! Special rules can be called within the grammar. They are:
//!
//! * `whitespace` - gets run between rules and sub-rules
//! * `comment` - gets run between rules and sub-rules
//! * `any` - matches exactly one `char`
//! * `soi` - (start-of-input) matches only when a `Parser` is still at the starting position
//! * `eoi` - (end-of-input) matches only when a `Parser` has reached its end
//! * `pop` - pops a string from the stack and matches it
//! * `peek` - peeks a string from the stack and matches it
//!
//! `whitespace` and `comment` should be defined manually if needed. All other rules cannot be
//! overridden.

#![doc(html_root_url = "https://docs.rs/pest_derive")]
#![recursion_limit="256"]

#[macro_use]
extern crate pest;
extern crate proc_macro;
#[macro_use]
extern crate quote;
extern crate syn;

use std::env;
use std::path::Path;
use std::rc::Rc;

use pest::inputs::FileInput;
use pest::Parser;
use proc_macro::TokenStream;
use quote::Ident;
use syn::{Attribute, Lit, MetaItem};

mod ast;
mod generator;
mod optimizer;
mod parser;
mod validator;

use parser::{GrammarParser, GrammarRule};

#[proc_macro_derive(Parser, attributes(grammar))]
pub fn derive_parser(input: TokenStream) -> TokenStream {
    let source = input.to_string();

    let (name, path) = parse_derive(source);

    let root = env::var("CARGO_MANIFEST_DIR").unwrap_or(".".into());
    let path = Path::new(&root).join("src/").join(&path);
    let file_name = match path.file_name() {
        Some(file_name) => file_name,
        None => panic!("grammar attribute should point to a file")
    };

    let input = match FileInput::new(&path) {
        Ok(input) => Rc::new(input),
        Err(error) => panic!("error opening {:?}: {}", file_name, error)
    };
    let pairs = match GrammarParser::parse(GrammarRule::grammar_rules, input) {
        Ok(pairs) => pairs,
        Err(error) => panic!("error parsing {:?}\n\n{}", file_name, error.renamed_rules(|rule| {
            match *rule {
                GrammarRule::eoi => "end-of-input".to_owned(),
                GrammarRule::assignment_operator => "`=`".to_owned(),
                GrammarRule::silent_modifier => "`_`".to_owned(),
                GrammarRule::atomic_modifier => "`@`".to_owned(),
                GrammarRule::compound_atomic_modifier => "`$`".to_owned(),
                GrammarRule::non_atomic_modifier => "`!`".to_owned(),
                GrammarRule::opening_brace => "`{`".to_owned(),
                GrammarRule::closing_brace => "`}`".to_owned(),
                GrammarRule::opening_paren => "`(`".to_owned(),
                GrammarRule::positive_predicate_operator => "`&`".to_owned(),
                GrammarRule::negative_predicate_operator => "`!`".to_owned(),
                GrammarRule::sequence_operator => "`&`".to_owned(),
                GrammarRule::choice_operator => "`|`".to_owned(),
                GrammarRule::optional_operator => "`?`".to_owned(),
                GrammarRule::repeat_operator => "`*`".to_owned(),
                GrammarRule::repeat_once_operator => "`+`".to_owned(),
                GrammarRule::closing_paren => "`)`".to_owned(),
                GrammarRule::quote => "`\"`".to_owned(),
                GrammarRule::insensitive_string => "`^`".to_owned(),
                GrammarRule::range_operator => "`..`".to_owned(),
                GrammarRule::single_quote => "`'`".to_owned(),
                other_rule => format!("{:?}", other_rule)
            }
        }))
    };

    let (ast, defaults) = parser::consume_rules(pairs);
    let optimized = optimizer::optimize(ast);
    let generated = generator::generate(name, optimized, defaults);

    generated.as_ref().parse().unwrap()
}

fn parse_derive(source: String) -> (Ident, String) {
    let ast = syn::parse_macro_input(&source).unwrap();
    let name = Ident::new(ast.ident.as_ref());

    let grammar: Vec<_> = ast.attrs.iter().filter(|attr| {
        match attr.value {
            MetaItem::NameValue(ref ident, _) => format!("{}", ident) == "grammar",
            _ => false
        }
    }).collect();

    let filename = match grammar.len() {
        0 => panic!("a grammar file needs to be provided with the #[grammar(\"...\")] attribute"),
        1 => get_filename(grammar[0]),
        _ => panic!("only 1 grammar file can be provided")
    };

    (name, filename)
}

fn get_filename(attr: &Attribute) -> String {
    if let MetaItem::NameValue(_, ref lit) = attr.value {
        if let &Lit::Str(ref string, _) = lit {
            string.clone()
        } else {
            panic!("grammar attribute must be a string")
        }
    } else {
        unreachable!();
    }
}

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

    #[test]
    fn derive_ok() {
        let (_, filename) = parse_derive("
            #[other_attr]
            #[grammar = \"myfile.pest\"]
            pub struct MyParser<'a, T>;
        ".to_owned());

        assert_eq!(filename, "myfile.pest");
    }

    #[test]
    #[should_panic(expected = "only 1 grammar file can be provided")]
    fn derive_multiple_grammars() {
        parse_derive("
            #[other_attr]
            #[grammar = \"myfile1.pest\"]
            #[grammar = \"myfile2.pest\"]
            pub struct MyParser<'a, T>;
        ".to_owned());
    }

    #[test]
    #[should_panic(expected = "grammar attribute must be a string")]
    fn derive_wrong_arg() {
        parse_derive("
            #[other_attr]
            #[grammar = 1]
            pub struct MyParser<'a, T>;
        ".to_owned());
    }
}
<commit_msg>Added Rule documentation.<commit_after>// pest. The Elegant Parser
// Copyright (C) 2017  Dragoș Tiselice
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

//! # pest. The Elegant Parser
//!
//! pest is a [PEG](https://en.wikipedia.org/wiki/Parsing_expression_grammar) parser built with
//! *simplicity* and *speed* in mind.
//!
//! This crate works in conjunction with the [`pest` crate](https://docs.rs/pest) by
//! deriving a grammar implementation based on a provided grammar.
//!
//! ## `.pest` files
//!
//! Grammar definitions reside in custom `.pest` files located in the `src` directory. Their path is
//! relative to `src` and is specified between the `derive` attribute and empty `struct` that
//! `Parser` will be derived on.
//!
//! Because of a limitation in procedural macros, there is no way for Cargo to know that a module
//! needs to be recompiled based on the file that the procedural macro is opening. This leads to the
//! case where modifying a `.pest` file without touching the file where the `derive` is does not
//! recompile it if it already has a working binary in the cache. To avoid this issue, the grammar
//! file can be included in a dummy `const` definition while debugging.
//!
//! ```ignore
//! const _GRAMMAR: &'static = include_str!("path/to/my_grammar.pest"); // relative to this file
//!
//! #[derive(Parser)]
//! #[grammar = "path/to/my_grammar.pest"] // relative to src
//! struct MyParser;
//! ```
//!
//! ## Grammar
//!
//! A grammar is a series of rules separated by whitespace, possibly containing comments.
//!
//! ### Comments
//!
//! Comments start with `//` and end at the end of the line.
//!
//! ```text
//! // a comment
//! ```
//!
//! ### Rules
//!
//! Rules have the following form:
//!
//! ```text
//! name = optional_modifier { expression }
//! ```
//!
//! The name of the rule is formed from alphanumeric characters or `_` with the condition that the
//! first character is not a digit and is used to create token pairs. When the rule starts being
//! parsed, the starting part of the token is being produced, with the ending part being produced
//! when the rule finishes parsing.
//!
//! The following token pair notation `a(b(), c())` denotes the tokens: start `a`, start `b`, end
//! `b`, start `c`, end `c`, end `a`.
//!
//! #### Modifiers
//!
//! Modifiers are optional and can be one of `_`, `@`, `$`, or `!`. These modifiers change the
//! behavior of the rules.
//!
//! 1. Silent (`_`)
//!
//!     Silent rules do not create token pairs during parsing, nor are they error-reported.
//!
//!     ```text
//!     a = _{ "a" }
//!     b =  { a ~ "b" }
//!     ```
//!
//!     Parsing `"ab"` produces the token pair `b()`.
//!
//! 2. Atomic (`@`)
//!
//!     Atomic rules do not accept whitespace or comments between within their expressions and have a
//!     cascading effect on any rule they call. I.e. rules that are not atomic but are called by atomic
//!     rules behave atomically.
//!
//!     Any rules called by atomic rules do not generate token pairs.
//!
//!     ```text
//!     a =  { "a" }
//!     b = @{ a ~ "b" }
//!
//!     whitespace = _{ " " }
//!     ```
//!
//!     Parsing `"ab"` produces the token pair `b()`, while `"a   b"` produces an error.
//!
//! 3. Compound-atomic (`$`)
//!
//!     Compound-atomic are identical to atomic rules with the exception that rules called by them are
//!     not forbidden from generating token pairs.
//!
//!     ```text
//!     a =  { "a" }
//!     b = ${ a ~ "b" }
//!
//!     whitespace = _{ " " }
//!     ```
//!
//!     Parsing `"ab"` produces the token pairs `b(a())`, while `"a   b"` produces an error.
//!
//! 4. Non-atomic (`!`)
//!
//!     Non-atomic are identical to normal rules with the exception that they stop the cascading effect
//!     of atomic and compound-atomic rules.
//!
//!     ```text
//!     a =  { "a" }
//!     b = !{ a ~ "b" }
//!     c = @{ b }
//!
//!     whitespace = _{ " " }
//!     ```
//!
//!     Parsing both `"ab"` and `"a   b"` produce the token pairs `c(b(a()))`.
//!
//! #### Expressions
//!
//! Expressions can be either terminals or non-terminals.
//!
//! 1. Terminals
//!
//!     | Terminal   | Usage                                                          |
//!     |------------|----------------------------------------------------------------|
//!     | `"a"`      | matches the exact string `"a"`                                 |
//!     | `^"a"`     | matches the exact string `"a"` case insensitively (ASCII only) |
//!     | `'a'..'z'` | matches one character between `'a'` and `'z'`                  |
//!     | `a`        | matches rule `a`                                               |
//!
//! 2. Non-terminals
//!
//!     | Non-terminal | Usage                                                      |
//!     |--------------|------------------------------------------------------------|
//!     | `(e)`        | matches `e`                                                |
//!     | `e1 ~ e2`    | matches the sequence `e1` `e2`                             |
//!     | `e1 | e2`    | matches either `e1` or `e1`                                |
//!     | `e*`         | matches `e` zero or more times                             |
//!     | `e+`         | matches `e` one or more times                              |
//!     | `e?`         | optionally matches `e`                                     |
//!     | `&e`         | matches `e` without making progress                        |
//!     | `!e`         | matches if `e` doesn't match without making progress       |
//!     | `push(e)`    | matches `e` and pushes it's captured string down the stack |
//!
//!     where `e`, `e1`, and `e2` are expressions.
//!
//! ## Special rules
//!
//! Special rules can be called within the grammar. They are:
//!
//! * `whitespace` - gets run between rules and sub-rules
//! * `comment` - gets run between rules and sub-rules
//! * `any` - matches exactly one `char`
//! * `soi` - (start-of-input) matches only when a `Parser` is still at the starting position
//! * `eoi` - (end-of-input) matches only when a `Parser` has reached its end
//! * `pop` - pops a string from the stack and matches it
//! * `peek` - peeks a string from the stack and matches it
//!
//! `whitespace` and `comment` should be defined manually if needed. All other rules cannot be
//! overridden.
//!
//! ## `Rule`
//!
//! All rules defined or used in the grammar populate a generated `enum` called `Rule`. This
//! implements `pest`'s `RuleType` and can be used throughout the API.

#![doc(html_root_url = "https://docs.rs/pest_derive")]
#![recursion_limit="256"]

#[macro_use]
extern crate pest;
extern crate proc_macro;
#[macro_use]
extern crate quote;
extern crate syn;

use std::env;
use std::path::Path;
use std::rc::Rc;

use pest::inputs::FileInput;
use pest::Parser;
use proc_macro::TokenStream;
use quote::Ident;
use syn::{Attribute, Lit, MetaItem};

mod ast;
mod generator;
mod optimizer;
mod parser;
mod validator;

use parser::{GrammarParser, GrammarRule};

#[proc_macro_derive(Parser, attributes(grammar))]
pub fn derive_parser(input: TokenStream) -> TokenStream {
    let source = input.to_string();

    let (name, path) = parse_derive(source);

    let root = env::var("CARGO_MANIFEST_DIR").unwrap_or(".".into());
    let path = Path::new(&root).join("src/").join(&path);
    let file_name = match path.file_name() {
        Some(file_name) => file_name,
        None => panic!("grammar attribute should point to a file")
    };

    let input = match FileInput::new(&path) {
        Ok(input) => Rc::new(input),
        Err(error) => panic!("error opening {:?}: {}", file_name, error)
    };
    let pairs = match GrammarParser::parse(GrammarRule::grammar_rules, input) {
        Ok(pairs) => pairs,
        Err(error) => panic!("error parsing {:?}\n\n{}", file_name, error.renamed_rules(|rule| {
            match *rule {
                GrammarRule::eoi => "end-of-input".to_owned(),
                GrammarRule::assignment_operator => "`=`".to_owned(),
                GrammarRule::silent_modifier => "`_`".to_owned(),
                GrammarRule::atomic_modifier => "`@`".to_owned(),
                GrammarRule::compound_atomic_modifier => "`$`".to_owned(),
                GrammarRule::non_atomic_modifier => "`!`".to_owned(),
                GrammarRule::opening_brace => "`{`".to_owned(),
                GrammarRule::closing_brace => "`}`".to_owned(),
                GrammarRule::opening_paren => "`(`".to_owned(),
                GrammarRule::positive_predicate_operator => "`&`".to_owned(),
                GrammarRule::negative_predicate_operator => "`!`".to_owned(),
                GrammarRule::sequence_operator => "`&`".to_owned(),
                GrammarRule::choice_operator => "`|`".to_owned(),
                GrammarRule::optional_operator => "`?`".to_owned(),
                GrammarRule::repeat_operator => "`*`".to_owned(),
                GrammarRule::repeat_once_operator => "`+`".to_owned(),
                GrammarRule::closing_paren => "`)`".to_owned(),
                GrammarRule::quote => "`\"`".to_owned(),
                GrammarRule::insensitive_string => "`^`".to_owned(),
                GrammarRule::range_operator => "`..`".to_owned(),
                GrammarRule::single_quote => "`'`".to_owned(),
                other_rule => format!("{:?}", other_rule)
            }
        }))
    };

    let (ast, defaults) = parser::consume_rules(pairs);
    let optimized = optimizer::optimize(ast);
    let generated = generator::generate(name, optimized, defaults);

    generated.as_ref().parse().unwrap()
}

fn parse_derive(source: String) -> (Ident, String) {
    let ast = syn::parse_macro_input(&source).unwrap();
    let name = Ident::new(ast.ident.as_ref());

    let grammar: Vec<_> = ast.attrs.iter().filter(|attr| {
        match attr.value {
            MetaItem::NameValue(ref ident, _) => format!("{}", ident) == "grammar",
            _ => false
        }
    }).collect();

    let filename = match grammar.len() {
        0 => panic!("a grammar file needs to be provided with the #[grammar(\"...\")] attribute"),
        1 => get_filename(grammar[0]),
        _ => panic!("only 1 grammar file can be provided")
    };

    (name, filename)
}

fn get_filename(attr: &Attribute) -> String {
    if let MetaItem::NameValue(_, ref lit) = attr.value {
        if let &Lit::Str(ref string, _) = lit {
            string.clone()
        } else {
            panic!("grammar attribute must be a string")
        }
    } else {
        unreachable!();
    }
}

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

    #[test]
    fn derive_ok() {
        let (_, filename) = parse_derive("
            #[other_attr]
            #[grammar = \"myfile.pest\"]
            pub struct MyParser<'a, T>;
        ".to_owned());

        assert_eq!(filename, "myfile.pest");
    }

    #[test]
    #[should_panic(expected = "only 1 grammar file can be provided")]
    fn derive_multiple_grammars() {
        parse_derive("
            #[other_attr]
            #[grammar = \"myfile1.pest\"]
            #[grammar = \"myfile2.pest\"]
            pub struct MyParser<'a, T>;
        ".to_owned());
    }

    #[test]
    #[should_panic(expected = "grammar attribute must be a string")]
    fn derive_wrong_arg() {
        parse_derive("
            #[other_attr]
            #[grammar = 1]
            pub struct MyParser<'a, T>;
        ".to_owned());
    }
}
<|endoftext|>


<commit_before>// Copyright 2014-2016 bluss and ndarray developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use libnum::{Zero, One, Float};
use std::any::Any;
use std::fmt;
use std::ops::{Add, Sub, Mul, Div};
#[cfg(feature="assign_ops")]
use std::ops::{
    AddAssign,
    SubAssign,
    MulAssign,
    DivAssign,
    RemAssign,
};
use ScalarOperand;

/// Elements that support linear algebra operations.
///
/// `Any` for type-based specialization, `Copy` so that they don't need move
/// semantics or destructors, and the rest are numerical traits.
pub trait LinalgScalar :
    Any +
    Copy +
    Zero + One +
    Add<Output=Self> +
    Sub<Output=Self> +
    Mul<Output=Self> +
    Div<Output=Self>
{ }

impl<T> LinalgScalar for T
    where T:
    Any +
    Copy +
    Zero + One +
    Add<Output=T> +
    Sub<Output=T> +
    Mul<Output=T> +
    Div<Output=T>
{ }

/// Floating-point element types `f32` and `f64`.
///
/// Trait `NdFloat` is only implemented for `f32` and `f64` but encompasses as
/// much float-relevant ndarray functionality as possible, including the traits
/// needed for linear algebra (`Any`) and for *right hand side* scalar
/// operations (`ScalarOperand`).
#[cfg(not(feature="assign_ops"))]
pub trait NdFloat :
    Float +
    fmt::Display + fmt::Debug + fmt::LowerExp + fmt::UpperExp +
    ScalarOperand + LinalgScalar
{ }

/// Floating-point element types `f32` and `f64`.
///
/// Trait `NdFloat` is only implemented for `f32` and `f64` but encompasses as
/// much float-relevant ndarray functionality as possible, including the traits
/// needed for linear algebra (`Any`) and for *right hand side* scalar
/// operations (`ScalarOperand`).
///
/// This trait can only be implemented by `f32` and `f64`.
#[cfg(feature="assign_ops")]
pub trait NdFloat :
    Float +
    AddAssign + SubAssign + MulAssign + DivAssign + RemAssign +
    fmt::Display + fmt::Debug + fmt::LowerExp + fmt::UpperExp +
    ScalarOperand + LinalgScalar
{ }

impl NdFloat for f32 { }
impl NdFloat for f64 { }
<commit_msg>Add Send + Sync to NdFloat<commit_after>// Copyright 2014-2016 bluss and ndarray developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use libnum::{Zero, One, Float};
use std::any::Any;
use std::fmt;
use std::ops::{Add, Sub, Mul, Div};
#[cfg(feature="assign_ops")]
use std::ops::{
    AddAssign,
    SubAssign,
    MulAssign,
    DivAssign,
    RemAssign,
};
use ScalarOperand;

/// Elements that support linear algebra operations.
///
/// `Any` for type-based specialization, `Copy` so that they don't need move
/// semantics or destructors, and the rest are numerical traits.
pub trait LinalgScalar :
    Any +
    Copy +
    Zero + One +
    Add<Output=Self> +
    Sub<Output=Self> +
    Mul<Output=Self> +
    Div<Output=Self>
{ }

impl<T> LinalgScalar for T
    where T:
    Any +
    Copy +
    Zero + One +
    Add<Output=T> +
    Sub<Output=T> +
    Mul<Output=T> +
    Div<Output=T>
{ }

/// Floating-point element types `f32` and `f64`.
///
/// Trait `NdFloat` is only implemented for `f32` and `f64` but encompasses as
/// much float-relevant ndarray functionality as possible, including the traits
/// needed for linear algebra (`Any`) and for *right hand side* scalar
/// operations (`ScalarOperand`).
#[cfg(not(feature="assign_ops"))]
pub trait NdFloat :
    Float +
    fmt::Display + fmt::Debug + fmt::LowerExp + fmt::UpperExp +
    ScalarOperand + LinalgScalar + Send + Sync
{ }

/// Floating-point element types `f32` and `f64`.
///
/// Trait `NdFloat` is only implemented for `f32` and `f64` but encompasses as
/// much float-relevant ndarray functionality as possible, including the traits
/// needed for linear algebra (`Any`) and for *right hand side* scalar
/// operations (`ScalarOperand`).
///
/// This trait can only be implemented by `f32` and `f64`.
#[cfg(feature="assign_ops")]
pub trait NdFloat :
    Float +
    AddAssign + SubAssign + MulAssign + DivAssign + RemAssign +
    fmt::Display + fmt::Debug + fmt::LowerExp + fmt::UpperExp +
    ScalarOperand + LinalgScalar + Send + Sync
{ }

impl NdFloat for f32 { }
impl NdFloat for f64 { }
<|endoftext|>


<commit_before>use log;
use log::{LogRecord, LogLevel, LogMetadata, LogLevelFilter};
use arch::drivers::serial;

use core::fmt::Write;

struct SerialLogger;

pub fn initialize() -> Result<(), log::SetLoggerError> {
    unsafe {
        log::set_logger_raw(|max_log_level| {
            static LOGGER: SerialLogger = SerialLogger;
            max_log_level.set(LogLevelFilter::Trace);
            &SerialLogger
        })
    }
}
pub fn shutdown() -> Result<(), log::ShutdownLoggerError> {
    log::shutdown_logger_raw().map(|logger| {
        let logger = unsafe { &*(logger as *const SerialLogger) };
        // logger.flush();
    })
}

#[cfg(debug_assertions)]
impl log::Log for SerialLogger {

    #[inline] fn enabled(&self, metadata: &LogMetadata) -> bool {
        true // TODO: for now?
    }

    #[inline]
    fn log(&self, record: &LogRecord) {
        let meta = record.metadata();
        match record.level() {
            LogLevel::Trace if self.enabled(meta) => {
                let location = record.location();
                write!( *serial::COM1.lock()
                      , "[ TRACE ][ {} ][ {}:{} ] {}\n"
                      , meta.target()
                      , location.module_path(), location.line()
                      , record.args() );
            }
          , LogLevel::Debug if self.enabled(meta) => {
                write!( *serial::COM1.lock()
                      , "[ TRACE ] {}: {}\n"
                      , meta.target()
                      , record.args() );
            }
          , level => {
                let target = meta.target();
                let args = record.args();
                write!( *serial::COM1.lock()
                      , "[ {} ] {}: {}\n"
                      , level, target, args );
                // println!("{}: {}", target, args );
            }
        }
    }

}

#[cfg(not(debug_assertions))]
impl log::Log for SerialLogger {

    #[inline] fn enabled(&self, metadata: &LogMetadata) -> bool {
        false // TODO: for now
    }

    #[inline]
    fn log(&self, record: &LogRecord) {
        let meta = record.metadata();
        if self.enabled(meta) {
            println!("{}: {}", target, args );
            // TODO: should we log for com1 also?
        }
    }

}
<commit_msg>[kernel] fix more serial log formatting<commit_after>use log;
use log::{LogRecord, LogLevel, LogMetadata, LogLevelFilter};
use arch::drivers::serial;

use core::fmt::Write;

struct SerialLogger;

pub fn initialize() -> Result<(), log::SetLoggerError> {
    unsafe {
        log::set_logger_raw(|max_log_level| {
            static LOGGER: SerialLogger = SerialLogger;
            max_log_level.set(LogLevelFilter::Trace);
            &SerialLogger
        })
    }
}
pub fn shutdown() -> Result<(), log::ShutdownLoggerError> {
    log::shutdown_logger_raw().map(|logger| {
        let logger = unsafe { &*(logger as *const SerialLogger) };
        // logger.flush();
    })
}

#[cfg(debug_assertions)]
impl log::Log for SerialLogger {

    #[inline] fn enabled(&self, metadata: &LogMetadata) -> bool {
        true // TODO: for now?
    }

    #[inline]
    fn log(&self, record: &LogRecord) {
        let meta = record.metadata();
        match record.level() {
            LogLevel::Trace if self.enabled(meta) => {
                let location = record.location();
                write!( *serial::COM1.lock()
                      , "[ TRACE ][ {}:{} ] {}: {}\n"
                      , location.module_path(), location.line()

                      , meta.target()
                      , record.args() );
            }
          , LogLevel::Debug if self.enabled(meta) => {
                write!( *serial::COM1.lock()
                      , "[ DEBUG ] {}: {}\n"
                      , meta.target()
                      , record.args() );
            }
          , level => {
                let target = meta.target();
                let args = record.args();
                write!( *serial::COM1.lock()
                      , "[ {} ] {}: {}\n"
                      , level, target, args );
                // println!("{}: {}", target, args );
            }
        }
    }

}

#[cfg(not(debug_assertions))]
impl log::Log for SerialLogger {

    #[inline] fn enabled(&self, metadata: &LogMetadata) -> bool {
        false // TODO: for now
    }

    #[inline]
    fn log(&self, record: &LogRecord) {
        let meta = record.metadata();
        if self.enabled(meta) {
            println!("{}: {}", target, args );
            // TODO: should we log for com1 also?
        }
    }

}
<|endoftext|>


<commit_before>#[macro_export]
macro_rules! table {
    (
        $name:ident {
            $($column_name:ident -> $Type:ty,)+
        }
    ) => {
        table! {
            $name (id) {
                $($column_name -> $Type,)+
            }
        }
    };
    (
        $name:ident ($pk:ident) {
            $($column_name:ident -> $Type:ty,)+
        }
    ) => {
        pub mod $name {
            use $crate::*;
            use $crate::query_builder::*;
            use $crate::types::*;
            pub use self::columns::*;

            pub mod dsl {
                pub use super::columns::{$($column_name),+};
                pub use super::table as $name;
            }

            #[allow(non_upper_case_globals, dead_code)]
            pub const all_columns: ($($column_name),+) = ($($column_name),+);

            #[allow(non_camel_case_types)]
            #[derive(Clone, Copy)]
            pub struct table;

            impl table {
                #[allow(dead_code)]
                pub fn star(&self) -> star {
                    star
                }
            }

            pub type SqlType = ($($Type),+);

            impl QuerySource for table {
                fn from_clause(&self, out: &mut QueryBuilder) -> BuildQueryResult {
                    out.push_identifier(stringify!($name))
                }
            }

            impl AsQuery for table {
                type SqlType = SqlType;
                type Query = SelectStatement<SqlType, ($($column_name),+), Self>;

                fn as_query(self) -> Self::Query {
                    SelectStatement::simple(all_columns, self)
                }
            }

            impl Table for table {
                type PrimaryKey = columns::$pk;
                type AllColumns = ($($column_name),+);

                fn name() -> &'static str {
                    stringify!($name)
                }

                fn primary_key(&self) -> Self::PrimaryKey {
                    columns::$pk
                }

                fn all_columns() -> Self::AllColumns {
                    ($($column_name),+)
                }
            }

            pub mod columns {
                use super::table;
                use $crate::{Table, Column, Expression, SelectableExpression};
                use $crate::expression::NonAggregate;
                use $crate::query_builder::{QueryBuilder, BuildQueryResult};
                use $crate::types::*;

                #[allow(non_camel_case_types, dead_code)]
                #[derive(Debug, Clone, Copy)]
                pub struct star;

                impl Expression for star {
                    type SqlType = ();

                    fn to_sql(&self, out: &mut QueryBuilder) -> BuildQueryResult {
                        try!(out.push_identifier(table::name()));
                        out.push_sql(".*");
                        Ok(())
                    }
                }

                impl SelectableExpression<table> for star {}

                $(#[allow(non_camel_case_types, dead_code)]
                #[derive(Debug, Clone, Copy)]
                pub struct $column_name;

                impl Expression for $column_name {
                    type SqlType = $Type;

                    fn to_sql(&self, out: &mut QueryBuilder) -> BuildQueryResult {
                        try!(out.push_identifier(table::name()));
                        out.push_sql(".");
                        out.push_identifier(stringify!($column_name))
                    }
                }

                impl SelectableExpression<table> for $column_name {}

                impl NonAggregate for $column_name {}

                impl Column for $column_name {
                    type Table = table;

                    fn name() -> &'static str {
                        stringify!($column_name)
                    }
                }
                )+
            }
        }
    }
}

#[macro_export]
macro_rules! queriable {
    (
        $Struct:ident {
            $($field_name:ident -> $Type:ty,)+
        }
    ) => {
        impl<ST> $crate::Queriable<ST> for $Struct where
            ST: $crate::types::NativeSqlType,
            ($($Type),+): $crate::types::FromSqlRow<ST>,
        {
            type Row = ($($Type),+);

            fn build(row: Self::Row) -> Self {
                let ($($field_name),+) = row;
                $Struct {
                    $($field_name: $field_name),+
                }
            }
        }
    }
}

#[macro_export]
macro_rules! insertable {
    (
        $Struct:ty => $table_mod:ident {
            $($field_name:ident -> $Type:ty,)+
        }
    ) => {
        insertable! {
            $Struct => $table_mod {
                $($table_mod, $field_name -> $Type,)+
            }
        }
    };
    (
        $Struct:ty => $table_mod:ident {
            $($field_table_name:ident, $field_name:ident -> $Type:ty,)+
        }
    ) => {
        impl<'a: 'insert, 'insert> $crate::persistable::Insertable<$table_mod::table>
            for &'insert $Struct
        {
            type Columns = ($($table_mod::$field_name),+);
            type Values = $crate::expression::grouped::Grouped<($(
                $crate::expression::helper_types::AsExpr<&'insert $Type, $table_mod::$field_name>
            ),+)>;

            fn columns() -> Self::Columns {
                ($($table_mod::$field_name),+)
            }

            fn values(self) -> Self::Values {
                use $crate::expression::AsExpression;
                use $crate::expression::grouped::Grouped;
                Grouped(($(AsExpression::<
                   <$table_mod::$field_name as $crate::expression::Expression>::SqlType>
                   ::as_expression(&self.$field_name)
               ),+))
            }
        }
    };
}

#[macro_export]
macro_rules! changeset {
    (
        $Struct:ty => $table_mod:ident {
            $($field_name:ident -> $Type:ty,)+
        }
    ) => {
        impl<'a: 'update, 'update> $crate::query_builder::AsChangeset
            for &'update $Struct
        {
            type Changeset = ($(
                $crate::expression::predicates::Eq<
                    $table_mod::$field_name,
                    $crate::expression::bound::Bound<
                        <$table_mod::$field_name as $crate::expression::Expression>::SqlType,
                        &'update $Type,
                    >,
                >
            ),+);

            fn as_changeset(self) -> Self::Changeset {
                use $crate::expression::Expression;

                ($(
                    $table_mod::$field_name.eq(&self.$field_name)
                ),+)
            }
        }
    };
}

#[macro_export]
macro_rules! joinable {
    ($child:ident -> $parent:ident ($source:ident = $target:ident)) => {
        joinable_inner!($child -> $parent ($source = $target));
        joinable_inner!($parent -> $child ($target = $source));
    }
}

#[macro_export]
macro_rules! joinable_inner {
    ($child:ident -> $parent:ident ($source:ident = $target:ident)) => {
        impl $crate::JoinTo<$parent::table> for $child::table {
            type Predicate = $crate::expression::predicates::Eq<$child::$source, $parent::$target>;

            fn join_expression(&self) -> Self::Predicate {
                use $crate::Expression;
                $child::$source.eq($parent::$target)
            }
        }
    }
}

#[macro_export]
macro_rules! select_column_workaround {
    ($parent:ident -> $child:ident ($($column_name:ident),+)) => {
        $(select_column_inner!($parent -> $child $column_name);)+
        select_column_inner!($parent -> $child star);
    }
}

#[macro_export]
macro_rules! one_to_many {
    (
        $parent_table:ident ($parent_struct:ty) ->
        $child_table:ident ($child_struct:ty) on
        ($foreign_key:ident = $primary_key:ident)
    ) => {
        one_to_many!($child_table: $parent_table ($parent_struct) ->
                     $child_table ($child_struct) on ($foreign_key = $primary_key));
    };
    (
        $association_name:ident -> $association_type:ident :
        $parent_table:ident ($parent_struct:ty) ->
        $child_table:ident ($child_struct:ty) on
        ($foreign_key:ident = $primary_key:ident)
    ) => {
        pub type $association_type = $crate::helper_types::FindBy<
            $child_table::table,
            $child_table::$foreign_key,
            i32,
        >;
        one_to_many!($association_name: $parent_table ($parent_struct) ->
                     $child_table ($child_struct) on ($foreign_key = $primary_key));
    };
    (
        $association_name:ident :
        $parent_table:ident ($parent_struct:ty) ->
        $child_table:ident ($child_struct:ty) on
        ($foreign_key:ident = $primary_key:ident)
    ) => {
        impl $parent_struct {
            pub fn $association_name(&self) -> $crate::helper_types::FindBy<
                $child_table::table,
                $child_table::$foreign_key,
                i32,
            > {
                $child_table::table.filter($child_table::$foreign_key.eq(self.$primary_key))
            }
        }

        joinable!($child_table -> $parent_table ($foreign_key = $primary_key));
    };
}

#[macro_export]
macro_rules! select_column_inner {
    ($parent:ident -> $child:ident $column_name:ident) => {
        impl $crate::expression::SelectableExpression<
            $crate::query_source::InnerJoinSource<$child::table, $parent::table>,
        > for $parent::$column_name
        {
        }

        impl $crate::expression::SelectableExpression<
            $crate::query_source::InnerJoinSource<$parent::table, $child::table>,
        > for $parent::$column_name
        {
        }

        impl $crate::expression::SelectableExpression<
            $crate::query_source::LeftOuterJoinSource<$child::table, $parent::table>,
            $crate::types::Nullable<
                <$parent::$column_name as $crate::Expression>::SqlType>,
        > for $parent::$column_name
        {
        }

        impl $crate::expression::SelectableExpression<
            $crate::query_source::LeftOuterJoinSource<$parent::table, $child::table>,
        > for $parent::$column_name
        {
        }
    }
}
<commit_msg>Add the ability to have columns which aren't selected by default<commit_after>#[macro_export]
macro_rules! column {
    ($($table:ident)::*, $column_name:ident -> $Type:ty) => {
        #[allow(non_camel_case_types, dead_code)]
        #[derive(Debug, Clone, Copy)]
        pub struct $column_name;

        impl $crate::expression::Expression for $column_name {
            type SqlType = $Type;

            fn to_sql(&self, out: &mut $crate::query_builder::QueryBuilder) -> $crate::query_builder::BuildQueryResult {
                try!(out.push_identifier($($table)::*::name()));
                out.push_sql(".");
                out.push_identifier(stringify!($column_name))
            }
        }

        impl $crate::expression::SelectableExpression<$($table)::*> for $column_name {}

        impl $crate::expression::NonAggregate for $column_name {}

        impl $crate::query_source::Column for $column_name {
            type Table = $($table)::*;

            fn name() -> &'static str {
                stringify!($column_name)
            }
        }
    }
}

#[macro_export]
macro_rules! table {
    (
        $name:ident {
            $($column_name:ident -> $Type:ty,)+
        }
    ) => {
        table! {
            $name (id) {
                $($column_name -> $Type,)+
            }
        }
    };
    (
        $name:ident ($pk:ident) {
            $($column_name:ident -> $Type:ty,)+
        }
    ) => {
        table! {
            $name ($pk) {
                $($column_name -> $Type,)+
            } no select {}
        }
    };
    (
        $name:ident {
            $($column_name:ident -> $Type:ty,)+
        } no select {
            $($no_select_column_name:ident -> $no_select_type:ty,)*
        }
    ) => {
        table! {
            $name (id) {
                $($column_name -> $Type,)+
            } no select {
                $($no_select_column_name -> $no_select_type,)*
            }
        }
    };
    (
        $name:ident ($pk:ident) {
            $($column_name:ident -> $Type:ty,)+
        } no select {
            $($no_select_column_name:ident -> $no_select_type:ty,)*
        }
    ) => {
        pub mod $name {
            use $crate::*;
            use $crate::query_builder::*;
            use $crate::types::*;
            pub use self::columns::*;

            pub mod dsl {
                pub use super::columns::{$($column_name),+};
                pub use super::table as $name;
            }

            #[allow(non_upper_case_globals, dead_code)]
            pub const all_columns: ($($column_name),+) = ($($column_name),+);

            #[allow(non_camel_case_types)]
            #[derive(Clone, Copy)]
            pub struct table;

            impl table {
                #[allow(dead_code)]
                pub fn star(&self) -> star {
                    star
                }
            }

            pub type SqlType = ($($Type),+);

            impl QuerySource for table {
                fn from_clause(&self, out: &mut QueryBuilder) -> BuildQueryResult {
                    out.push_identifier(stringify!($name))
                }
            }

            impl AsQuery for table {
                type SqlType = SqlType;
                type Query = SelectStatement<SqlType, ($($column_name),+), Self>;

                fn as_query(self) -> Self::Query {
                    SelectStatement::simple(all_columns, self)
                }
            }

            impl Table for table {
                type PrimaryKey = columns::$pk;
                type AllColumns = ($($column_name),+);

                fn name() -> &'static str {
                    stringify!($name)
                }

                fn primary_key(&self) -> Self::PrimaryKey {
                    columns::$pk
                }

                fn all_columns() -> Self::AllColumns {
                    ($($column_name),+)
                }
            }

            pub mod columns {
                use super::table;
                use $crate::{Table, Column, Expression, SelectableExpression};
                use $crate::query_builder::{QueryBuilder, BuildQueryResult};
                use $crate::types::*;

                #[allow(non_camel_case_types, dead_code)]
                #[derive(Debug, Clone, Copy)]
                pub struct star;

                impl Expression for star {
                    type SqlType = ();

                    fn to_sql(&self, out: &mut QueryBuilder) -> BuildQueryResult {
                        try!(out.push_identifier(table::name()));
                        out.push_sql(".*");
                        Ok(())
                    }
                }

                impl SelectableExpression<table> for star {}

                $(column!(table, $column_name -> $Type);)+
                $(column!(table, $no_select_column_name -> $no_select_type);)*
            }
        }
    }
}

#[macro_export]
macro_rules! queriable {
    (
        $Struct:ident {
            $($field_name:ident -> $Type:ty,)+
        }
    ) => {
        impl<ST> $crate::Queriable<ST> for $Struct where
            ST: $crate::types::NativeSqlType,
            ($($Type),+): $crate::types::FromSqlRow<ST>,
        {
            type Row = ($($Type),+);

            fn build(row: Self::Row) -> Self {
                let ($($field_name),+) = row;
                $Struct {
                    $($field_name: $field_name),+
                }
            }
        }
    }
}

#[macro_export]
macro_rules! insertable {
    (
        $Struct:ty => $table_mod:ident {
            $($field_name:ident -> $Type:ty,)+
        }
    ) => {
        insertable! {
            $Struct => $table_mod {
                $($table_mod, $field_name -> $Type,)+
            }
        }
    };
    (
        $Struct:ty => $table_mod:ident {
            $($field_table_name:ident, $field_name:ident -> $Type:ty,)+
        }
    ) => {
        impl<'a: 'insert, 'insert> $crate::persistable::Insertable<$table_mod::table>
            for &'insert $Struct
        {
            type Columns = ($($table_mod::$field_name),+);
            type Values = $crate::expression::grouped::Grouped<($(
                $crate::expression::helper_types::AsExpr<&'insert $Type, $table_mod::$field_name>
            ),+)>;

            fn columns() -> Self::Columns {
                ($($table_mod::$field_name),+)
            }

            fn values(self) -> Self::Values {
                use $crate::expression::AsExpression;
                use $crate::expression::grouped::Grouped;
                Grouped(($(AsExpression::<
                   <$table_mod::$field_name as $crate::expression::Expression>::SqlType>
                   ::as_expression(&self.$field_name)
               ),+))
            }
        }
    };
}

#[macro_export]
macro_rules! changeset {
    (
        $Struct:ty => $table_mod:ident {
            $($field_name:ident -> $Type:ty,)+
        }
    ) => {
        impl<'a: 'update, 'update> $crate::query_builder::AsChangeset
            for &'update $Struct
        {
            type Changeset = ($(
                $crate::expression::predicates::Eq<
                    $table_mod::$field_name,
                    $crate::expression::bound::Bound<
                        <$table_mod::$field_name as $crate::expression::Expression>::SqlType,
                        &'update $Type,
                    >,
                >
            ),+);

            fn as_changeset(self) -> Self::Changeset {
                use $crate::expression::Expression;

                ($(
                    $table_mod::$field_name.eq(&self.$field_name)
                ),+)
            }
        }
    };
}

#[macro_export]
macro_rules! joinable {
    ($child:ident -> $parent:ident ($source:ident = $target:ident)) => {
        joinable_inner!($child -> $parent ($source = $target));
        joinable_inner!($parent -> $child ($target = $source));
    }
}

#[macro_export]
macro_rules! joinable_inner {
    ($child:ident -> $parent:ident ($source:ident = $target:ident)) => {
        impl $crate::JoinTo<$parent::table> for $child::table {
            type Predicate = $crate::expression::predicates::Eq<$child::$source, $parent::$target>;

            fn join_expression(&self) -> Self::Predicate {
                use $crate::Expression;
                $child::$source.eq($parent::$target)
            }
        }
    }
}

#[macro_export]
macro_rules! select_column_workaround {
    ($parent:ident -> $child:ident ($($column_name:ident),+)) => {
        $(select_column_inner!($parent -> $child $column_name);)+
        select_column_inner!($parent -> $child star);
    }
}

#[macro_export]
macro_rules! one_to_many {
    (
        $parent_table:ident ($parent_struct:ty) ->
        $child_table:ident ($child_struct:ty) on
        ($foreign_key:ident = $primary_key:ident)
    ) => {
        one_to_many!($child_table: $parent_table ($parent_struct) ->
                     $child_table ($child_struct) on ($foreign_key = $primary_key));
    };
    (
        $association_name:ident -> $association_type:ident :
        $parent_table:ident ($parent_struct:ty) ->
        $child_table:ident ($child_struct:ty) on
        ($foreign_key:ident = $primary_key:ident)
    ) => {
        pub type $association_type = $crate::helper_types::FindBy<
            $child_table::table,
            $child_table::$foreign_key,
            i32,
        >;
        one_to_many!($association_name: $parent_table ($parent_struct) ->
                     $child_table ($child_struct) on ($foreign_key = $primary_key));
    };
    (
        $association_name:ident :
        $parent_table:ident ($parent_struct:ty) ->
        $child_table:ident ($child_struct:ty) on
        ($foreign_key:ident = $primary_key:ident)
    ) => {
        impl $parent_struct {
            pub fn $association_name(&self) -> $crate::helper_types::FindBy<
                $child_table::table,
                $child_table::$foreign_key,
                i32,
            > {
                $child_table::table.filter($child_table::$foreign_key.eq(self.$primary_key))
            }
        }

        joinable!($child_table -> $parent_table ($foreign_key = $primary_key));
    };
}

#[macro_export]
macro_rules! select_column_inner {
    ($parent:ident -> $child:ident $column_name:ident) => {
        impl $crate::expression::SelectableExpression<
            $crate::query_source::InnerJoinSource<$child::table, $parent::table>,
        > for $parent::$column_name
        {
        }

        impl $crate::expression::SelectableExpression<
            $crate::query_source::InnerJoinSource<$parent::table, $child::table>,
        > for $parent::$column_name
        {
        }

        impl $crate::expression::SelectableExpression<
            $crate::query_source::LeftOuterJoinSource<$child::table, $parent::table>,
            $crate::types::Nullable<
                <$parent::$column_name as $crate::Expression>::SqlType>,
        > for $parent::$column_name
        {
        }

        impl $crate::expression::SelectableExpression<
            $crate::query_source::LeftOuterJoinSource<$parent::table, $child::table>,
        > for $parent::$column_name
        {
        }
    }
}
<|endoftext|>


<commit_before>///
/// A macro to handle those cases where you want to gracefully
/// deal with a pattern like `Result::Err` or `Option::None`,
/// but cannot use `try!` because your function does not return
/// either of the `Result` or `Option` types.
///
/// The expression provided as the first parameter with be matched
/// against the pattern provided as the second parameter.
/// If the pattern matches, the expression provided as the third
/// parameter will be evaluated and its result returned from the
/// calling function.
///
/// Helps to prevent unnecessary code indentation.
///
#[macro_export]
macro_rules! handle_pattern {
    ( $expression:expr, $pattern:pat, $on_match:expr ) => {{
        let result = $expression;
        if let $pattern = result {
            return $on_match;
        }
        result.unwrap()
    }};
}

///
/// A macro to handle those cases where you want to gracefully
/// deal with a `Result::Err`, but cannot use `try!` because your
/// function does not return the `Result` or `Option` type.
///
/// The expression provided as the first parameter with be matched
/// against the pattern `Err(error)`.
/// If the pattern matches, the closure provided as the second
/// parameter will be called with the expression result.
/// The closure result will then be returned from the calling function.
///
/// Helps to prevent unnecessary code indentation by replacing:
///
/// ```ignore
/// let value = match $expression {
///     Err(error) => {
///         return log!(error);
///     }
///     Ok(value) => value,
/// };
/// ```
///
/// with:
///
/// ```ignore
/// let value = unwrap_or_return!($expression, |error| log!(error));
/// ```
///
#[macro_export]
macro_rules! unwrap_or_return {
    ( $expression:expr, $on_error:expr ) => {{
        let result = $expression;
        if let Err(error) = result {
            return $on_error(error);
        }
        result.unwrap()
    }};
}

///
/// A macro to handle those cases where you want to gracefully
/// deal with an `Option::None`, but cannot use `try!` because
/// your function does not return the `Option` type.
///
/// The expression provided as the first parameter with be matched
/// against the pattern `None`.
/// If the pattern matches, the closure provided as the second
/// parameter will be called with the expression result.
/// The closure result will then be returned from the calling function.
///
/// Helps to prevent unnecessary code indentation.
///
#[macro_export]
macro_rules! handle_none {
    ( $expression:expr, $on_none:expr ) => {{
        let option = $expression;
        if let None = option {
            return $on_none();
        }
        option.unwrap()
    }};
}
<commit_msg>removed handle_pattern! and handle_none!<commit_after>///
/// A macro to handle those cases where you want to gracefully
/// deal with a `Result::Err`, but cannot use `try!` because your
/// function does not return the `Result` or `Option` type.
///
/// The expression provided as the first parameter with be matched
/// against the pattern `Err(error)`.
/// If the pattern matches, the closure provided as the second
/// parameter will be called with the expression result.
/// The closure result will then be returned from the calling function.
///
/// Helps to prevent unnecessary code indentation by replacing:
///
/// ```ignore
/// let value = match $expression {
///     Err(error) => {
///         return log!(error);
///     }
///     Ok(value) => value,
/// };
/// ```
///
/// with:
///
/// ```ignore
/// let value = unwrap_or_return!($expression, |error| log!(error));
/// ```
///
#[macro_export]
macro_rules! unwrap_or_return {
    ( $expression:expr, $on_error:expr ) => {{
        let result = $expression;
        if let Err(error) = result {
            return $on_error(error);
        }
        result.unwrap()
    }};
}
<|endoftext|>


<commit_before>macro_rules! itry {
    ($res:expr) => {
        match $res {
            Done(rest, result) => {
                (rest, result)
            },
            Error(e) => {
                return Error(e)
            },
            Incomplete(needed) => {
                println!("Incomplete at {}, {}", line!(), file!());
                return Incomplete(needed)
            }
        }
    }
}

macro_rules! get_from_header {
    ($bytes:expr, $field:expr, $fun:expr, $t:ty) => {{
        use std::mem::size_of;
        get_from_header!($bytes, $field, $fun, $t, size_of::<$t>())
    }};
    ($bytes:expr, $field:expr, $fun:expr, $t:ty, $size:expr) => {{
        let start = $field.offset as usize;
        let end = ($field.offset + $field.size) as usize;
        let slice = &$bytes[start..end];
        /*
        println!("Number of {}: {} ({}b each) in section {}-{} ({}b)",
            stringify!($t),
            $field.size as usize / $size,
            $size,
            start,
            end,
            slice.len()
        );
        */
        itry!(
            parse_vec::<$t>(
                slice,
                $fun,
                $field.size as usize / $size
            )
        )
    }}
}

macro_rules! take_s {
    ($count:expr) => {{
        |i: &[u8]| take_s!(i, $count)
    }};
    ($i:expr, $count:expr) => {{
        match take!($i, $count) {
            Done(rest, arr) =>
                if let Ok(s) = String::from_utf8(
                    arr.into_iter()
                        .map(|&a| a)
                        .take_while(|&c| c != 0)
                        .collect::<Vec<_>>()
                ) {
                    Done(
                        rest,
                        s
                    )
                } else {
                    use nom::ErrorKind;
                    Error(Err::Code(ErrorKind::Custom(0)))
                },
            Error(e) => {
                Error(e)
            },
            Incomplete(needed) => {
                Incomplete(needed.into())
            }
        }
    }};
}

macro_rules! take_exact {
    ($count:expr) => {{
        |i: &[u8]| take_exact!(i, $count)
    }};
    ($slice:expr, $count:expr) => {{
        let taken = take!($slice, $count);
        match taken {
            Done(rest, result) => {
                let mut array = [0u8; $count];
                for (&x, p) in result.iter().zip(array.iter_mut()) {
                    *p = x;
                }
                Done(rest, array)
            },
            Error(e) => {
                Error(e)
            },
            Incomplete(needed) => {
                Incomplete(needed.into())
            }
        }
    }}
}
<commit_msg>Remove debug<commit_after>macro_rules! itry {
    ($res:expr) => {
        match $res {
            Done(rest, result) => {
                (rest, result)
            },
            Error(e) => {
                return Error(e)
            },
            Incomplete(needed) => {
                return Incomplete(needed)
            }
        }
    }
}

macro_rules! get_from_header {
    ($bytes:expr, $field:expr, $fun:expr, $t:ty) => {{
        use std::mem::size_of;
        get_from_header!($bytes, $field, $fun, $t, size_of::<$t>())
    }};
    ($bytes:expr, $field:expr, $fun:expr, $t:ty, $size:expr) => {{
        let start = $field.offset as usize;
        let end = ($field.offset + $field.size) as usize;
        let slice = &$bytes[start..end];
        itry!(
            parse_vec::<$t>(
                slice,
                $fun,
                $field.size as usize / $size
            )
        )
    }}
}

macro_rules! take_s {
    ($count:expr) => {{
        |i: &[u8]| take_s!(i, $count)
    }};
    ($i:expr, $count:expr) => {{
        match take!($i, $count) {
            Done(rest, arr) =>
                if let Ok(s) = String::from_utf8(
                    arr.into_iter()
                        .map(|&a| a)
                        .take_while(|&c| c != 0)
                        .collect::<Vec<_>>()
                ) {
                    Done(
                        rest,
                        s
                    )
                } else {
                    use nom::ErrorKind;
                    Error(Err::Code(ErrorKind::Custom(0)))
                },
            Error(e) => {
                Error(e)
            },
            Incomplete(needed) => {
                Incomplete(needed.into())
            }
        }
    }};
}

macro_rules! take_exact {
    ($count:expr) => {{
        |i: &[u8]| take_exact!(i, $count)
    }};
    ($slice:expr, $count:expr) => {{
        let taken = take!($slice, $count);
        match taken {
            Done(rest, result) => {
                let mut array = [0u8; $count];
                for (&x, p) in result.iter().zip(array.iter_mut()) {
                    *p = x;
                }
                Done(rest, array)
            },
            Error(e) => {
                Error(e)
            },
            Incomplete(needed) => {
                Incomplete(needed.into())
            }
        }
    }}
}
<|endoftext|>


<commit_before>extern crate glium;

use std::mem::zeroed;
use std::ops::*;
use glium::uniforms::*;

#[derive(PartialEq, Clone, Debug)]
pub struct Matrix { m: [[f32; 4]; 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]],
            ]
        }
    }
}

#[test]
fn create_zero_filled_matrix() {
    let m = Matrix::zero();

    assert_eq!(m.m[0][0], 0.0);
    assert_eq!(m.m[0][1], 0.0);
    assert_eq!(m.m[0][2], 0.0);
    assert_eq!(m.m[0][3], 0.0);
    assert_eq!(m.m[1][0], 0.0);
    assert_eq!(m.m[1][1], 0.0);
    assert_eq!(m.m[1][2], 0.0);
    assert_eq!(m.m[1][3], 0.0);
    assert_eq!(m.m[2][0], 0.0);
    assert_eq!(m.m[2][1], 0.0);
    assert_eq!(m.m[2][2], 0.0);
    assert_eq!(m.m[2][3], 0.0);
    assert_eq!(m.m[3][0], 0.0);
    assert_eq!(m.m[3][1], 0.0);
    assert_eq!(m.m[3][2], 0.0);
    assert_eq!(m.m[3][3], 0.0);
}

#[test]
fn new_matrix() {
    let m = Matrix::new(
        1.0, 2.0, 3.0, 4.0,
        5.0, 6.0, 7.0, 8.0,
        9.0, 10.0, 11.0, 12.0,
        13.0, 14.0, 15.0, 16.0,
    );

    assert_eq!(m.m[0][0], 1.0);
    assert_eq!(m.m[0][1], 2.0);
    assert_eq!(m.m[0][2], 3.0);
    assert_eq!(m.m[0][3], 4.0);
    assert_eq!(m.m[1][0], 5.0);
    assert_eq!(m.m[1][1], 6.0);
    assert_eq!(m.m[1][2], 7.0);
    assert_eq!(m.m[1][3], 8.0);
    assert_eq!(m.m[2][0], 9.0);
    assert_eq!(m.m[2][1], 10.0);
    assert_eq!(m.m[2][2], 11.0);
    assert_eq!(m.m[2][3], 12.0);
    assert_eq!(m.m[3][0], 13.0);
    assert_eq!(m.m[3][1], 14.0);
    assert_eq!(m.m[3][2], 15.0);
    assert_eq!(m.m[3][3], 16.0);
}

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 AsUniformValue for Matrix {
    fn as_uniform_value(&self) -> UniformValue<'static> {
        UniformValue::Mat4(self.m)
    }

    fn matches(ty: &UniformType) -> bool {
        ty == &UniformType::FloatMat4
    }
}

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

#[test]
fn indexing() {
    let matrix = Matrix {
        m: [
            [ 2.0, 3.0, 5.0, 7.0 ],
            [ 11.0, 13.0, 17.0, 19.0 ],
            [ 23.0, 29.0, 31.0, 37.0 ],
            [ 41.0, 43.0, 47.0, 53.0 ],
        ]
    };

    let row0 = matrix[0];
    assert_eq!(row0, [ 2.0, 3.0, 5.0, 7.0 ]);

    let row1 = matrix[1];
    assert_eq!(row1, [ 11.0, 13.0, 17.0, 19.0 ]);

    let row2 = matrix[2];
    assert_eq!(row2, [ 23.0, 29.0, 31.0, 37.0 ]);

    let row3 = matrix[3];
    assert_eq!(row3, [ 41.0, 43.0, 47.0, 53.0 ]);
}
<commit_msg>Update glium to v0.7.0<commit_after>extern crate glium;

use std::mem::zeroed;
use std::ops::*;
use glium::uniforms::*;

#[derive(PartialEq, Clone, Debug)]
pub struct Matrix { m: [[f32; 4]; 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]],
            ]
        }
    }
}

#[test]
fn create_zero_filled_matrix() {
    let m = Matrix::zero();

    assert_eq!(m.m[0][0], 0.0);
    assert_eq!(m.m[0][1], 0.0);
    assert_eq!(m.m[0][2], 0.0);
    assert_eq!(m.m[0][3], 0.0);
    assert_eq!(m.m[1][0], 0.0);
    assert_eq!(m.m[1][1], 0.0);
    assert_eq!(m.m[1][2], 0.0);
    assert_eq!(m.m[1][3], 0.0);
    assert_eq!(m.m[2][0], 0.0);
    assert_eq!(m.m[2][1], 0.0);
    assert_eq!(m.m[2][2], 0.0);
    assert_eq!(m.m[2][3], 0.0);
    assert_eq!(m.m[3][0], 0.0);
    assert_eq!(m.m[3][1], 0.0);
    assert_eq!(m.m[3][2], 0.0);
    assert_eq!(m.m[3][3], 0.0);
}

#[test]
fn new_matrix() {
    let m = Matrix::new(
        1.0, 2.0, 3.0, 4.0,
        5.0, 6.0, 7.0, 8.0,
        9.0, 10.0, 11.0, 12.0,
        13.0, 14.0, 15.0, 16.0,
    );

    assert_eq!(m.m[0][0], 1.0);
    assert_eq!(m.m[0][1], 2.0);
    assert_eq!(m.m[0][2], 3.0);
    assert_eq!(m.m[0][3], 4.0);
    assert_eq!(m.m[1][0], 5.0);
    assert_eq!(m.m[1][1], 6.0);
    assert_eq!(m.m[1][2], 7.0);
    assert_eq!(m.m[1][3], 8.0);
    assert_eq!(m.m[2][0], 9.0);
    assert_eq!(m.m[2][1], 10.0);
    assert_eq!(m.m[2][2], 11.0);
    assert_eq!(m.m[2][3], 12.0);
    assert_eq!(m.m[3][0], 13.0);
    assert_eq!(m.m[3][1], 14.0);
    assert_eq!(m.m[3][2], 15.0);
    assert_eq!(m.m[3][3], 16.0);
}

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 AsUniformValue for Matrix {
    fn as_uniform_value(&self) -> UniformValue<'static> {
        UniformValue::Mat4(self.m)
    }
}

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

#[test]
fn indexing() {
    let matrix = Matrix {
        m: [
            [ 2.0, 3.0, 5.0, 7.0 ],
            [ 11.0, 13.0, 17.0, 19.0 ],
            [ 23.0, 29.0, 31.0, 37.0 ],
            [ 41.0, 43.0, 47.0, 53.0 ],
        ]
    };

    let row0 = matrix[0];
    assert_eq!(row0, [ 2.0, 3.0, 5.0, 7.0 ]);

    let row1 = matrix[1];
    assert_eq!(row1, [ 11.0, 13.0, 17.0, 19.0 ]);

    let row2 = matrix[2];
    assert_eq!(row2, [ 23.0, 29.0, 31.0, 37.0 ]);

    let row3 = matrix[3];
    assert_eq!(row3, [ 41.0, 43.0, 47.0, 53.0 ]);
}
<|endoftext|>