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

//! This module implements the `Any` trait, which enables dynamic typing
//! of any `'static` type through runtime reflection.
//!
//! `Any` itself can be used to get a `TypeId`, and has more features when used
//! as a trait object. As `&Any` (a borrowed trait object), it has the `is` and
//! `downcast_ref` methods, to test if the contained value is of a given type,
//! and to get a reference to the inner value as a type. As `&mut Any`, there
//! is also the `downcast_mut` method, for getting a mutable reference to the
//! inner value. `Box<Any>` adds the `downcast` method, which attempts to
//! convert to a `Box<T>`. See the [`Box`] documentation for the full details.
//!
//! Note that &Any is limited to testing whether a value is of a specified
//! concrete type, and cannot be used to test whether a type implements a trait.
//!
//! [`Box`]: ../../std/boxed/struct.Box.html
//!
//! # Examples
//!
//! Consider a situation where we want to log out a value passed to a function.
//! We know the value we're working on implements Debug, but we don't know its
//! concrete type.  We want to give special treatment to certain types: in this
//! case printing out the length of String values prior to their value.
//! We don't know the concrete type of our value at compile time, so we need to
//! use runtime reflection instead.
//!
//! ```rust
//! use std::fmt::Debug;
//! use std::any::Any;
//!
//! // Logger function for any type that implements Debug.
//! fn log<T: Any + Debug>(value: &T) {
//!     let value_any = value as &Any;
//!
//!     // try to convert our value to a String.  If successful, we want to
//!     // output the String's length as well as its value.  If not, it's a
//!     // different type: just print it out unadorned.
//!     match value_any.downcast_ref::<String>() {
//!         Some(as_string) => {
//!             println!("String ({}): {}", as_string.len(), as_string);
//!         }
//!         None => {
//!             println!("{:?}", value);
//!         }
//!     }
//! }
//!
//! // This function wants to log its parameter out prior to doing work with it.
//! fn do_work<T: Any + Debug>(value: &T) {
//!     log(value);
//!     // ...do some other work
//! }
//!
//! fn main() {
//!     let my_string = "Hello World".to_string();
//!     do_work(&my_string);
//!
//!     let my_i8: i8 = 100;
//!     do_work(&my_i8);
//! }
//! ```

#![stable(feature = "rust1", since = "1.0.0")]

use fmt;
use marker::Send;
use mem::transmute;
use option::Option::{self, Some, None};
use raw::TraitObject;
use intrinsics;
use marker::{Reflect, Sized};

///////////////////////////////////////////////////////////////////////////////
// Any trait
///////////////////////////////////////////////////////////////////////////////

/// A type to emulate dynamic typing.
///
/// Most types implement `Any`. However, any type which contains a non-`'static` reference does not.
/// See the [module-level documentation][mod] for more details.
///
/// [mod]: index.html
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Any: Reflect + 'static {
    /// Gets the `TypeId` of `self`.
    #[unstable(feature = "get_type_id",
               reason = "this method will likely be replaced by an associated static",
               issue = "27745")]
    fn get_type_id(&self) -> TypeId;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Reflect + 'static + ?Sized > Any for T {
    fn get_type_id(&self) -> TypeId { TypeId::of::<T>() }
}

///////////////////////////////////////////////////////////////////////////////
// Extension methods for Any trait objects.
///////////////////////////////////////////////////////////////////////////////

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for Any {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad("Any")
    }
}

// Ensure that the result of e.g. joining a thread can be printed and
// hence used with `unwrap`. May eventually no longer be needed if
// dispatch works with upcasting.
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for Any + Send {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad("Any")
    }
}

impl Any {
    /// Returns true if the boxed type is the same as `T`
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn is<T: Any>(&self) -> bool {
        // Get TypeId of the type this function is instantiated with
        let t = TypeId::of::<T>();

        // Get TypeId of the type in the trait object
        let boxed = self.get_type_id();

        // Compare both TypeIds on equality
        t == boxed
    }

    /// Returns some reference to the boxed value if it is of type `T`, or
    /// `None` if it isn't.
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
        if self.is::<T>() {
            unsafe {
                // Get the raw representation of the trait object
                let to: TraitObject = transmute(self);

                // Extract the data pointer
                Some(&*(to.data as *const T))
            }
        } else {
            None
        }
    }

    /// Returns some mutable reference to the boxed value if it is of type `T`, or
    /// `None` if it isn't.
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
        if self.is::<T>() {
            unsafe {
                // Get the raw representation of the trait object
                let to: TraitObject = transmute(self);

                // Extract the data pointer
                Some(&mut *(to.data as *const T as *mut T))
            }
        } else {
            None
        }
    }
}

impl Any+Send {
    /// Forwards to the method defined on the type `Any`.
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn is<T: Any>(&self) -> bool {
        Any::is::<T>(self)
    }

    /// Forwards to the method defined on the type `Any`.
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
        Any::downcast_ref::<T>(self)
    }

    /// Forwards to the method defined on the type `Any`.
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
        Any::downcast_mut::<T>(self)
    }
}

///////////////////////////////////////////////////////////////////////////////
// TypeID and its methods
///////////////////////////////////////////////////////////////////////////////

/// A `TypeId` represents a globally unique identifier for a type.
///
/// Each `TypeId` is an opaque object which does not allow inspection of what's
/// inside but does allow basic operations such as cloning, comparison,
/// printing, and showing.
///
/// A `TypeId` is currently only available for types which ascribe to `'static`,
/// but this limitation may be removed in the future.
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct TypeId {
    t: u64,
}

impl TypeId {
    /// Returns the `TypeId` of the type this generic function has been
    /// instantiated with
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn of<T: ?Sized + Reflect + 'static>() -> TypeId {
        TypeId {
            t: unsafe { intrinsics::type_id::<T>() },
        }
    }
}
<commit_msg>Improve std::any module doc<commit_after>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! This module implements the `Any` trait, which enables dynamic typing
//! of any `'static` type through runtime reflection.
//!
//! `Any` itself can be used to get a `TypeId`, and has more features when used
//! as a trait object. As `&Any` (a borrowed trait object), it has the `is` and
//! `downcast_ref` methods, to test if the contained value is of a given type,
//! and to get a reference to the inner value as a type. As `&mut Any`, there
//! is also the `downcast_mut` method, for getting a mutable reference to the
//! inner value. `Box<Any>` adds the `downcast` method, which attempts to
//! convert to a `Box<T>`. See the [`Box`] documentation for the full details.
//!
//! Note that &Any is limited to testing whether a value is of a specified
//! concrete type, and cannot be used to test whether a type implements a trait.
//!
//! [`Box`]: ../../std/boxed/struct.Box.html
//!
//! # Examples
//!
//! Consider a situation where we want to log out a value passed to a function.
//! We know the value we're working on implements Debug, but we don't know its
//! concrete type.  We want to give special treatment to certain types: in this
//! case printing out the length of String values prior to their value.
//! We don't know the concrete type of our value at compile time, so we need to
//! use runtime reflection instead.
//!
//! ```rust
//! use std::fmt::Debug;
//! use std::any::Any;
//!
//! // Logger function for any type that implements Debug.
//! fn log<T: Any + Debug>(value: &T) {
//!     let value_any = value as &Any;
//!
//!     // try to convert our value to a String.  If successful, we want to
//!     // output the String's length as well as its value.  If not, it's a
//!     // different type: just print it out unadorned.
//!     match value_any.downcast_ref::<String>() {
//!         Some(as_string) => {
//!             println!("String ({}): {}", as_string.len(), as_string);
//!         }
//!         None => {
//!             println!("{:?}", value);
//!         }
//!     }
//! }
//!
//! // This function wants to log its parameter out prior to doing work with it.
//! fn do_work<T: Any + Debug>(value: &T) {
//!     log(value);
//!     // ...do some other work
//! }
//!
//! fn main() {
//!     let my_string = "Hello World".to_string();
//!     do_work(&my_string);
//!
//!     let my_i8: i8 = 100;
//!     do_work(&my_i8);
//! }
//! ```

#![stable(feature = "rust1", since = "1.0.0")]

use fmt;
use marker::Send;
use mem::transmute;
use option::Option::{self, Some, None};
use raw::TraitObject;
use intrinsics;
use marker::{Reflect, Sized};

///////////////////////////////////////////////////////////////////////////////
// Any trait
///////////////////////////////////////////////////////////////////////////////

/// A type to emulate dynamic typing.
///
/// Most types implement `Any`. However, any type which contains a non-`'static` reference does not.
/// See the [module-level documentation][mod] for more details.
///
/// [mod]: index.html
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Any: Reflect + 'static {
    /// Gets the `TypeId` of `self`.
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(get_type_id)]
    ///
    /// use std::any::{Any, TypeId};
    ///
    /// fn is_string(s: &Any) -> bool {
    ///     TypeId::of::<String>() == s.get_type_id()
    /// }
    ///
    /// fn main() {
    ///     assert_eq!(is_string(&0), false);
    ///     assert_eq!(is_string(&"cookie monster".to_owned()), true);
    /// }
    /// ```
    #[unstable(feature = "get_type_id",
               reason = "this method will likely be replaced by an associated static",
               issue = "27745")]
    fn get_type_id(&self) -> TypeId;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Reflect + 'static + ?Sized > Any for T {
    fn get_type_id(&self) -> TypeId { TypeId::of::<T>() }
}

///////////////////////////////////////////////////////////////////////////////
// Extension methods for Any trait objects.
///////////////////////////////////////////////////////////////////////////////

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for Any {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad("Any")
    }
}

// Ensure that the result of e.g. joining a thread can be printed and
// hence used with `unwrap`. May eventually no longer be needed if
// dispatch works with upcasting.
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for Any + Send {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad("Any")
    }
}

impl Any {
    /// Returns true if the boxed type is the same as `T`.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::any::Any;
    ///
    /// fn is_string(s: &Any) {
    ///     if s.is::<String>() {
    ///         println!("It's a string!");
    ///     } else {
    ///         println!("Not a string...");
    ///     }
    /// }
    ///
    /// fn main() {
    ///     is_string(&0);
    ///     is_string(&"cookie monster".to_owned());
    /// }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn is<T: Any>(&self) -> bool {
        // Get TypeId of the type this function is instantiated with
        let t = TypeId::of::<T>();

        // Get TypeId of the type in the trait object
        let boxed = self.get_type_id();

        // Compare both TypeIds on equality
        t == boxed
    }

    /// Returns some reference to the boxed value if it is of type `T`, or
    /// `None` if it isn't.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::any::Any;
    ///
    /// fn print_if_string(s: &Any) {
    ///     if let Some(string) = s.downcast_ref::<String>() {
    ///         println!("It's a string({}): '{}'", string.len(), string);
    ///     } else {
    ///         println!("Not a string...");
    ///     }
    /// }
    ///
    /// fn main() {
    ///     print_if_string(&0);
    ///     print_if_string(&"cookie monster".to_owned());
    /// }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
        if self.is::<T>() {
            unsafe {
                // Get the raw representation of the trait object
                let to: TraitObject = transmute(self);

                // Extract the data pointer
                Some(&*(to.data as *const T))
            }
        } else {
            None
        }
    }

    /// Returns some mutable reference to the boxed value if it is of type `T`, or
    /// `None` if it isn't.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::any::Any;
    ///
    /// fn modify_if_u32(s: &mut Any) {
    ///     if let Some(num) = s.downcast_mut::<u32>() {
    ///         *num = 42;
    ///     }
    /// }
    ///
    /// fn main() {
    ///     let mut x = 10u32;
    ///     let mut s = "starlord".to_owned();
    ///
    ///     modify_if_u32(&mut x);
    ///     modify_if_u32(&mut s);
    ///
    ///     assert_eq!(x, 42);
    ///     assert_eq!(&s, "starlord");
    /// }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
        if self.is::<T>() {
            unsafe {
                // Get the raw representation of the trait object
                let to: TraitObject = transmute(self);

                // Extract the data pointer
                Some(&mut *(to.data as *const T as *mut T))
            }
        } else {
            None
        }
    }
}

impl Any+Send {
    /// Forwards to the method defined on the type `Any`.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::any::Any;
    ///
    /// fn is_string(s: &(Any + Send)) {
    ///     if s.is::<String>() {
    ///         println!("It's a string!");
    ///     } else {
    ///         println!("Not a string...");
    ///     }
    /// }
    ///
    /// fn main() {
    ///     is_string(&0);
    ///     is_string(&"cookie monster".to_owned());
    /// }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn is<T: Any>(&self) -> bool {
        Any::is::<T>(self)
    }

    /// Forwards to the method defined on the type `Any`.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::any::Any;
    ///
    /// fn print_if_string(s: &(Any + Send)) {
    ///     if let Some(string) = s.downcast_ref::<String>() {
    ///         println!("It's a string({}): '{}'", string.len(), string);
    ///     } else {
    ///         println!("Not a string...");
    ///     }
    /// }
    ///
    /// fn main() {
    ///     print_if_string(&0);
    ///     print_if_string(&"cookie monster".to_owned());
    /// }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
        Any::downcast_ref::<T>(self)
    }

    /// Forwards to the method defined on the type `Any`.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::any::Any;
    ///
    /// fn modify_if_u32(s: &mut (Any+ Send)) {
    ///     if let Some(num) = s.downcast_mut::<u32>() {
    ///         *num = 42;
    ///     }
    /// }
    ///
    /// fn main() {
    ///     let mut x = 10u32;
    ///     let mut s = "starlord".to_owned();
    ///
    ///     modify_if_u32(&mut x);
    ///     modify_if_u32(&mut s);
    ///
    ///     assert_eq!(x, 42);
    ///     assert_eq!(&s, "starlord");
    /// }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
        Any::downcast_mut::<T>(self)
    }
}

///////////////////////////////////////////////////////////////////////////////
// TypeID and its methods
///////////////////////////////////////////////////////////////////////////////

/// A `TypeId` represents a globally unique identifier for a type.
///
/// Each `TypeId` is an opaque object which does not allow inspection of what's
/// inside but does allow basic operations such as cloning, comparison,
/// printing, and showing.
///
/// A `TypeId` is currently only available for types which ascribe to `'static`,
/// but this limitation may be removed in the future.
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct TypeId {
    t: u64,
}

impl TypeId {
    /// Returns the `TypeId` of the type this generic function has been
    /// instantiated with.
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(get_type_id)]
    ///
    /// use std::any::{Any, TypeId};
    ///
    /// fn is_string(s: &Any) -> bool {
    ///     TypeId::of::<String>() == s.get_type_id()
    /// }
    ///
    /// fn main() {
    ///     assert_eq!(is_string(&0), false);
    ///     assert_eq!(is_string(&"cookie monster".to_owned()), true);
    /// }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn of<T: ?Sized + Reflect + 'static>() -> TypeId {
        TypeId {
            t: unsafe { intrinsics::type_id::<T>() },
        }
    }
}
<|endoftext|>


<commit_before>use toml::Value;

/// Check whether the configuration is valid for the store
///
/// The passed `Value` _must be_ the `[store]` sub-tree of the configuration. Otherwise this will
/// fail.
///
/// It checks whether the configuration looks like the store wants it to be:
///
/// ```toml
/// [store]
/// pre-create-hook-aspects = [ "misc", "encryption", "version-control"]
///
/// [[aspects.misc]]
/// parallel = true
/// [[aspects.encryption]]
/// parallel = false
/// [[aspects.version-control]]
/// parallel = false
///
/// [[hooks.gnupg]]
/// aspect = "encryption"
/// key = "0x123456789"
///
/// [[hooks.git]]
/// aspect = "version-control"
/// ```
///
/// It checks:
///  * Whether all the maps are there (whether store, store.aspects, store.aspects.example are all
///  maps)
///  * Whether each aspect configuration has a "parallel = <Boolean>" setting
///  * Whether each hook congfiguration has a "aspect = <String>" setting
///
/// It does NOT check:
///  * Whether all aspects which are used in the hook configuration are also configured
///
/// No configuration is a valid configuration, as the store will use the most conservative settings
/// automatically. This has also performance impact, as all hooks run in no-parallel mode then.
/// You have been warned!
///
///
pub fn config_is_valid(config: &Option<Value>) -> bool {
    use std::collections::BTreeMap;

    if config.is_none() {
        return true;
    }

    fn has_key_with_string_ary(v: &BTreeMap<String, Value>, key: &str) -> bool {
        v.get(key)
            .map(|t| match t {
                &Value::Array(ref a) => a.iter().all(|elem| {
                    match elem {
                        &Value::String(_) => true,
                        _ => false,
                    }
                }),
                _ => false
            }).unwrap_or(false)
    }

    /// Check that
    /// * the top-level configuration
    /// * is a table
    /// * where all entries of a key `section` (eg. "hooks" or "aspects")
    ///     * Are maps
    ///     * where each has a key `key` (eg. "aspect" or "parallel")
    ///     * which fullfills constraint `f` (typecheck)
    fn check_all_inner_maps_have_key_with<F>(store_config: &BTreeMap<String, Value>,
                                             section: &str,
                                             key: &str,
                                             f: F)
        -> bool
        where F: Fn(&Value) -> bool
    {
        store_config.get(section) // The store config has the section `section`
            .map(|section_table| {
                match section_table { // which is
                    &Value::Table(ref section_table) => // a table
                        section_table
                            .values() // which has values,
                            .all(|cfg| { // and all of these values
                                match cfg {
                                    &Value::Table(ref hook_config) => { // are tables
                                        hook_config.get(key) // with a key
                                            // fullfilling this constraint
                                            .map(|hook_aspect| f(&hook_aspect))
                                            .unwrap_or(false)
                                    },
                                    _ => false,
                                }
                            }),
                    _ => false,
                }
            })
            .unwrap_or(false)
    }

    match config {
        &Some(Value::Table(ref t)) => {
            has_key_with_string_ary(t, "pre-read-hook-aspects")        &&
            has_key_with_string_ary(t, "post-read-hook-aspects")       &&
            has_key_with_string_ary(t, "pre-create-hook-aspects")      &&
            has_key_with_string_ary(t, "post-create-hook-aspects")     &&
            has_key_with_string_ary(t, "pre-retrieve-hook-aspects")    &&
            has_key_with_string_ary(t, "post-retrieve-hook-aspects")   &&
            has_key_with_string_ary(t, "pre-update-hook-aspects")      &&
            has_key_with_string_ary(t, "post-update-hook-aspects")     &&
            has_key_with_string_ary(t, "pre-delete-hook-aspects")      &&
            has_key_with_string_ary(t, "post-delete-hook-aspects")     &&

            // The section "hooks" has maps which have a key "aspect" which has a value of type
            // String
            check_all_inner_maps_have_key_with(t, "hooks", "aspect", |asp| {
                match asp { &Value::String(_) => true, _ => false }
            }) &&

            // The section "aspects" has maps which have a key "parllel" which has a value of type
            // Boolean
            check_all_inner_maps_have_key_with(t, "aspects", "parallel", |asp| {
                match asp { &Value::Boolean(_) => true, _ => false, }
            })
        }
        _ => false,
    }
}

pub fn get_pre_read_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("pre-read-hook-aspects", value)
}

pub fn get_post_read_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("post-read-hook-aspects", value)
}

pub fn get_pre_create_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("pre-create-hook-aspects", value)
}

pub fn get_post_create_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("post-create-hook-aspects", value)
}

pub fn get_pre_retrieve_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("pre-retrieve-hook-aspects", value)
}

pub fn get_post_retrieve_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("post-retrieve-hook-aspects", value)
}

pub fn get_pre_update_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("pre-update-hook-aspects", value)
}

pub fn get_post_update_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("post-update-hook-aspects", value)
}

pub fn get_pre_delete_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("pre-delete-hook-aspects", value)
}

pub fn get_post_delete_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("post-delete-hook-aspects", value)
}

#[derive(Debug)]
pub struct AspectConfig {
    parallel: bool,
    config: Value,
}

impl AspectConfig {

    pub fn new(init: Value) -> AspectConfig {
        let parallel = AspectConfig::is_parallel(&init);
        AspectConfig {
            config: init,
            parallel: parallel,
        }
    }

    fn is_parallel(init: &Value) -> bool {
        match init {
            &Value::Table(ref t) =>
                t.get("parallel")
                    .map(|value| {
                        match value {
                            &Value::Boolean(b) => b,
                            _ => false,
                        }
                    })
                    .unwrap_or(false),
            _ => false,
        }
    }

    /// Get the aspect configuration for an aspect.
    ///
    /// Pass the store configuration object, this searches in `[aspects][<aspect_name>]`.
    ///
    /// Returns `None` if one of the keys in the chain is not available
    pub fn get_for(v: &Option<Value>, a_name: String) -> Option<AspectConfig> {
        match v {
            &Some(Value::Table(ref tabl)) => tabl.get(&a_name[..])
                .map(|asp| AspectConfig::new(asp.clone())),
            _ => None,
        }
    }

}

fn get_aspect_names_for_aspect_position(config_name: &'static str, value: &Option<Value>) -> Vec<String> {
    let mut v = vec![];

    match value {
        &Some(Value::Table(ref t)) => {
            match t.get(config_name) {
                Some(&Value::Array(ref a)) => {
                    for elem in a {
                        match elem {
                            &Value::String(ref s) => v.push(s.clone()),
                            _ => warn!("Non-String in configuration, inside '{}'", config_name),
                        }
                    }
                },
                _ => warn!("'{}' configuration key should contain Array, does not", config_name),
            };
        },
        &None => warn!("No store configuration"),
        _ => warn!("Configuration is not a table"),
    }
    v
}

<commit_msg>Removed unused functions<commit_after>use toml::Value;

/// Check whether the configuration is valid for the store
///
/// The passed `Value` _must be_ the `[store]` sub-tree of the configuration. Otherwise this will
/// fail.
///
/// It checks whether the configuration looks like the store wants it to be:
///
/// ```toml
/// [store]
/// pre-create-hook-aspects = [ "misc", "encryption", "version-control"]
///
/// [[aspects.misc]]
/// parallel = true
/// [[aspects.encryption]]
/// parallel = false
/// [[aspects.version-control]]
/// parallel = false
///
/// [[hooks.gnupg]]
/// aspect = "encryption"
/// key = "0x123456789"
///
/// [[hooks.git]]
/// aspect = "version-control"
/// ```
///
/// It checks:
///  * Whether all the maps are there (whether store, store.aspects, store.aspects.example are all
///  maps)
///  * Whether each aspect configuration has a "parallel = <Boolean>" setting
///  * Whether each hook congfiguration has a "aspect = <String>" setting
///
/// It does NOT check:
///  * Whether all aspects which are used in the hook configuration are also configured
///
/// No configuration is a valid configuration, as the store will use the most conservative settings
/// automatically. This has also performance impact, as all hooks run in no-parallel mode then.
/// You have been warned!
///
///
pub fn config_is_valid(config: &Option<Value>) -> bool {
    use std::collections::BTreeMap;

    if config.is_none() {
        return true;
    }

    fn has_key_with_string_ary(v: &BTreeMap<String, Value>, key: &str) -> bool {
        v.get(key)
            .map(|t| match t {
                &Value::Array(ref a) => a.iter().all(|elem| {
                    match elem {
                        &Value::String(_) => true,
                        _ => false,
                    }
                }),
                _ => false
            }).unwrap_or(false)
    }

    /// Check that
    /// * the top-level configuration
    /// * is a table
    /// * where all entries of a key `section` (eg. "hooks" or "aspects")
    ///     * Are maps
    ///     * where each has a key `key` (eg. "aspect" or "parallel")
    ///     * which fullfills constraint `f` (typecheck)
    fn check_all_inner_maps_have_key_with<F>(store_config: &BTreeMap<String, Value>,
                                             section: &str,
                                             key: &str,
                                             f: F)
        -> bool
        where F: Fn(&Value) -> bool
    {
        store_config.get(section) // The store config has the section `section`
            .map(|section_table| {
                match section_table { // which is
                    &Value::Table(ref section_table) => // a table
                        section_table
                            .values() // which has values,
                            .all(|cfg| { // and all of these values
                                match cfg {
                                    &Value::Table(ref hook_config) => { // are tables
                                        hook_config.get(key) // with a key
                                            // fullfilling this constraint
                                            .map(|hook_aspect| f(&hook_aspect))
                                            .unwrap_or(false)
                                    },
                                    _ => false,
                                }
                            }),
                    _ => false,
                }
            })
            .unwrap_or(false)
    }

    match config {
        &Some(Value::Table(ref t)) => {
            has_key_with_string_ary(t, "pre-read-hook-aspects")        &&
            has_key_with_string_ary(t, "post-read-hook-aspects")       &&
            has_key_with_string_ary(t, "pre-create-hook-aspects")      &&
            has_key_with_string_ary(t, "post-create-hook-aspects")     &&
            has_key_with_string_ary(t, "pre-retrieve-hook-aspects")    &&
            has_key_with_string_ary(t, "post-retrieve-hook-aspects")   &&
            has_key_with_string_ary(t, "pre-update-hook-aspects")      &&
            has_key_with_string_ary(t, "post-update-hook-aspects")     &&
            has_key_with_string_ary(t, "pre-delete-hook-aspects")      &&
            has_key_with_string_ary(t, "post-delete-hook-aspects")     &&

            // The section "hooks" has maps which have a key "aspect" which has a value of type
            // String
            check_all_inner_maps_have_key_with(t, "hooks", "aspect", |asp| {
                match asp { &Value::String(_) => true, _ => false }
            }) &&

            // The section "aspects" has maps which have a key "parllel" which has a value of type
            // Boolean
            check_all_inner_maps_have_key_with(t, "aspects", "parallel", |asp| {
                match asp { &Value::Boolean(_) => true, _ => false, }
            })
        }
        _ => false,
    }
}

pub fn get_pre_create_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("pre-create-hook-aspects", value)
}

pub fn get_post_create_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("post-create-hook-aspects", value)
}

pub fn get_pre_retrieve_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("pre-retrieve-hook-aspects", value)
}

pub fn get_post_retrieve_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("post-retrieve-hook-aspects", value)
}

pub fn get_pre_update_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("pre-update-hook-aspects", value)
}

pub fn get_post_update_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("post-update-hook-aspects", value)
}

pub fn get_pre_delete_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("pre-delete-hook-aspects", value)
}

pub fn get_post_delete_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("post-delete-hook-aspects", value)
}

#[derive(Debug)]
pub struct AspectConfig {
    parallel: bool,
    config: Value,
}

impl AspectConfig {

    pub fn new(init: Value) -> AspectConfig {
        let parallel = AspectConfig::is_parallel(&init);
        AspectConfig {
            config: init,
            parallel: parallel,
        }
    }

    fn is_parallel(init: &Value) -> bool {
        match init {
            &Value::Table(ref t) =>
                t.get("parallel")
                    .map(|value| {
                        match value {
                            &Value::Boolean(b) => b,
                            _ => false,
                        }
                    })
                    .unwrap_or(false),
            _ => false,
        }
    }

    /// Get the aspect configuration for an aspect.
    ///
    /// Pass the store configuration object, this searches in `[aspects][<aspect_name>]`.
    ///
    /// Returns `None` if one of the keys in the chain is not available
    pub fn get_for(v: &Option<Value>, a_name: String) -> Option<AspectConfig> {
        match v {
            &Some(Value::Table(ref tabl)) => tabl.get(&a_name[..])
                .map(|asp| AspectConfig::new(asp.clone())),
            _ => None,
        }
    }

}

fn get_aspect_names_for_aspect_position(config_name: &'static str, value: &Option<Value>) -> Vec<String> {
    let mut v = vec![];

    match value {
        &Some(Value::Table(ref t)) => {
            match t.get(config_name) {
                Some(&Value::Array(ref a)) => {
                    for elem in a {
                        match elem {
                            &Value::String(ref s) => v.push(s.clone()),
                            _ => warn!("Non-String in configuration, inside '{}'", config_name),
                        }
                    }
                },
                _ => warn!("'{}' configuration key should contain Array, does not", config_name),
            };
        },
        &None => warn!("No store configuration"),
        _ => warn!("Configuration is not a table"),
    }
    v
}

<|endoftext|>


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

/*! Composable internal iterators

Internal iterators are functions implementing the protocol used by the `for` loop.

An internal iterator takes `fn(...) -> bool` as a parameter, with returning `false` used to signal
breaking out of iteration. The adaptors in the module work with any such iterator, not just ones
tied to specific traits. For example:

~~~ {.rust}
println(iter::to_vec(|f| uint::range(0, 20, f)).to_str());
~~~

An external iterator object implementing the interface in the `iterator` module can be used as an
internal iterator by calling the `advance` method. For example:

~~~ {.rust}
use core::iterator::*;

let xs = [0u, 1, 2, 3, 4, 5];
let ys = [30, 40, 50, 60];
let mut it = xs.iter().chain(ys.iter());
for it.advance |&x: &uint| {
    println(x.to_str());
}
~~~

Internal iterators provide a subset of the functionality of an external iterator. It's not possible
to interleave them to implement algorithms like `zip`, `union` and `merge`. However, they're often
much easier to implement.

*/

use cmp::Ord;
use option::{Option, Some, None};
use vec::OwnedVector;
use num::{One, Zero};
use ops::{Add, Mul};

#[allow(missing_doc)]
pub trait Times {
    fn times(&self, it: &fn() -> bool) -> bool;
}

/**
 * Transform an internal iterator into an owned vector.
 *
 * # Example:
 *
 * ~~~ {.rust}
 * let xs = ~[1, 2, 3];
 * let ys = do iter::to_vec |f| { xs.each(|x| f(*x)) };
 * assert_eq!(xs, ys);
 * ~~~
 */
#[inline(always)]
pub fn to_vec<T>(iter: &fn(f: &fn(T) -> bool) -> bool) -> ~[T] {
    let mut v = ~[];
    for iter |x| { v.push(x) }
    v
}

/**
 * Return true if `predicate` is true for any values yielded by an internal iterator.
 *
 * Example:
 *
 * ~~~ {.rust}
 * let xs = ~[1u, 2, 3, 4, 5];
 * assert!(any(|&x: &uint| x > 2, |f| xs.each(f)));
 * assert!(!any(|&x: &uint| x > 5, |f| xs.each(f)));
 * ~~~
 */
#[inline(always)]
pub fn any<T>(predicate: &fn(T) -> bool,
              iter: &fn(f: &fn(T) -> bool) -> bool) -> bool {
    for iter |x| {
        if predicate(x) {
            return true;
        }
    }
    return false;
}

/**
 * Return true if `predicate` is true for all values yielded by an internal iterator.
 *
 * # Example:
 *
 * ~~~ {.rust}
 * assert!(all(|&x: &uint| x < 6, |f| uint::range(1, 6, f)));
 * assert!(!all(|&x: &uint| x < 5, |f| uint::range(1, 6, f)));
 * ~~~
 */
#[inline(always)]
pub fn all<T>(predicate: &fn(T) -> bool,
              iter: &fn(f: &fn(T) -> bool) -> bool) -> bool {
    // If we ever break, iter will return false, so this will only return true
    // if predicate returns true for everything.
    iter(|x| predicate(x))
}

/**
 * Return the first element where `predicate` returns `true`. Return `None` if no element is found.
 *
 * # Example:
 *
 * ~~~ {.rust}
 * let xs = ~[1u, 2, 3, 4, 5, 6];
 * assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.each(f)).unwrap(), 4);
 * ~~~
 */
#[inline(always)]
pub fn find<T>(predicate: &fn(&T) -> bool,
               iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
    for iter |x| {
        if predicate(&x) {
            return Some(x);
        }
    }
    None
}

/**
 * Return the largest item yielded by an iterator. Return `None` if the iterator is empty.
 *
 * # Example:
 *
 * ~~~ {.rust}
 * let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
 * assert_eq!(max(|f| xs.each(f)).unwrap(), &15);
 * ~~~
 */
#[inline]
pub fn max<T: Ord>(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
    let mut result = None;
    for iter |x| {
        match result {
            Some(ref mut y) => {
                if x > *y {
                    *y = x;
                }
            }
            None => result = Some(x)
        }
    }
    result
}

/**
 * Return the smallest item yielded by an iterator. Return `None` if the iterator is empty.
 *
 * # Example:
 *
 * ~~~ {.rust}
 * let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
 * assert_eq!(max(|f| xs.each(f)).unwrap(), &-5);
 * ~~~
 */
#[inline]
pub fn min<T: Ord>(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
    let mut result = None;
    for iter |x| {
        match result {
            Some(ref mut y) => {
                if x < *y {
                    *y = x;
                }
            }
            None => result = Some(x)
        }
    }
    result
}

/**
 * Reduce an iterator to an accumulated value.
 *
 * # Example:
 *
 * ~~~ {.rust}
 * assert_eq!(fold(0i, |f| int::range(1, 5, f), |a, x| *a += x), 10);
 * ~~~
 */
#[inline]
pub fn fold<T, U>(start: T, iter: &fn(f: &fn(U) -> bool) -> bool, f: &fn(&mut T, U)) -> T {
    let mut result = start;
    for iter |x| {
        f(&mut result, x);
    }
    result
}

/**
 * Reduce an iterator to an accumulated value.
 *
 * `fold_ref` is usable in some generic functions where `fold` is too lenient to type-check, but it
 * forces the iterator to yield borrowed pointers.
 *
 * # Example:
 *
 * ~~~ {.rust}
 * fn product<T: One + Mul<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T {
 *     fold_ref(One::one::<T>(), iter, |a, x| *a = a.mul(x))
 * }
 * ~~~
 */
#[inline]
pub fn fold_ref<T, U>(start: T, iter: &fn(f: &fn(&U) -> bool) -> bool, f: &fn(&mut T, &U)) -> T {
    let mut result = start;
    for iter |x| {
        f(&mut result, x);
    }
    result
}

/**
 * Return the sum of the items yielding by an iterator.
 *
 * # Example:
 *
 * ~~~ {.rust}
 * let xs: ~[int] = ~[1, 2, 3, 4];
 * assert_eq!(do sum |f| { xs.each(f) }, 10);
 * ~~~
 */
#[inline(always)]
pub fn sum<T: Zero + Add<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T {
    fold_ref(Zero::zero::<T>(), iter, |a, x| *a = a.add(x))
}

/**
 * Return the product of the items yielded by an iterator.
 *
 * # Example:
 *
 * ~~~ {.rust}
 * let xs: ~[int] = ~[1, 2, 3, 4];
 * assert_eq!(do product |f| { xs.each(f) }, 24);
 * ~~~
 */
#[inline(always)]
pub fn product<T: One + Mul<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T {
    fold_ref(One::one::<T>(), iter, |a, x| *a = a.mul(x))
}

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

    use int;
    use uint;

    #[test]
    fn test_to_vec() {
        let xs = ~[1, 2, 3];
        let ys = do to_vec |f| { xs.each(|x| f(*x)) };
        assert_eq!(xs, ys);
    }

    #[test]
    fn test_any() {
        let xs = ~[1u, 2, 3, 4, 5];
        assert!(any(|&x: &uint| x > 2, |f| xs.each(f)));
        assert!(!any(|&x: &uint| x > 5, |f| xs.each(f)));
    }

    #[test]
    fn test_all() {
        assert!(all(|x: uint| x < 6, |f| uint::range(1, 6, f)));
        assert!(!all(|x: uint| x < 5, |f| uint::range(1, 6, f)));
    }

    #[test]
    fn test_find() {
        let xs = ~[1u, 2, 3, 4, 5, 6];
        assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.each(f)).unwrap(), 4);
    }

    #[test]
    fn test_max() {
        let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
        assert_eq!(max(|f| xs.each(f)).unwrap(), &15);
    }

    #[test]
    fn test_min() {
        let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
        assert_eq!(min(|f| xs.each(f)).unwrap(), &-5);
    }

    #[test]
    fn test_fold() {
        assert_eq!(fold(0i, |f| int::range(1, 5, f), |a, x| *a += x), 10);
    }

    #[test]
    fn test_sum() {
        let xs: ~[int] = ~[1, 2, 3, 4];
        assert_eq!(do sum |f| { xs.each(f) }, 10);
    }

    #[test]
    fn test_empty_sum() {
        let xs: ~[int] = ~[];
        assert_eq!(do sum |f| { xs.each(f) }, 0);
    }

    #[test]
    fn test_product() {
        let xs: ~[int] = ~[1, 2, 3, 4];
        assert_eq!(do product |f| { xs.each(f) }, 24);
    }

    #[test]
    fn test_empty_product() {
        let xs: ~[int] = ~[];
        assert_eq!(do product |f| { xs.each(f) }, 1);
    }
}
<commit_msg>Added iter::FromIter<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*! Composable internal iterators

Internal iterators are functions implementing the protocol used by the `for` loop.

An internal iterator takes `fn(...) -> bool` as a parameter, with returning `false` used to signal
breaking out of iteration. The adaptors in the module work with any such iterator, not just ones
tied to specific traits. For example:

~~~ {.rust}
println(iter::to_vec(|f| uint::range(0, 20, f)).to_str());
~~~

An external iterator object implementing the interface in the `iterator` module can be used as an
internal iterator by calling the `advance` method. For example:

~~~ {.rust}
use core::iterator::*;

let xs = [0u, 1, 2, 3, 4, 5];
let ys = [30, 40, 50, 60];
let mut it = xs.iter().chain(ys.iter());
for it.advance |&x: &uint| {
    println(x.to_str());
}
~~~

Internal iterators provide a subset of the functionality of an external iterator. It's not possible
to interleave them to implement algorithms like `zip`, `union` and `merge`. However, they're often
much easier to implement.

*/

use cmp::Ord;
use option::{Option, Some, None};
use vec::OwnedVector;
use num::{One, Zero};
use ops::{Add, Mul};

#[allow(missing_doc)]
pub trait Times {
    fn times(&self, it: &fn() -> bool) -> bool;
}

pub trait FromIter<T> {
    // Build a container with elements from an internal iterator.
    //
    // # Example:
    //
    // ~~~ {.rust}
    // let xs = ~[1, 2, 3];
    // let ys: ~[int] = do FromIter::from_iter |f| { xs.each(|x| f(*x)) };
    // assert_eq!(xs, ys);
    // ~~~
    pub fn from_iter(iter: &fn(f: &fn(T) -> bool) -> bool) -> Self;
}

// NOTE: This should be in vec but can't because of coherence
impl<T> FromIter<T> for ~[T]{
    #[inline(always)]
    pub fn from_iter(iter: &fn(f: &fn(T) -> bool) -> bool) -> ~[T] {
        let mut v = ~[];
        for iter |x| { v.push(x) }
        v
    }
}

/**
 * Transform an internal iterator into an owned vector.
 *
 * # Example:
 *
 * ~~~ {.rust}
 * let xs = ~[1, 2, 3];
 * let ys = do iter::to_vec |f| { xs.each(|x| f(*x)) };
 * assert_eq!(xs, ys);
 * ~~~
 */
#[inline(always)]
pub fn to_vec<T>(iter: &fn(f: &fn(T) -> bool) -> bool) -> ~[T] {
    FromIter::from_iter(iter)
}

/**
 * Return true if `predicate` is true for any values yielded by an internal iterator.
 *
 * Example:
 *
 * ~~~ {.rust}
 * let xs = ~[1u, 2, 3, 4, 5];
 * assert!(any(|&x: &uint| x > 2, |f| xs.each(f)));
 * assert!(!any(|&x: &uint| x > 5, |f| xs.each(f)));
 * ~~~
 */
#[inline(always)]
pub fn any<T>(predicate: &fn(T) -> bool,
              iter: &fn(f: &fn(T) -> bool) -> bool) -> bool {
    for iter |x| {
        if predicate(x) {
            return true;
        }
    }
    return false;
}

/**
 * Return true if `predicate` is true for all values yielded by an internal iterator.
 *
 * # Example:
 *
 * ~~~ {.rust}
 * assert!(all(|&x: &uint| x < 6, |f| uint::range(1, 6, f)));
 * assert!(!all(|&x: &uint| x < 5, |f| uint::range(1, 6, f)));
 * ~~~
 */
#[inline(always)]
pub fn all<T>(predicate: &fn(T) -> bool,
              iter: &fn(f: &fn(T) -> bool) -> bool) -> bool {
    // If we ever break, iter will return false, so this will only return true
    // if predicate returns true for everything.
    iter(|x| predicate(x))
}

/**
 * Return the first element where `predicate` returns `true`. Return `None` if no element is found.
 *
 * # Example:
 *
 * ~~~ {.rust}
 * let xs = ~[1u, 2, 3, 4, 5, 6];
 * assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.each(f)).unwrap(), 4);
 * ~~~
 */
#[inline(always)]
pub fn find<T>(predicate: &fn(&T) -> bool,
               iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
    for iter |x| {
        if predicate(&x) {
            return Some(x);
        }
    }
    None
}

/**
 * Return the largest item yielded by an iterator. Return `None` if the iterator is empty.
 *
 * # Example:
 *
 * ~~~ {.rust}
 * let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
 * assert_eq!(max(|f| xs.each(f)).unwrap(), &15);
 * ~~~
 */
#[inline]
pub fn max<T: Ord>(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
    let mut result = None;
    for iter |x| {
        match result {
            Some(ref mut y) => {
                if x > *y {
                    *y = x;
                }
            }
            None => result = Some(x)
        }
    }
    result
}

/**
 * Return the smallest item yielded by an iterator. Return `None` if the iterator is empty.
 *
 * # Example:
 *
 * ~~~ {.rust}
 * let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
 * assert_eq!(max(|f| xs.each(f)).unwrap(), &-5);
 * ~~~
 */
#[inline]
pub fn min<T: Ord>(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
    let mut result = None;
    for iter |x| {
        match result {
            Some(ref mut y) => {
                if x < *y {
                    *y = x;
                }
            }
            None => result = Some(x)
        }
    }
    result
}

/**
 * Reduce an iterator to an accumulated value.
 *
 * # Example:
 *
 * ~~~ {.rust}
 * assert_eq!(fold(0i, |f| int::range(1, 5, f), |a, x| *a += x), 10);
 * ~~~
 */
#[inline]
pub fn fold<T, U>(start: T, iter: &fn(f: &fn(U) -> bool) -> bool, f: &fn(&mut T, U)) -> T {
    let mut result = start;
    for iter |x| {
        f(&mut result, x);
    }
    result
}

/**
 * Reduce an iterator to an accumulated value.
 *
 * `fold_ref` is usable in some generic functions where `fold` is too lenient to type-check, but it
 * forces the iterator to yield borrowed pointers.
 *
 * # Example:
 *
 * ~~~ {.rust}
 * fn product<T: One + Mul<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T {
 *     fold_ref(One::one::<T>(), iter, |a, x| *a = a.mul(x))
 * }
 * ~~~
 */
#[inline]
pub fn fold_ref<T, U>(start: T, iter: &fn(f: &fn(&U) -> bool) -> bool, f: &fn(&mut T, &U)) -> T {
    let mut result = start;
    for iter |x| {
        f(&mut result, x);
    }
    result
}

/**
 * Return the sum of the items yielding by an iterator.
 *
 * # Example:
 *
 * ~~~ {.rust}
 * let xs: ~[int] = ~[1, 2, 3, 4];
 * assert_eq!(do sum |f| { xs.each(f) }, 10);
 * ~~~
 */
#[inline(always)]
pub fn sum<T: Zero + Add<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T {
    fold_ref(Zero::zero::<T>(), iter, |a, x| *a = a.add(x))
}

/**
 * Return the product of the items yielded by an iterator.
 *
 * # Example:
 *
 * ~~~ {.rust}
 * let xs: ~[int] = ~[1, 2, 3, 4];
 * assert_eq!(do product |f| { xs.each(f) }, 24);
 * ~~~
 */
#[inline(always)]
pub fn product<T: One + Mul<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T {
    fold_ref(One::one::<T>(), iter, |a, x| *a = a.mul(x))
}

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

    use int;
    use uint;

    #[test]
    fn test_to_vec() {
        let xs = ~[1, 2, 3];
        let ys = do to_vec |f| { xs.each(|x| f(*x)) };
        assert_eq!(xs, ys);
    }

    #[test]
    fn test_from_iter() {
        let xs: ~[int] = ~[1, 2, 3];
        let ys: ~[int] = do FromIter::from_iter |f| { xs.each(|x| f(*x)) };
        assert_eq!(xs, ys);
    }

    #[test]
    fn test_any() {
        let xs = ~[1u, 2, 3, 4, 5];
        assert!(any(|&x: &uint| x > 2, |f| xs.each(f)));
        assert!(!any(|&x: &uint| x > 5, |f| xs.each(f)));
    }

    #[test]
    fn test_all() {
        assert!(all(|x: uint| x < 6, |f| uint::range(1, 6, f)));
        assert!(!all(|x: uint| x < 5, |f| uint::range(1, 6, f)));
    }

    #[test]
    fn test_find() {
        let xs = ~[1u, 2, 3, 4, 5, 6];
        assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.each(f)).unwrap(), 4);
    }

    #[test]
    fn test_max() {
        let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
        assert_eq!(max(|f| xs.each(f)).unwrap(), &15);
    }

    #[test]
    fn test_min() {
        let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
        assert_eq!(min(|f| xs.each(f)).unwrap(), &-5);
    }

    #[test]
    fn test_fold() {
        assert_eq!(fold(0i, |f| int::range(1, 5, f), |a, x| *a += x), 10);
    }

    #[test]
    fn test_sum() {
        let xs: ~[int] = ~[1, 2, 3, 4];
        assert_eq!(do sum |f| { xs.each(f) }, 10);
    }

    #[test]
    fn test_empty_sum() {
        let xs: ~[int] = ~[];
        assert_eq!(do sum |f| { xs.each(f) }, 0);
    }

    #[test]
    fn test_product() {
        let xs: ~[int] = ~[1, 2, 3, 4];
        assert_eq!(do product |f| { xs.each(f) }, 24);
    }

    #[test]
    fn test_empty_product() {
        let xs: ~[int] = ~[];
        assert_eq!(do product |f| { xs.each(f) }, 1);
    }
}
<|endoftext|>


<commit_before><commit_msg>Fix for the number factorization code. Preventing duplicates.<commit_after><|endoftext|>


<commit_before><commit_msg>Make match_available be the bool it really wants to be<commit_after><|endoftext|>


<commit_before><commit_msg>Auto merge of #1699 - m-ou-se:panic-format, r=RalfJung<commit_after><|endoftext|>


<commit_before><commit_msg>Auto merge of #2113 - RalfJung:rustc-log, r=RalfJung<commit_after><|endoftext|>


<commit_before>#![allow(dead_code)]

extern crate libc;

use crate::config::Config;
use crate::layout::{Layout, LayoutMsg};
use crate::xlib_window_system::XlibWindowSystem;
use crate::workspaces::Workspaces;
use crate::workspace::MoveOp;
use self::libc::execvp;
use std::{env, thread};
use std::ptr::null;
use std::ffi::CString;
use std::process::Command;
use std::path::Path;
use std::fs::OpenOptions;
use x11::xlib::Window;
use anyhow::{bail, Context, Result};

pub enum Cmd {
    Exec(String),
    SwitchWorkspace(usize),
    SwitchScreen(usize),
    MoveToWorkspace(usize),
    MoveToScreen(usize),
    SendLayoutMsg(LayoutMsg),
    NestLayout(Box<dyn Fn() -> Box<dyn Layout>>),
    Reload,
    Exit,
    KillClient,
    FocusParentUp,
    FocusParentDown,
    FocusParentMaster,
    FocusUp,
    FocusDown,
    FocusMaster,
    SwapUp,
    SwapDown,
    SwapMaster,
    SwapParentUp,
    SwapParentDown,
    SwapParentMaster,
}

impl Cmd {
    pub fn call(&self, ws: &XlibWindowSystem, workspaces: &mut Workspaces, config: &Config) -> Result<()> {
        match self {
            Cmd::Exec(ref cmd) => {
                debug!("Cmd::Exec: {}", cmd);
                exec(cmd.clone());
            }
            Cmd::SwitchWorkspace(index) => {
                debug!("Cmd::SwitchWorkspace: {}", index);
                workspaces.switch_to(ws, config, index - 1, true);
            }
            Cmd::SwitchScreen(screen) => {
                debug!("Cmd::SwitchScreen: {}", screen);
                workspaces.switch_to_screen(ws, config, screen - 1);
            }
            Cmd::MoveToWorkspace(index) => {
                debug!("Cmd::MoveToWorkspace: {}", index);
                workspaces.move_window_to(ws, config, index - 1);
            }
            Cmd::MoveToScreen(screen) => {
                debug!("Cmd::MoveToScreen: {}", screen);
                workspaces.move_window_to_screen(ws, config, screen - 1);
            }
            Cmd::SendLayoutMsg(ref msg) => {
                debug!("Cmd::SendLayoutMsg::{:?}", msg);
                workspaces.current_mut().send_layout_message(msg.clone());
                workspaces.current().redraw(ws, config);
            }
            Cmd::NestLayout(layout_fn) => {
                let layout = layout_fn();
                debug!("Cmd::NestLayout: {}", layout.name());
                workspaces.current_mut().nest_layout(layout);
            }
            Cmd::Reload => {
                debug!("Cmd::Reload");
                reload(workspaces)
                    .context("failed to reload xr3wm")?;
            }
            Cmd::Exit => {
                debug!("Cmd::Exit");
                ws.close();
            }
            Cmd::KillClient => {
                if let Some(window) = workspaces.current().focused_window() {
                    debug!("Cmd::KillClient: {}", window);
                    ws.kill_window(window);
                }
            }
            Cmd::FocusUp => {
                if let Some(window) = workspaces.current().focused_window() {
                    debug!("Cmd::FocusUp: {}", window);
                    workspaces.current_mut().move_focus(ws, config, MoveOp::Up);
                }
            }
            Cmd::FocusDown => {
                if let Some(window) = workspaces.current().focused_window() {
                    debug!("Cmd::FocusDown: {}", window);
                    workspaces.current_mut().move_focus(ws, config, MoveOp::Down);
                }
            }
            Cmd::FocusMaster => {
                if let Some(window) = workspaces.current().focused_window() {
                    debug!("Cmd::FocusMaster: {}", window);
                    workspaces.current_mut().move_focus(ws, config, MoveOp::Swap);
                }
            }
            Cmd::FocusParentUp => {
                if let Some(window) = workspaces.current().focused_window() {
                    debug!("Cmd::FocusParentUp: {}", window);
                    workspaces.current_mut().move_parent_focus(ws, config, MoveOp::Up);
                }
            }
            Cmd::FocusParentDown => {
                if let Some(window) = workspaces.current().focused_window() {
                    debug!("Cmd::FocusParentDown: {}", window);
                    workspaces.current_mut().move_parent_focus(ws, config, MoveOp::Down);
                }
            }
            Cmd::FocusParentMaster => {
                if let Some(window) = workspaces.current().focused_window() {
                    debug!("Cmd::FocusParentMaster: {}", window);
                    workspaces.current_mut().move_parent_focus(ws, config, MoveOp::Swap);
                }
            }
            Cmd::SwapUp => {
                if let Some(window) = workspaces.current().focused_window() {
                    debug!("Cmd::SwapUp: {}", window);
                    workspaces.current_mut().move_window(ws, config, MoveOp::Up);
                }
            }
            Cmd::SwapDown => {
                if let Some(window) = workspaces.current().focused_window() {
                    debug!("Cmd::SwapDown: {}", window);
                    workspaces.current_mut().move_window(ws, config, MoveOp::Down);
                }
            }
            Cmd::SwapMaster => {
                if let Some(window) = workspaces.current().focused_window() {
                    debug!("Cmd::SwapMaster: {}", window);
                    workspaces.current_mut().move_window(ws, config, MoveOp::Swap);
                }
            }
            Cmd::SwapParentUp => {
                if let Some(window) = workspaces.current().focused_window() {
                    debug!("Cmd::SwapParentUp: {}", window);
                    workspaces.current_mut().move_parent_window(ws, config, MoveOp::Up);
                }
            }
            Cmd::SwapParentDown => {
                if let Some(window) = workspaces.current().focused_window() {
                    debug!("Cmd::SwapParentDown: {}", window);
                    workspaces.current_mut().move_parent_window(ws, config, MoveOp::Down);
                }
            }
            Cmd::SwapParentMaster => {
                if let Some(window) = workspaces.current().focused_window() {
                    debug!("Cmd::SwapParentMaster: {}", window);
                    workspaces.current_mut().move_parent_window(ws, config, MoveOp::Swap);
                }
            }
        }
        Ok(())
    }
}

fn reload(workspaces: &mut Workspaces) -> Result<()> {
    info!("recompiling...");

    let config_build_dir = concat!(env!("HOME"), "/.xr3wm/.build");
    let mut cmd = Command::new("cargo");

    let output = cmd.current_dir(&config_build_dir)
        .arg("build")
        .env("RUST_LOG", "none")
        .output()
        .context("failed to run cargo")?;

    if !output.status.success() {
        let stderr_msg = String::from_utf8(output.stderr)
            .context("failed to convert cargo stderr to UTF-8")?;
        bail!("failed to recompile: {}", stderr_msg)
    }

    debug!("Cmd::Reload: restarting xr3wm...");

    let path = Path::new(concat!(env!("HOME"), "/.xr3wm/.tmp"));

    // save current workspace states to restore on restart
    let file = OpenOptions::new()
        .create(true)
        .write(true)
        .truncate(true)
        .open(&path)
        .context("failed to open workspace state tmp file")?;

    serde_json::to_writer(file, workspaces)
        .context("failed to serialize workspace states")?;

    let mut args: Vec<*const libc::c_char> = env::args()
        .filter_map(|x| CString::new(x).ok())
        .map(|x| x.into_raw() as *const libc::c_char)
        .collect();
    args.push(null());

    unsafe {
        execvp(args[0] as *const libc::c_char, args.as_ptr());
        // execvp returns only if an error has occurred
        error!("failed to reload: {}", ::std::io::Error::last_os_error());
    }

    Ok(())
}

pub struct ManageHook {
    pub class_name: String,
    pub cmd: CmdManage,
}

pub enum CmdManage {
    Move(usize),
    Float,
    Fullscreen,
    Ignore,
}

impl CmdManage {
    pub fn call(&self,
                ws: &XlibWindowSystem,
                workspaces: &mut Workspaces,
                config: &Config,
                window: Window) {
        match *self {
            CmdManage::Move(index) => {
                debug!("CmdManage::Move: {}, {}", window, index);
                workspaces.add_window(Some(index - 1), ws, config, window);
            }
            CmdManage::Float => {
                debug!("CmdManage::Float");
                unimplemented!()
            }
            CmdManage::Fullscreen => {
                debug!("CmdManage::Fullscreen");
                unimplemented!()
            }
            CmdManage::Ignore => {
                debug!("CmdManage::Ignore");
                unimplemented!()
            }
        }
    }
}

fn exec(cmd: String) {
    thread::spawn(move || {
        let args: Vec<&str> = cmd[..].split(' ').collect();

        if !args.is_empty() {
            let mut cmd = Command::new(args[0]);

            if args.len() > 1 {
                cmd.args(&args[1..]);
            }

            match cmd.output() {
                Ok(_) => (),
                _ => panic!("failed to start \"{:?}\"", cmd),
            }
        }
    });
}
<commit_msg>Pass env vars to the new process on reload<commit_after>#![allow(dead_code)]

extern crate libc;

use crate::config::Config;
use crate::layout::{Layout, LayoutMsg};
use crate::xlib_window_system::XlibWindowSystem;
use crate::workspaces::Workspaces;
use crate::workspace::MoveOp;
use self::libc::execvpe;
use std::{env, iter, thread};
use std::ptr::null;
use std::ffi::CString;
use std::process::Command;
use std::path::Path;
use std::fs::OpenOptions;
use x11::xlib::Window;
use anyhow::{bail, Context, Result};

pub enum Cmd {
    Exec(String),
    SwitchWorkspace(usize),
    SwitchScreen(usize),
    MoveToWorkspace(usize),
    MoveToScreen(usize),
    SendLayoutMsg(LayoutMsg),
    NestLayout(Box<dyn Fn() -> Box<dyn Layout>>),
    Reload,
    Exit,
    KillClient,
    FocusParentUp,
    FocusParentDown,
    FocusParentMaster,
    FocusUp,
    FocusDown,
    FocusMaster,
    SwapUp,
    SwapDown,
    SwapMaster,
    SwapParentUp,
    SwapParentDown,
    SwapParentMaster,
}

impl Cmd {
    pub fn call(&self, ws: &XlibWindowSystem, workspaces: &mut Workspaces, config: &Config) -> Result<()> {
        match self {
            Cmd::Exec(ref cmd) => {
                debug!("Cmd::Exec: {}", cmd);
                exec(cmd.clone());
            }
            Cmd::SwitchWorkspace(index) => {
                debug!("Cmd::SwitchWorkspace: {}", index);
                workspaces.switch_to(ws, config, index - 1, true);
            }
            Cmd::SwitchScreen(screen) => {
                debug!("Cmd::SwitchScreen: {}", screen);
                workspaces.switch_to_screen(ws, config, screen - 1);
            }
            Cmd::MoveToWorkspace(index) => {
                debug!("Cmd::MoveToWorkspace: {}", index);
                workspaces.move_window_to(ws, config, index - 1);
            }
            Cmd::MoveToScreen(screen) => {
                debug!("Cmd::MoveToScreen: {}", screen);
                workspaces.move_window_to_screen(ws, config, screen - 1);
            }
            Cmd::SendLayoutMsg(ref msg) => {
                debug!("Cmd::SendLayoutMsg::{:?}", msg);
                workspaces.current_mut().send_layout_message(msg.clone());
                workspaces.current().redraw(ws, config);
            }
            Cmd::NestLayout(layout_fn) => {
                let layout = layout_fn();
                debug!("Cmd::NestLayout: {}", layout.name());
                workspaces.current_mut().nest_layout(layout);
            }
            Cmd::Reload => {
                debug!("Cmd::Reload");
                reload(workspaces)
                    .context("failed to reload xr3wm")?;
            }
            Cmd::Exit => {
                debug!("Cmd::Exit");
                ws.close();
            }
            Cmd::KillClient => {
                if let Some(window) = workspaces.current().focused_window() {
                    debug!("Cmd::KillClient: {}", window);
                    ws.kill_window(window);
                }
            }
            Cmd::FocusUp => {
                if let Some(window) = workspaces.current().focused_window() {
                    debug!("Cmd::FocusUp: {}", window);
                    workspaces.current_mut().move_focus(ws, config, MoveOp::Up);
                }
            }
            Cmd::FocusDown => {
                if let Some(window) = workspaces.current().focused_window() {
                    debug!("Cmd::FocusDown: {}", window);
                    workspaces.current_mut().move_focus(ws, config, MoveOp::Down);
                }
            }
            Cmd::FocusMaster => {
                if let Some(window) = workspaces.current().focused_window() {
                    debug!("Cmd::FocusMaster: {}", window);
                    workspaces.current_mut().move_focus(ws, config, MoveOp::Swap);
                }
            }
            Cmd::FocusParentUp => {
                if let Some(window) = workspaces.current().focused_window() {
                    debug!("Cmd::FocusParentUp: {}", window);
                    workspaces.current_mut().move_parent_focus(ws, config, MoveOp::Up);
                }
            }
            Cmd::FocusParentDown => {
                if let Some(window) = workspaces.current().focused_window() {
                    debug!("Cmd::FocusParentDown: {}", window);
                    workspaces.current_mut().move_parent_focus(ws, config, MoveOp::Down);
                }
            }
            Cmd::FocusParentMaster => {
                if let Some(window) = workspaces.current().focused_window() {
                    debug!("Cmd::FocusParentMaster: {}", window);
                    workspaces.current_mut().move_parent_focus(ws, config, MoveOp::Swap);
                }
            }
            Cmd::SwapUp => {
                if let Some(window) = workspaces.current().focused_window() {
                    debug!("Cmd::SwapUp: {}", window);
                    workspaces.current_mut().move_window(ws, config, MoveOp::Up);
                }
            }
            Cmd::SwapDown => {
                if let Some(window) = workspaces.current().focused_window() {
                    debug!("Cmd::SwapDown: {}", window);
                    workspaces.current_mut().move_window(ws, config, MoveOp::Down);
                }
            }
            Cmd::SwapMaster => {
                if let Some(window) = workspaces.current().focused_window() {
                    debug!("Cmd::SwapMaster: {}", window);
                    workspaces.current_mut().move_window(ws, config, MoveOp::Swap);
                }
            }
            Cmd::SwapParentUp => {
                if let Some(window) = workspaces.current().focused_window() {
                    debug!("Cmd::SwapParentUp: {}", window);
                    workspaces.current_mut().move_parent_window(ws, config, MoveOp::Up);
                }
            }
            Cmd::SwapParentDown => {
                if let Some(window) = workspaces.current().focused_window() {
                    debug!("Cmd::SwapParentDown: {}", window);
                    workspaces.current_mut().move_parent_window(ws, config, MoveOp::Down);
                }
            }
            Cmd::SwapParentMaster => {
                if let Some(window) = workspaces.current().focused_window() {
                    debug!("Cmd::SwapParentMaster: {}", window);
                    workspaces.current_mut().move_parent_window(ws, config, MoveOp::Swap);
                }
            }
        }
        Ok(())
    }
}

fn reload(workspaces: &Workspaces) -> Result<()> {
    info!("recompiling...");

    let config_build_dir = concat!(env!("HOME"), "/.xr3wm/.build");
    let mut cmd = Command::new("cargo");

    let output = cmd.current_dir(&config_build_dir)
        .arg("build")
        .env("RUST_LOG", "none")
        .output()
        .context("failed to run cargo")?;

    if !output.status.success() {
        let stderr_msg = String::from_utf8(output.stderr)
            .context("failed to convert cargo stderr to UTF-8")?;
        bail!("failed to recompile: {}", stderr_msg)
    }

    debug!("Cmd::Reload: restarting xr3wm...");

    let path = Path::new(concat!(env!("HOME"), "/.xr3wm/.tmp"));

    // save current workspace states to restore on restart
    let file = OpenOptions::new()
        .create(true)
        .write(true)
        .truncate(true)
        .open(&path)
        .context("failed to open workspace state tmp file")?;

    serde_json::to_writer(file, workspaces)
        .context("failed to serialize workspace states")?;

    let args: Vec<*const libc::c_char> = env::args()
        .filter_map(|x| CString::new(x).ok())
        .map(|x| x.into_raw() as *const libc::c_char)
        .chain(iter::once(null()))
        .collect();

    let envs: Vec<*const libc::c_char> = env::vars()
        .filter_map(|(k,v)| CString::new(format!("{}={}", k, v)).ok())
        .map(|x| x.into_raw() as *const libc::c_char)
        .chain(iter::once(null()))
        .collect();

    unsafe {
        execvpe(args[0] as *const libc::c_char, args.as_ptr(), envs.as_ptr());
        // execvp returns only if an error has occurred
        error!("failed to reload: {}", ::std::io::Error::last_os_error());
    }

    Ok(())
}

pub struct ManageHook {
    pub class_name: String,
    pub cmd: CmdManage,
}

pub enum CmdManage {
    Move(usize),
    Float,
    Fullscreen,
    Ignore,
}

impl CmdManage {
    pub fn call(&self,
                ws: &XlibWindowSystem,
                workspaces: &mut Workspaces,
                config: &Config,
                window: Window) {
        match *self {
            CmdManage::Move(index) => {
                debug!("CmdManage::Move: {}, {}", window, index);
                workspaces.add_window(Some(index - 1), ws, config, window);
            }
            CmdManage::Float => {
                debug!("CmdManage::Float");
                unimplemented!()
            }
            CmdManage::Fullscreen => {
                debug!("CmdManage::Fullscreen");
                unimplemented!()
            }
            CmdManage::Ignore => {
                debug!("CmdManage::Ignore");
                unimplemented!()
            }
        }
    }
}

fn exec(cmd: String) {
    thread::spawn(move || {
        let args: Vec<&str> = cmd[..].split(' ').collect();

        if !args.is_empty() {
            let mut cmd = Command::new(args[0]);

            if args.len() > 1 {
                cmd.args(&args[1..]);
            }

            match cmd.output() {
                Ok(_) => (),
                _ => panic!("failed to start \"{:?}\"", cmd),
            }
        }
    });
}
<|endoftext|>


<commit_before>extern crate glium;
extern crate image;

use glium::{DisplayBuild, VertexBuffer, Program, DrawParameters, Display, Surface};
use glium::texture::Texture2d;
use glium::index::NoIndices;

use std::path::Path;
use std::ops::{Deref, DerefMut};

use super::{DrawResult, TextureResult};

#[derive(Copy, Clone)]
struct Vertex {
    position  : [f32; 2],
    tex_coords: [f32; 2]
}

implement_vertex!(Vertex, position, tex_coords);

impl Vertex{
    #[inline]
    fn new(position: [f32; 2], tex_coords: [f32; 2]) -> Self{
        Vertex{
            position  : position,
            tex_coords: tex_coords,
        }
    }
}

type VertexBuffers = [VertexBuffer<Vertex>; 2];

/// A 2D texture that is ready to be drawn
// NOTE Size: 1 696 bytes
pub struct Texture{
    tex: Texture2d,
    vertex_buffers: VertexBuffers,
}

impl Texture {
    #[inline]
    fn from_png_bytes(display: &Display, bytes: &[u8]) -> TextureResult<Texture>{
        Texture::new(display,
            try!(
                image::load_from_memory_with_format(bytes, image::PNG)
            ).to_rgba()
        )
    }
    #[inline]
    fn from_file<P: AsRef<Path>>(display: &Display, path: P) -> TextureResult<Texture>{
        Texture::new(display,
            try!(
                image::open(path)
            ).to_rgba()
        )
    }

    fn new(display: &Display, image: image::RgbaImage) -> TextureResult<Texture>{
        let (width, height) = image.dimensions();
        let image = glium::texture::RawImage2d::from_raw_rgba_reversed(image.into_raw(), (width, height));

        let (w, h) = (width as f32 / 2.0, height as f32 / 2.0);

        let v1 = Vertex::new([-w, -h], [0.0, 0.0]);
        let v2 = Vertex::new([ w, -h], [1.0, 0.0]);
        let v3 = Vertex::new([ w,  h], [1.0, 1.0]);
        let v4 = Vertex::new([-w,  h], [0.0, 1.0]);

        Ok(Texture {
            tex: try!(Texture2d::new(display, image)),
            vertex_buffers: [try!(VertexBuffer::new(display, &[v1, v2, v4])), try!(VertexBuffer::new(display, &[v2, v3, v4]))],
        })
    }
}

/// Loads a texture, by loading the bytes at compile-time
#[macro_export]
macro_rules! include_texture {
    ($draw:expr, $texture:tt) => {
        $draw.load_texture_from_bytes(include_bytes!($texture))
    };
}

/// Contains the display and handles most of the graphics
pub struct Graphics<'a> {
    display: Display,
    program: Program,
    h_size : (f32, f32),
    params : DrawParameters<'a>
}

const INDICES: NoIndices = NoIndices(glium::index::PrimitiveType::TrianglesList);

impl<'a> Graphics<'a> {
    /// Creates a new `Graphics` from a `Display` made using the arguments
    pub fn new(title: &str, width: u32, height: u32) -> Self {
        Self::from_display(
            glium::glutin::WindowBuilder::new()
                .with_title(title.to_string())
                .with_dimensions(width, height)
                .with_vsync()
                .build_glium().expect("Failed to build the window")
        )
    }

    /// Creates a new `Graphics` instance using the given display
    pub fn from_display(display: Display) -> Self {
        let (w, h) = display.get_window().unwrap().get_inner_size().unwrap();
        let (w, h) = (w as f32 / 2.0, h as f32 / 2.0);

        let vertex_shader_src = &r#"
            #version 140

            in vec2 position;
            in vec2 tex_coords;
            out vec2 v_tex_coords;

            uniform mat4 matrix;

            void main() {
                v_tex_coords = tex_coords;

                vec4 pos = matrix * vec4(position, 0.0, 1.0);

                pos.x /= $width;
                pos.y /= $height;

                gl_Position = pos;
            }
        "#.replace("$width", &w.to_string()).replace("$height", &h.to_string());
        let fragment_shader_src = r#"
            #version 140

            in vec2 v_tex_coords;
            out vec4 color;

            uniform sampler2D tex;

            void main() {
                color = texture(tex, v_tex_coords);
            }
        "#;

        let params = DrawParameters{
            blend : glium::Blend::alpha_blending(),
            .. Default::default()
        };

        Graphics{
            // Unwrap should be safe
            program: Program::from_source(&display, vertex_shader_src, fragment_shader_src, None).unwrap(),
            display: display,
            params : params,
            h_size : (w, h)
        }
    }

    #[inline]
    /// Returns half of the size of the window
    pub fn get_h_size(&self) -> (f32, f32){
        self.h_size
    }

    #[inline]
    /// Returns a `Texture` created from a PNG-encoded byte slice
    pub fn load_texture_from_bytes(&self, bytes: &[u8]) -> TextureResult<Texture> {
        Texture::from_png_bytes(&self.display, bytes)
    }

    #[inline]
    /// Returns a `Texture` created from a file
    pub fn load_texture_from_file<P: AsRef<Path>>(&self, path: P) -> TextureResult<Texture> {
        Texture::from_file(&self.display, path)
    }
}

fn draw(target: &mut glium::Frame, graphics: &Graphics, texture: &Texture, matrix: [[f32; 4]; 4]) -> DrawResult<()>{
    let uniforms = uniform! {
        tex   : &texture.tex,
        matrix: matrix
    };

    for vertex_buffer in &texture.vertex_buffers{
        try!(target.draw(vertex_buffer, INDICES, &graphics.program, &uniforms, &graphics.params));
    }

    Ok(())
}

impl<'a> Deref for Graphics<'a>{
    type Target = Display;

    #[inline]
    fn deref(&self) -> &Display{
        &self.display
    }
}

/// Provides functionality for drawing.
/// Can also be dereferenced into a `glium::Frame`.
pub struct Drawer<'a>{
    target: glium::Frame,
    /// Reference to the draw instance
    pub graphics: &'a Graphics<'a>
}

impl<'a> Drawer<'a>{
    #[inline]
    /// Creates a new `Drawer` to draw next frame
    pub fn new(graphics: &'a Graphics<'a>) -> Self{
        let target = graphics.draw();
        Drawer{
            target: target,
            graphics: graphics
        }
    }

    #[inline]
    /// Clears the screen with the specified colour
    pub fn clear(&mut self, red: f32, green: f32, blue: f32){
        self.clear_color(red, green, blue, 1.)
    }

    /// Draws a texture onto the screen
    pub fn draw_texture(&mut self, texture: &Texture, x: f32, y: f32, rotation: f32) -> DrawResult<()>{
        let (sin, cos)  = rotation.sin_cos();

        let matrix = [
            [ cos, sin, 0.0, 0.0],
            [-sin, cos, 0.0, 0.0],
            [ 0.0, 0.0, 1.0, 0.0],
            [   x,   y, 0.0, 1.0],
        ];

        draw(self, self.graphics, texture, matrix)
    }

    /// Draws a texture onto the screen without rotation
    pub fn draw_texture_rigid(&mut self, texture: &Texture, x: f32, y: f32) -> DrawResult<()>{
        let matrix = [
            [1.0, 0.0, 0.0, 0.0],
            [0.0, 1.0, 0.0, 0.0],
            [0.0, 0.0, 1.0, 0.0],
            [  x,   y, 0.0, 1.0],
        ];

        draw(self, self.graphics, texture, matrix)
    }
}

impl<'a> Deref for Drawer<'a>{
    type Target = glium::Frame;
    #[inline]
    fn deref(&self) -> &glium::Frame{
        &self.target
    }
}

impl<'a> DerefMut for Drawer<'a>{
    #[inline]
    fn deref_mut(&mut self) -> &mut glium::Frame{
        &mut self.target
    }
}

impl<'a> Drop for Drawer<'a>{
    #[inline]
    fn drop(&mut self){
        self.target.set_finish().unwrap()
    }
}

/// Descibes objects that can be drawn to the screen
pub trait Draw {
    /// Draws itself to the screen
    fn draw(&self, &mut Drawer) -> DrawResult<()>;
}
<commit_msg>Only use one draw call when drawing a texture<commit_after>extern crate glium;
extern crate image;

use glium::{DisplayBuild, VertexBuffer, Program, DrawParameters, Display, Surface};
use glium::texture::Texture2d;
use glium::IndexBuffer;

use std::path::Path;
use std::ops::{Deref, DerefMut};

use super::{DrawResult, TextureResult};

#[derive(Copy, Clone)]
struct Vertex {
    position  : [f32; 2],
    tex_coords: [f32; 2]
}

implement_vertex!(Vertex, position, tex_coords);

impl Vertex{
    #[inline]
    fn new(position: [f32; 2], tex_coords: [f32; 2]) -> Self{
        Vertex{
            position  : position,
            tex_coords: tex_coords,
        }
    }
}

/// A 2D texture that is ready to be drawn
pub struct Texture{
    tex: Texture2d,
    vertex_buffer: VertexBuffer<Vertex>,
}

impl Texture {
    #[inline]
    fn from_png_bytes(display: &Display, bytes: &[u8]) -> TextureResult<Texture>{
        Texture::new(display,
            try!(
                image::load_from_memory_with_format(bytes, image::PNG)
            ).to_rgba()
        )
    }
    #[inline]
    fn from_file<P: AsRef<Path>>(display: &Display, path: P) -> TextureResult<Texture>{
        Texture::new(display,
            try!(
                image::open(path)
            ).to_rgba()
        )
    }

    fn new(display: &Display, image: image::RgbaImage) -> TextureResult<Texture>{
        let (width, height) = image.dimensions();
        let image = glium::texture::RawImage2d::from_raw_rgba_reversed(image.into_raw(), (width, height));

        let (w, h) = (width as f32 / 2.0, height as f32 / 2.0);

        let vb = try!(VertexBuffer::new(display, &[
            Vertex::new([-w, -h], [0.0, 0.0]),
            Vertex::new([ w, -h], [1.0, 0.0]),
            Vertex::new([ w,  h], [1.0, 1.0]),
            Vertex::new([-w,  h], [0.0, 1.0])
        ]));

        Ok(Texture {
            tex: try!(Texture2d::new(display, image)),
            vertex_buffer: vb,
        })
    }
}

/// Loads a texture, by loading the bytes at compile-time
#[macro_export]
macro_rules! include_texture {
    ($draw:expr, $texture:tt) => {
        $draw.load_texture_from_bytes(include_bytes!($texture))
    };
}

/// Contains the display and handles most of the graphics
pub struct Graphics<'a> {
    display: Display,
    program: Program,
    h_size : (f32, f32),
    indices: IndexBuffer<u8>,
    params : DrawParameters<'a>
}

impl<'a> Graphics<'a> {
    /// Creates a new `Graphics` from a `Display` made using the arguments
    pub fn new(title: &str, width: u32, height: u32) -> Self {
        Self::from_display(
            glium::glutin::WindowBuilder::new()
                .with_title(title.to_string())
                .with_dimensions(width, height)
                .with_vsync()
                .build_glium().expect("Failed to build the window")
        )
    }

    /// Creates a new `Graphics` instance using the given display
    pub fn from_display(display: Display) -> Self {
        let (w, h) = display.get_window().unwrap().get_inner_size().unwrap();
        let (w, h) = (w as f32 / 2.0, h as f32 / 2.0);

        let vertex_shader_src = &r#"
            #version 140

            in vec2 position;
            in vec2 tex_coords;
            out vec2 v_tex_coords;

            uniform mat4 matrix;

            void main() {
                v_tex_coords = tex_coords;

                vec4 pos = matrix * vec4(position, 0.0, 1.0);

                pos.x /= $width;
                pos.y /= $height;

                gl_Position = pos;
            }
        "#.replace("$width", &w.to_string()).replace("$height", &h.to_string());
        let fragment_shader_src = r#"
            #version 140

            in vec2 v_tex_coords;
            out vec4 color;

            uniform sampler2D tex;

            void main() {
                color = texture(tex, v_tex_coords);
            }
        "#;

        let params = DrawParameters{
            blend : glium::Blend::alpha_blending(),
            .. Default::default()
        };

        let indices = IndexBuffer::new(&display, glium::index::PrimitiveType::TriangleStrip, &[0u8, 1, 3, 2]).unwrap();

        Graphics{
            // Unwrap should be safe
            program: Program::from_source(&display, vertex_shader_src, fragment_shader_src, None).unwrap(),
            display: display,
            params : params,
            indices: indices,
            h_size : (w, h)
        }
    }

    #[inline]
    /// Returns half of the size of the window
    pub fn get_h_size(&self) -> (f32, f32){
        self.h_size
    }

    #[inline]
    /// Returns a `Texture` created from a PNG-encoded byte slice
    pub fn load_texture_from_bytes(&self, bytes: &[u8]) -> TextureResult<Texture> {
        Texture::from_png_bytes(&self.display, bytes)
    }

    #[inline]
    /// Returns a `Texture` created from a file
    pub fn load_texture_from_file<P: AsRef<Path>>(&self, path: P) -> TextureResult<Texture> {
        Texture::from_file(&self.display, path)
    }
}

fn draw(target: &mut glium::Frame, graphics: &Graphics, texture: &Texture, matrix: [[f32; 4]; 4]) -> DrawResult<()>{
    let uniforms = uniform! {
        tex   : &texture.tex,
        matrix: matrix
    };

    target.draw(&texture.vertex_buffer, &graphics.indices, &graphics.program, &uniforms, &graphics.params)
}

impl<'a> Deref for Graphics<'a>{
    type Target = Display;

    #[inline]
    fn deref(&self) -> &Display{
        &self.display
    }
}

/// Provides functionality for drawing.
/// Can also be dereferenced into a `glium::Frame`.
pub struct Drawer<'a>{
    target: glium::Frame,
    /// Reference to the draw instance
    pub graphics: &'a Graphics<'a>
}

impl<'a> Drawer<'a>{
    #[inline]
    /// Creates a new `Drawer` to draw next frame
    pub fn new(graphics: &'a Graphics<'a>) -> Self{
        let target = graphics.draw();
        Drawer{
            target: target,
            graphics: graphics
        }
    }

    #[inline]
    /// Clears the screen with the specified colour
    pub fn clear(&mut self, red: f32, green: f32, blue: f32){
        self.clear_color(red, green, blue, 1.)
    }

    /// Draws a texture onto the screen
    pub fn draw_texture(&mut self, texture: &Texture, x: f32, y: f32, rotation: f32) -> DrawResult<()>{
        let (sin, cos)  = rotation.sin_cos();

        let matrix = [
            [ cos, sin, 0.0, 0.0],
            [-sin, cos, 0.0, 0.0],
            [ 0.0, 0.0, 1.0, 0.0],
            [   x,   y, 0.0, 1.0],
        ];

        draw(self, self.graphics, texture, matrix)
    }

    /// Draws a texture onto the screen without rotation
    pub fn draw_texture_rigid(&mut self, texture: &Texture, x: f32, y: f32) -> DrawResult<()>{
        let matrix = [
            [1.0, 0.0, 0.0, 0.0],
            [0.0, 1.0, 0.0, 0.0],
            [0.0, 0.0, 1.0, 0.0],
            [  x,   y, 0.0, 1.0],
        ];

        draw(self, self.graphics, texture, matrix)
    }
}

impl<'a> Deref for Drawer<'a>{
    type Target = glium::Frame;
    #[inline]
    fn deref(&self) -> &glium::Frame{
        &self.target
    }
}

impl<'a> DerefMut for Drawer<'a>{
    #[inline]
    fn deref_mut(&mut self) -> &mut glium::Frame{
        &mut self.target
    }
}

impl<'a> Drop for Drawer<'a>{
    #[inline]
    fn drop(&mut self){
        self.target.set_finish().unwrap()
    }
}

/// Descibes objects that can be drawn to the screen
pub trait Draw {
    /// Draws itself to the screen
    fn draw(&self, &mut Drawer) -> DrawResult<()>;
}
<|endoftext|>


<commit_before>extern crate rusty_collaborative_filter as rcf;

use rcf::math::linalg::matrix::Matrix;
use rcf::math::linalg::vector::Vector;

#[test]
fn create_mat_new() {
	let a = Matrix::new(4, 3, vec![0.0; 12]);

	assert_eq!(a.rows, 4);
	assert_eq!(a.cols, 3);
}

#[test]
fn create_mat_identity() {
	let a = Matrix::identity(4);

	assert_eq!(a.rows, 4);
	assert_eq!(a.cols, 4);

	assert_eq!(a[[0,0]], 1.0);
	assert_eq!(a[[1,1]], 1.0);
	assert_eq!(a[[2,2]], 1.0);
	assert_eq!(a[[3,3]], 1.0);

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

#[test]
fn create_mat_diag() {
	let a = Matrix::from_diag(&[1.0,2.0,3.0,4.0]);

	assert_eq!(a.rows, 4);
	assert_eq!(a.cols, 4);

	assert_eq!(a[[0,0]], 1.0);
	assert_eq!(a[[1,1]], 2.0);
	assert_eq!(a[[2,2]], 3.0);
	assert_eq!(a[[3,3]], 4.0);

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

#[test]
fn transpose_mat() {
	let a = Matrix::new(5, 2, vec![1.,2.,3.,4.,5.,6.,7.,8.,9.,10.]);

	let c = a.transpose();

	assert_eq!(c.cols, a.rows);
	assert_eq!(c.rows, a.cols);

	assert_eq!(a[[0,0]], c[[0,0]]);
	assert_eq!(a[[1,0]], c[[0,1]]);
	assert_eq!(a[[2,0]], c[[0,2]]);
	assert_eq!(a[[3,0]], c[[0,3]]);
	assert_eq!(a[[4,0]], c[[0,4]]);
	assert_eq!(a[[0,1]], c[[1,0]]);
	assert_eq!(a[[1,1]], c[[1,1]]);
	assert_eq!(a[[2,1]], c[[1,2]]);
	assert_eq!(a[[3,1]], c[[1,3]]);
	assert_eq!(a[[4,1]], c[[1,4]]);

}

#[test]
fn indexing_mat() {
	let a = Matrix::new(3, 2, vec![1.,2.,3.,4.,5.,6.]);

	assert_eq!(a[[0,0]], 1.0);
	assert_eq!(a[[0,1]], 2.0);
	assert_eq!(a[[1,0]], 3.0);
	assert_eq!(a[[1,1]], 4.0);
	assert_eq!(a[[2,0]], 5.0);
	assert_eq!(a[[2,1]], 6.0);
}

#[test]
fn matrix_mul() {
	let a = Matrix::new(3, 2, vec![1.,2.,3.,4.,5.,6.]);
	let b = Matrix::new(2, 3, vec![1.,2.,3.,4.,5.,6.]);

	let c = a * b;

	assert_eq!(c.rows, 3);
	assert_eq!(c.cols, 3);

	assert_eq!(c[[0,0]], 9.0);
	assert_eq!(c[[0,1]], 12.0);
	assert_eq!(c[[0,2]], 15.0);
	assert_eq!(c[[1,0]], 19.0);
	assert_eq!(c[[1,1]], 26.0);
	assert_eq!(c[[1,2]], 33.0);
	assert_eq!(c[[2,0]], 29.0);
	assert_eq!(c[[2,1]], 40.0);
	assert_eq!(c[[2,2]], 51.0);
}

#[test]
fn matrix_vec_mul() {
	let a = Matrix::new(3, 2, vec![1.,2.,3.,4.,5.,6.]);
	let b = Vector::new(2, vec![4.,7.]);

	let c = a * b;

	assert_eq!(c.size, 3);

	assert_eq!(c[0], 18.0);
	assert_eq!(c[1], 40.0);
	assert_eq!(c[2], 62.0);
}

#[test]
fn matrix_f32_mul() {
	let a = Matrix::new(3, 2, vec![1.,2.,3.,4.,5.,6.]);

	let c = a * 2.0;

	assert_eq!(c[[0,0]], 2.0);
	assert_eq!(c[[0,1]], 4.0);
	assert_eq!(c[[1,0]], 6.0);
	assert_eq!(c[[1,1]], 8.0);
	assert_eq!(c[[2,0]], 10.0);
	assert_eq!(c[[2,1]], 12.0);
}

#[test]
fn matrix_add() {
	let a = Matrix::new(3, 2, vec![1.,2.,3.,4.,5.,6.]);
	let b = Matrix::new(3, 2, vec![2.,3.,4.,5.,6.,7.]);

	let c = a + b;

	assert_eq!(c[[0,0]], 3.0);
	assert_eq!(c[[0,1]], 5.0);
	assert_eq!(c[[1,0]], 7.0);
	assert_eq!(c[[1,1]], 9.0);
	assert_eq!(c[[2,0]], 11.0);
	assert_eq!(c[[2,1]], 13.0);
}

#[test]
fn matrix_f32_add() {
	let a = Matrix::new(3, 2, vec![1.,2.,3.,4.,5.,6.]);
	let b = 3.0;

	let c = a + b;

	assert_eq!(c[[0,0]], 4.0);
	assert_eq!(c[[0,1]], 5.0);
	assert_eq!(c[[1,0]], 6.0);
	assert_eq!(c[[1,1]], 7.0);
	assert_eq!(c[[2,0]], 8.0);
	assert_eq!(c[[2,1]], 9.0);
}

#[test]
fn matrix_sub() {
	let a = Matrix::new(3, 2, vec![1.,2.,3.,4.,5.,6.]);
	let b = Matrix::new(3, 2, vec![2.,3.,4.,5.,6.,7.]);

	let c = a - b;

	assert_eq!(c[[0,0]], -1.0);
	assert_eq!(c[[0,1]], -1.0);
	assert_eq!(c[[1,0]], -1.0);
	assert_eq!(c[[1,1]], -1.0);
	assert_eq!(c[[2,0]], -1.0);
	assert_eq!(c[[2,1]], -1.0);
}

#[test]
fn matrix_f32_sub() {
	let a = Matrix::new(3, 2, vec![1.,2.,3.,4.,5.,6.]);
	let b = 3.0;

	let c = a - b;

	assert_eq!(c[[0,0]], -2.0);
	assert_eq!(c[[0,1]], -1.0);
	assert_eq!(c[[1,0]], 0.0);
	assert_eq!(c[[1,1]], 1.0);
	assert_eq!(c[[2,0]], 2.0);
	assert_eq!(c[[2,1]], 3.0);
}

#[test]
fn matrix_f32_div() {
	let a = Matrix::new(3, 2, vec![1.,2.,3.,4.,5.,6.]);
	let b = 3.0;

	let c = a / b;

	assert_eq!(c[[0,0]], 1.0/3.0);
	assert_eq!(c[[0,1]], 2.0/3.0);
	assert_eq!(c[[1,0]], 1.0);
	assert_eq!(c[[1,1]], 4.0/3.0);
	assert_eq!(c[[2,0]], 5.0/3.0);
	assert_eq!(c[[2,1]], 2.0);
}<commit_msg>Updating to use new vector creation function.<commit_after>extern crate rusty_collaborative_filter as rcf;

use rcf::math::linalg::matrix::Matrix;
use rcf::math::linalg::vector::Vector;

#[test]
fn create_mat_new() {
	let a = Matrix::new(4, 3, vec![0.0; 12]);

	assert_eq!(a.rows, 4);
	assert_eq!(a.cols, 3);
}

#[test]
fn create_mat_zeros() {
	let a = Matrix::zeros(10, 10);

	assert_eq!(a.rows, 10);
	assert_eq!(a.cols, 10);

	for i in 0..10
	{
		for j in 0..10
		{
			assert_eq!(a[[i,j]], 0.0);
		}
	}
}

#[test]
fn create_mat_identity() {
	let a = Matrix::identity(4);

	assert_eq!(a.rows, 4);
	assert_eq!(a.cols, 4);

	assert_eq!(a[[0,0]], 1.0);
	assert_eq!(a[[1,1]], 1.0);
	assert_eq!(a[[2,2]], 1.0);
	assert_eq!(a[[3,3]], 1.0);

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

#[test]
fn create_mat_diag() {
	let a = Matrix::from_diag(&[1.0,2.0,3.0,4.0]);

	assert_eq!(a.rows, 4);
	assert_eq!(a.cols, 4);

	assert_eq!(a[[0,0]], 1.0);
	assert_eq!(a[[1,1]], 2.0);
	assert_eq!(a[[2,2]], 3.0);
	assert_eq!(a[[3,3]], 4.0);

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

#[test]
fn transpose_mat() {
	let a = Matrix::new(5, 2, vec![1.,2.,3.,4.,5.,6.,7.,8.,9.,10.]);

	let c = a.transpose();

	assert_eq!(c.cols, a.rows);
	assert_eq!(c.rows, a.cols);

	assert_eq!(a[[0,0]], c[[0,0]]);
	assert_eq!(a[[1,0]], c[[0,1]]);
	assert_eq!(a[[2,0]], c[[0,2]]);
	assert_eq!(a[[3,0]], c[[0,3]]);
	assert_eq!(a[[4,0]], c[[0,4]]);
	assert_eq!(a[[0,1]], c[[1,0]]);
	assert_eq!(a[[1,1]], c[[1,1]]);
	assert_eq!(a[[2,1]], c[[1,2]]);
	assert_eq!(a[[3,1]], c[[1,3]]);
	assert_eq!(a[[4,1]], c[[1,4]]);

}

#[test]
fn indexing_mat() {
	let a = Matrix::new(3, 2, vec![1.,2.,3.,4.,5.,6.]);

	assert_eq!(a[[0,0]], 1.0);
	assert_eq!(a[[0,1]], 2.0);
	assert_eq!(a[[1,0]], 3.0);
	assert_eq!(a[[1,1]], 4.0);
	assert_eq!(a[[2,0]], 5.0);
	assert_eq!(a[[2,1]], 6.0);
}

#[test]
fn matrix_mul() {
	let a = Matrix::new(3, 2, vec![1.,2.,3.,4.,5.,6.]);
	let b = Matrix::new(2, 3, vec![1.,2.,3.,4.,5.,6.]);

	let c = a * b;

	assert_eq!(c.rows, 3);
	assert_eq!(c.cols, 3);

	assert_eq!(c[[0,0]], 9.0);
	assert_eq!(c[[0,1]], 12.0);
	assert_eq!(c[[0,2]], 15.0);
	assert_eq!(c[[1,0]], 19.0);
	assert_eq!(c[[1,1]], 26.0);
	assert_eq!(c[[1,2]], 33.0);
	assert_eq!(c[[2,0]], 29.0);
	assert_eq!(c[[2,1]], 40.0);
	assert_eq!(c[[2,2]], 51.0);
}

#[test]
fn matrix_vec_mul() {
	let a = Matrix::new(3, 2, vec![1.,2.,3.,4.,5.,6.]);
	let b = Vector::new(vec![4.,7.]);

	let c = a * b;

	assert_eq!(c.size, 3);

	assert_eq!(c[0], 18.0);
	assert_eq!(c[1], 40.0);
	assert_eq!(c[2], 62.0);
}

#[test]
fn matrix_f32_mul() {
	let a = Matrix::new(3, 2, vec![1.,2.,3.,4.,5.,6.]);

	let c = a * 2.0;

	assert_eq!(c[[0,0]], 2.0);
	assert_eq!(c[[0,1]], 4.0);
	assert_eq!(c[[1,0]], 6.0);
	assert_eq!(c[[1,1]], 8.0);
	assert_eq!(c[[2,0]], 10.0);
	assert_eq!(c[[2,1]], 12.0);
}

#[test]
fn matrix_add() {
	let a = Matrix::new(3, 2, vec![1.,2.,3.,4.,5.,6.]);
	let b = Matrix::new(3, 2, vec![2.,3.,4.,5.,6.,7.]);

	let c = a + b;

	assert_eq!(c[[0,0]], 3.0);
	assert_eq!(c[[0,1]], 5.0);
	assert_eq!(c[[1,0]], 7.0);
	assert_eq!(c[[1,1]], 9.0);
	assert_eq!(c[[2,0]], 11.0);
	assert_eq!(c[[2,1]], 13.0);
}

#[test]
fn matrix_f32_add() {
	let a = Matrix::new(3, 2, vec![1.,2.,3.,4.,5.,6.]);
	let b = 3.0;

	let c = a + b;

	assert_eq!(c[[0,0]], 4.0);
	assert_eq!(c[[0,1]], 5.0);
	assert_eq!(c[[1,0]], 6.0);
	assert_eq!(c[[1,1]], 7.0);
	assert_eq!(c[[2,0]], 8.0);
	assert_eq!(c[[2,1]], 9.0);
}

#[test]
fn matrix_sub() {
	let a = Matrix::new(3, 2, vec![1.,2.,3.,4.,5.,6.]);
	let b = Matrix::new(3, 2, vec![2.,3.,4.,5.,6.,7.]);

	let c = a - b;

	assert_eq!(c[[0,0]], -1.0);
	assert_eq!(c[[0,1]], -1.0);
	assert_eq!(c[[1,0]], -1.0);
	assert_eq!(c[[1,1]], -1.0);
	assert_eq!(c[[2,0]], -1.0);
	assert_eq!(c[[2,1]], -1.0);
}

#[test]
fn matrix_f32_sub() {
	let a = Matrix::new(3, 2, vec![1.,2.,3.,4.,5.,6.]);
	let b = 3.0;

	let c = a - b;

	assert_eq!(c[[0,0]], -2.0);
	assert_eq!(c[[0,1]], -1.0);
	assert_eq!(c[[1,0]], 0.0);
	assert_eq!(c[[1,1]], 1.0);
	assert_eq!(c[[2,0]], 2.0);
	assert_eq!(c[[2,1]], 3.0);
}

#[test]
fn matrix_f32_div() {
	let a = Matrix::new(3, 2, vec![1.,2.,3.,4.,5.,6.]);
	let b = 3.0;

	let c = a / b;

	assert_eq!(c[[0,0]], 1.0/3.0);
	assert_eq!(c[[0,1]], 2.0/3.0);
	assert_eq!(c[[1,0]], 1.0);
	assert_eq!(c[[1,1]], 4.0/3.0);
	assert_eq!(c[[2,0]], 5.0/3.0);
	assert_eq!(c[[2,1]], 2.0);
}<|endoftext|>