<commit_before>// Lumol, an extensible molecular simulation engine
// Copyright (C) 2015-2016 G. Fraux — BSD license

//! Multi-dimmensional arrays based on ndarray
use ndarray::{Array, Ix};

use std::ops::{Index, IndexMut};
use std::cmp::PartialEq;
use types::Zero;

/// Two dimmensional tensors, based on ndarray.
///
/// Most of the methods are simply forwarded to ndarray, so also look the doc
/// for this crate.
#[derive(Debug, Clone)]
pub struct Array2<T>(Array<T, (Ix, Ix)>);

impl<T: Zero + Clone> Array2<T> {
    /// Create a new `Array2` of the specified `size` filled with the
    /// `Zero::zero` return value.
    pub fn zeros(size: (Ix, Ix)) -> Array2<T> {
        Array2(Array::<T, (Ix, Ix)>::zeros(size))
    }

    /// Resize the array if the current size is not `size`, and fill the
    /// new array with zeros.
    pub fn resize_if_different(&mut self, size: (Ix, Ix)) {
        if self.0.shape() != &[size.0, size.1] {
            *self = Array2::zeros(size);
        }
    }
}

impl<T> Array2<T> {
    /// Get the shape of the array
    pub fn shape(&self) -> (Ix, Ix) {
        let shape = self.0.shape();
        (shape[0], shape[1])
    }
}

impl<T: Clone> Array2<T> {
    /// Assign the given scalar to all entry in this array
    pub fn assign(&mut self, value: T) {
        self.0.assign_scalar(&value);
    }
}

impl<T: Default> Array2<T> {
    /// Create a new `Array2` of the specified `size` filled with the
    /// `Default::default` return value.
    pub fn default(size: (Ix, Ix)) -> Array2<T>{
        Array2(Array::<T, (Ix, Ix)>::default(size))
    }
}

impl<T: PartialEq> PartialEq for Array2<T> {
    fn eq(&self, other: &Array2<T>) -> bool {
        self == other
    }
}

impl<T> Index<(Ix, Ix)> for Array2<T> {
    type Output = T;
    fn index(&self, index: (Ix, Ix)) -> &T {
        unsafe {
            // ndarray does the check for us in debug builds
            self.0.uget(index)
        }
    }
}

impl<T> IndexMut<(Ix, Ix)> for Array2<T> {
    fn index_mut(&mut self, index: (Ix, Ix)) -> &mut T {
        unsafe {
            // ndarray does the check for us in debug builds
            self.0.uget_mut(index)
        }
    }
}

/******************************************************************************/

/// Three dimmensional tensors, based on ndarray
///
/// Most of the methods are simply forwarded to ndarray, so also look the doc
/// for this crate.
#[derive(Debug, Clone)]
pub struct Array3<T>(Array<T, (Ix, Ix, Ix)>);

impl<T: Zero + Clone> Array3<T> {
    /// Create a new `Array3` of the specified `size` filled with the
    /// `Zero::zero` return value.
    pub fn zeros(size: (Ix, Ix, Ix)) -> Array3<T> {
        Array3(Array::<T, (Ix, Ix, Ix)>::zeros(size))
    }

    /// Resize the array if the current size is not `size`, and fill the
    /// new array with zeros.
    pub fn resize_if_different(&mut self, size: (Ix, Ix, Ix)) {
        if self.0.shape() != &[size.0, size.1, size.2] {
            *self = Array3::zeros(size);
        }
    }
}

impl<T> Array3<T> {
    /// Get the shape of the array
    pub fn shape(&self) -> (Ix, Ix, Ix) {
        let shape = self.0.shape();
        (shape[0], shape[1], shape[2])
    }
}

impl<T: Clone> Array3<T> {
    /// Assign the given scalar to all entry in this array
    pub fn assign(&mut self, value: T) {
        self.0.assign_scalar(&value);
    }
}

impl<T: Default> Array3<T> {
    /// Create a new `Array3` of the specified `size` filled with the
    /// `Default::default` return value.
    pub fn default(size: (Ix, Ix, Ix)) -> Array3<T>{
        Array3(Array::<T, (Ix, Ix, Ix)>::default(size))
    }
}

impl<T> Index<(Ix, Ix, Ix)> for Array3<T> {
    type Output = T;
    fn index(&self, index: (Ix, Ix, Ix)) -> &T {
        unsafe {
            // ndarray does the check for us in debug builds
            self.0.uget(index)
        }
    }
}

impl<T> IndexMut<(Ix, Ix, Ix)> for Array3<T> {
    fn index_mut(&mut self, index: (Ix, Ix, Ix)) -> &mut T {
        unsafe {
            // ndarray does the check for us in debug builds
            self.0.uget_mut(index)
        }
    }
}

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

        #[test]
        fn zeros() {
            let a: Array2<f64> = Array2::zeros((3, 4));
            for i in 0..3 {
                for j in 0..4 {
                    assert_eq!(a[(i, j)], 0.0);
                }
            }
        }

        #[test]
        fn default() {
            #[derive(Clone)] struct F64(f64);
            impl Default for F64 {fn default() -> F64 { F64(42.0) }}

            let a: Array2<F64> = Array2::default((3, 4));
            for i in 0..3 {
                for j in 0..4 {
                    assert_eq!(a[(i, j)].0, 42.0);
                }
            }
        }

        #[test]
        fn resize() {
            let mut a: Array2<f64> = Array2::zeros((3, 4));
            assert_eq!(a.shape(), (3, 4));
            a[(1, 1)] = 42.0;

            a.resize_if_different((7, 90));
            assert_eq!(a.shape(), (7, 90));
            assert_eq!(a[(1, 1)], 0.0);

            a[(1, 1)] = 42.0;
            a.resize_if_different((7, 90));
            assert_eq!(a[(1, 1)], 42.0);
        }

        #[test]
        fn index() {
            let mut a: Array2<f64> = Array2::zeros((3, 4));

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

            a[(1, 3)] = 45.0;
            assert_eq!(a[(1, 3)], 45.0);
        }

        #[test]
        #[should_panic]
        #[cfg(debug_assertions)]
        fn out_of_bound_1() {
            let a: Array2<f64> = Array2::zeros((3, 4));
            let _ = a[(5, 1)];
        }

        #[test]
        #[should_panic]
        #[cfg(debug_assertions)]
        fn out_of_bound_2() {
            let a: Array2<f64> = Array2::zeros((3, 4));
            let _ = a[(2, 7)];
        }
    }

    mod array3 {
        use super::super::Array3;

        #[test]
        fn zeros() {
            let a: Array3<f64> = Array3::zeros((3, 4, 8));
            for i in 0..3 {
                for j in 0..4 {
                    for k in 0..8 {
                        assert_eq!(a[(i, j, k)], 0.0);
                    }
                }
            }
        }

        #[test]
        fn default() {
            #[derive(Clone)] struct F64(f64);
            impl Default for F64 {fn default() -> F64 { F64(42.0) }}

            let a: Array3<F64> = Array3::default((3, 4, 8));
            for i in 0..3 {
                for j in 0..4 {
                    for k in 0..8 {
                        assert_eq!(a[(i, j, k)].0, 42.0);
                    }
                }
            }
        }

        #[test]
        fn resize() {
            let mut a: Array3<f64> = Array3::zeros((3, 4, 5));
            assert_eq!(a.shape(), (3, 4, 5));
            a[(1, 1, 1)] = 42.0;

            a.resize_if_different((7, 90, 8));
            assert_eq!(a.shape(), (7, 90, 8));
            assert_eq!(a[(1, 1, 1)], 0.0);

            a[(1, 1, 1)] = 42.0;
            a.resize_if_different((7, 90, 8));
            assert_eq!(a[(1, 1, 1)], 42.0);
        }

        #[test]
        fn index() {
            let mut a: Array3<f64> = Array3::zeros((3, 4, 5));
            assert_eq!(a[(1, 3, 2)], 0.0);

            a[(1, 3, 2)] = 45.0;
            assert_eq!(a[(1, 3, 2)], 45.0);
        }

        #[test]
        #[should_panic]
        #[cfg(debug_assertions)]
        fn out_of_bound_1() {
            let a: Array3<f64> = Array3::zeros((3, 4, 89));
            let _ = a[(5, 1, 6)];
        }

        #[test]
        #[should_panic]
        #[cfg(debug_assertions)]
        fn out_of_bound_2() {
            let a: Array3<f64> = Array3::zeros((3, 4, 89));
            let _ = a[(2, 67, 6)];
        }

        #[test]
        #[should_panic]
        #[cfg(debug_assertions)]
        fn out_of_bound_3() {
            let a: Array3<f64> = Array3::zeros((3, 4, 89));
            let _ = a[(2, 1, 600)];
        }
    }
}
<commit_msg>[doc] Add examples to all Array{2,3} functions<commit_after>// Lumol, an extensible molecular simulation engine
// Copyright (C) 2015-2016 G. Fraux — BSD license

//! Multi-dimmensional arrays based on ndarray
use ndarray::{Array, Ix};

use std::ops::{Index, IndexMut};
use std::cmp::PartialEq;
use types::Zero;

/// Two dimensional tensors, based on ndarray.
///
/// Most of the methods are simply forwarded to ndarray, so also look the doc
/// for this crate. This array type mainly supports indexing using tuples as
/// indices and is though as storage backend for multi-dimensional data.
///
/// ```
/// # use lumol::Array2;
/// let mut a = Array2::zeros((3, 5));
///
/// assert_eq!(a[(0, 4)], 0.0);
///
/// a[(0, 4)] = 7.0;
/// assert_eq!(a[(0, 4)], 7.0);
/// ```
#[derive(Debug, Clone)]
pub struct Array2<T>(Array<T, (Ix, Ix)>);

impl<T> Array2<T> {
    /// Get the shape of the array
    /// # Examples
    /// ```
    /// # use lumol::Array2;
    /// let a: Array2<f64> = Array2::zeros((3, 5));
    /// assert_eq!(a.shape(), (3, 5));
    /// ```
    pub fn shape(&self) -> (Ix, Ix) {
        let shape = self.0.shape();
        (shape[0], shape[1])
    }
}

impl<T: Zero + Clone> Array2<T> {
    /// Create a new `Array2` of the specified `size` filled with the
    /// `Zero::zero` return value.
    ///
    /// # Examples
    ///
    /// ```
    /// # use lumol::Array2;
    /// let a: Array2<f64> = Array2::zeros((8, 5));
    /// assert_eq!(a[(6, 2)], 0.0);
    /// ```
    pub fn zeros(size: (Ix, Ix)) -> Array2<T> {
        Array2(Array::<T, (Ix, Ix)>::zeros(size))
    }

    /// Resize the array if the current size is not `size`, and fill the
    /// new array with zeros.
    ///
    /// # Examples
    ///
    /// ```
    /// # use lumol::Array2;
    /// let mut a = Array2::zeros((8, 5));
    ///
    /// a[(3, 3)] = 42.0;
    ///
    /// // This does nothing
    /// a.resize_if_different((8, 5));
    /// assert_eq!(a[(3, 3)], 42.0);
    ///
    /// // This allocates a new array
    /// a.resize_if_different((8, 9));
    /// assert_eq!(a[(3, 3)], 0.0);
    /// ```
    pub fn resize_if_different(&mut self, size: (Ix, Ix)) {
        if self.0.shape() != &[size.0, size.1] {
            *self = Array2::zeros(size);
        }
    }
}

impl<T: Clone> Array2<T> {
    /// Assign the given scalar to all entries in this array
    /// # Examples
    /// ```
    /// # use lumol::Array2;
    /// let mut a = Array2::zeros((8, 5));
    /// a.assign(33.0);
    ///
    /// assert_eq!(a[(3, 4)], 33.0);
    /// ```
    pub fn assign(&mut self, value: T) {
        self.0.assign_scalar(&value);
    }
}

impl<T: Default> Array2<T> {
    /// Create a new `Array2` of the specified `size` filled with the
    /// `Default::default` return value.
    ///
    /// # Examples
    ///
    /// ```
    /// # use lumol::Array2;
    /// let a: Array2<f64> = Array2::zeros((8, 5));
    /// let b: Array2<f64> = Array2::default((8, 5));
    ///
    /// assert_eq!(a, b);
    /// ```
    pub fn default(size: (Ix, Ix)) -> Array2<T> {
        Array2(Array::<T, (Ix, Ix)>::default(size))
    }
}

impl<T: PartialEq> PartialEq for Array2<T> {
    fn eq(&self, other: &Array2<T>) -> bool {
        self == other
    }
}

impl<T> Index<(Ix, Ix)> for Array2<T> {
    type Output = T;
    fn index(&self, index: (Ix, Ix)) -> &T {
        unsafe {
            // ndarray does the check for us in debug builds
            self.0.uget(index)
        }
    }
}

impl<T> IndexMut<(Ix, Ix)> for Array2<T> {
    fn index_mut(&mut self, index: (Ix, Ix)) -> &mut T {
        unsafe {
            // ndarray does the check for us in debug builds
            self.0.uget_mut(index)
        }
    }
}

/******************************************************************************/

/// Three dimensional tensors, based on ndarray
///
/// Most of the methods are simply forwarded to ndarray, so also look the doc
/// for this crate. This array type mainly supports indexing using tuples as
/// indices and is though as storage backend for multi-dimensional data.
///
/// ```
/// # use lumol::Array3;
/// let mut a = Array3::zeros((3, 5, 2));
///
/// assert_eq!(a[(0, 4, 1)], 0.0);
///
/// a[(0, 4, 1)] = 7.0;
/// assert_eq!(a[(0, 4, 1)], 7.0);
/// ```
#[derive(Debug, Clone)]
pub struct Array3<T>(Array<T, (Ix, Ix, Ix)>);

impl<T> Array3<T> {
    /// Get the shape of the array.
    /// # Examples
    /// ```
    /// # use lumol::Array3;
    /// let a: Array3<f64> = Array3::zeros((3, 5, 7));
    /// assert_eq!(a.shape(), (3, 5, 7));
    /// ```
    pub fn shape(&self) -> (Ix, Ix, Ix) {
        let shape = self.0.shape();
        (shape[0], shape[1], shape[2])
    }
}

impl<T: Zero + Clone> Array3<T> {
    /// Create a new `Array3` of the specified `size` filled with the
    /// `Zero::zero` return value.
    ///
    /// # Examples
    ///
    /// ```
    /// # use lumol::Array3;
    /// let a: Array3<f64> = Array3::zeros((8, 5, 2));
    /// assert_eq!(a[(6, 2, 0)], 0.0);
    /// ```
    pub fn zeros(size: (Ix, Ix, Ix)) -> Array3<T> {
        Array3(Array::<T, (Ix, Ix, Ix)>::zeros(size))
    }

    /// Resize the array if the current size is not `size`, and fill the
    /// new array with zeros.
    ///
    /// # Examples
    ///
    /// ```
    /// # use lumol::Array3;
    /// let mut a = Array3::zeros((8, 5, 7));
    ///
    /// a[(3, 3, 3)] = 42.0;
    ///
    /// // This does nothing
    /// a.resize_if_different((8, 5, 7));
    /// assert_eq!(a[(3, 3, 3)], 42.0);
    ///
    /// // This allocates a new array
    /// a.resize_if_different((8, 5, 6));
    /// assert_eq!(a[(3, 3, 3)], 0.0);
    /// ```
    pub fn resize_if_different(&mut self, size: (Ix, Ix, Ix)) {
        if self.0.shape() != &[size.0, size.1, size.2] {
            *self = Array3::zeros(size);
        }
    }
}

impl<T: Clone> Array3<T> {
    /// Assign the given scalar to all entries in this array
    pub fn assign(&mut self, value: T) {
        self.0.assign_scalar(&value);
    }
}

impl<T: Default> Array3<T> {
    /// Create a new `Array3` of the specified `size` filled with the
    /// `Default::default` return value.
    /// `Default::default` return value.
    ///
    /// # Examples
    ///
    /// ```
    /// # use lumol::Array3;
    /// let a: Array3<f64> = Array3::zeros((8, 5, 2));
    /// let b: Array3<f64> = Array3::default((8, 5, 2));
    ///
    /// assert_eq!(a, b);
    /// ```
    pub fn default(size: (Ix, Ix, Ix)) -> Array3<T>{
        Array3(Array::<T, (Ix, Ix, Ix)>::default(size))
    }
}

impl<T> Index<(Ix, Ix, Ix)> for Array3<T> {
    type Output = T;
    fn index(&self, index: (Ix, Ix, Ix)) -> &T {
        unsafe {
            // ndarray does the check for us in debug builds
            self.0.uget(index)
        }
    }
}

impl<T> IndexMut<(Ix, Ix, Ix)> for Array3<T> {
    fn index_mut(&mut self, index: (Ix, Ix, Ix)) -> &mut T {
        unsafe {
            // ndarray does the check for us in debug builds
            self.0.uget_mut(index)
        }
    }
}

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

        #[test]
        fn zeros() {
            let a: Array2<f64> = Array2::zeros((3, 4));
            for i in 0..3 {
                for j in 0..4 {
                    assert_eq!(a[(i, j)], 0.0);
                }
            }
        }

        #[test]
        fn default() {
            #[derive(Clone)] struct F64(f64);
            impl Default for F64 {fn default() -> F64 { F64(42.0) }}

            let a: Array2<F64> = Array2::default((3, 4));
            for i in 0..3 {
                for j in 0..4 {
                    assert_eq!(a[(i, j)].0, 42.0);
                }
            }
        }

        #[test]
        fn resize() {
            let mut a: Array2<f64> = Array2::zeros((3, 4));
            assert_eq!(a.shape(), (3, 4));
            a[(1, 1)] = 42.0;

            a.resize_if_different((7, 90));
            assert_eq!(a.shape(), (7, 90));
            assert_eq!(a[(1, 1)], 0.0);

            a[(1, 1)] = 42.0;
            a.resize_if_different((7, 90));
            assert_eq!(a[(1, 1)], 42.0);
        }

        #[test]
        fn index() {
            let mut a: Array2<f64> = Array2::zeros((3, 4));

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

            a[(1, 3)] = 45.0;
            assert_eq!(a[(1, 3)], 45.0);
        }

        #[test]
        #[should_panic]
        #[cfg(debug_assertions)]
        fn out_of_bound_1() {
            let a: Array2<f64> = Array2::zeros((3, 4));
            let _ = a[(5, 1)];
        }

        #[test]
        #[should_panic]
        #[cfg(debug_assertions)]
        fn out_of_bound_2() {
            let a: Array2<f64> = Array2::zeros((3, 4));
            let _ = a[(2, 7)];
        }
    }

    mod array3 {
        use super::super::Array3;

        #[test]
        fn zeros() {
            let a: Array3<f64> = Array3::zeros((3, 4, 8));
            for i in 0..3 {
                for j in 0..4 {
                    for k in 0..8 {
                        assert_eq!(a[(i, j, k)], 0.0);
                    }
                }
            }
        }

        #[test]
        fn default() {
            #[derive(Clone)] struct F64(f64);
            impl Default for F64 {fn default() -> F64 { F64(42.0) }}

            let a: Array3<F64> = Array3::default((3, 4, 8));
            for i in 0..3 {
                for j in 0..4 {
                    for k in 0..8 {
                        assert_eq!(a[(i, j, k)].0, 42.0);
                    }
                }
            }
        }

        #[test]
        fn resize() {
            let mut a: Array3<f64> = Array3::zeros((3, 4, 5));
            assert_eq!(a.shape(), (3, 4, 5));
            a[(1, 1, 1)] = 42.0;

            a.resize_if_different((7, 90, 8));
            assert_eq!(a.shape(), (7, 90, 8));
            assert_eq!(a[(1, 1, 1)], 0.0);

            a[(1, 1, 1)] = 42.0;
            a.resize_if_different((7, 90, 8));
            assert_eq!(a[(1, 1, 1)], 42.0);
        }

        #[test]
        fn index() {
            let mut a: Array3<f64> = Array3::zeros((3, 4, 5));
            assert_eq!(a[(1, 3, 2)], 0.0);

            a[(1, 3, 2)] = 45.0;
            assert_eq!(a[(1, 3, 2)], 45.0);
        }

        #[test]
        #[should_panic]
        #[cfg(debug_assertions)]
        fn out_of_bound_1() {
            let a: Array3<f64> = Array3::zeros((3, 4, 89));
            let _ = a[(5, 1, 6)];
        }

        #[test]
        #[should_panic]
        #[cfg(debug_assertions)]
        fn out_of_bound_2() {
            let a: Array3<f64> = Array3::zeros((3, 4, 89));
            let _ = a[(2, 67, 6)];
        }

        #[test]
        #[should_panic]
        #[cfg(debug_assertions)]
        fn out_of_bound_3() {
            let a: Array3<f64> = Array3::zeros((3, 4, 89));
            let _ = a[(2, 1, 600)];
        }
    }
}
<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2013 Jeremy Letang (letang.jeremy@gmail.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

/*!
* The functionnality that a Sound or a Music should implement.
*/

use states::State;

/// The functionnality that an Audio Source should implement.
pub trait AudioController {
	/**
    * Play or resume the Audio Source.
    */
	fn play(&mut self) -> ();

	/**
    * Pause the Audio Source.
    */
	fn pause(&mut self) -> ();

	/**
    * Stop the Audio Source.
    */
	fn stop(&mut self) -> ();

	/**
    * Check if the Audio Source is playing or not.
    *
    * # Return
    * true if the Audio Source is playing, false otherwise.
    */
	fn is_playing(&self) -> bool;

	/**
    * Get the current state of the Audio Source
    *
    * # Return
    * The state of the Audio Source as a variant of the enum State
    */
	fn get_state(&self) -> State;

	/**
    * Set the volume of the Audio Source.
    *
    * A value of 1.0 means unattenuated. Each division by 2 equals an attenuation
    * of about -6dB. Each multiplicaton by 2 equals an amplification of about
    * +6dB.
    *
    * # Argument
    * * `volume` - The volume of the Audio Source, should be between 0. and 1.
    */
	fn set_volume(&mut self, volume : f32) -> ();

	/**
    * Get the volume of the Audio Source.
    *
    * # Return
    * The volume of the Audio Source between 0. and 1.
    */
	fn get_volume(&self) -> f32;

	/**
    * Set the minimal volume for a Audio Source.
    *
    * The minimum volume allowed for a source, after distance and cone attenation is
    * applied (if applicable).
    *
    * # Argument
    * * `min_volume` - The new minimal volume of the Audio Source should be between 0. and 1.
    */
	fn set_min_volume(&mut self, min_volume : f32) -> ();

	/**
    * Get the minimal volume of the Audio Source.
    *
    * # Return
    * The minimal volume of the Audio Source between 0. and 1.
    */
	fn get_min_volume(&self) -> f32;

	/**
    * Set the maximal volume for a Audio Source.
    *
    * The maximum volume allowed for a sound, after distance and cone attenation is
    * applied (if applicable).
    *
    * # Argument
    * * `max_volume` - The new maximal volume of the Audio Source should be between 0. and 1.
    */
	fn set_max_volume(&mut self, max_volume : f32) -> ();

	/**
    * Get the maximal volume of the Audio Source.
    *
    * # Return
    * The maximal volume of the Audio Source between 0. and 1.
    */
	fn get_max_volume(&self) -> f32;

	/**
    * Set the Audio Source looping or not
    *
    * The default looping is false.
    *
    * # Arguments
    * `looping` - The new looping state.
    */
	fn set_looping(&mut self, looping : bool) -> ();

	/**
    * Check if the Audio Source is looping or not
    *
    * # Return
    * True if the Audio Source is looping, false otherwise.
    */
	fn is_looping(&self) -> bool;

	/**
    * Set the pitch of the source.
    *
    * A multiplier for the frequency (sample rate) of the source's buffer.
    *
    * Default pitch is 1.0.
    *
    * # Argument
    * * `new_pitch` - The new pitch of the Audio Source in the range [0.5 - 2.0]
    */
	fn set_pitch(&mut self, pitch : f32) -> ();

	/**
    * Set the pitch of the source.
    *
    * # Return
    * The pitch of the Audio Source in the range [0.5 - 2.0]
    */
	fn get_pitch(&self) -> f32;

	/**
    * Set the position of the Audio Source relative to the listener or absolute.
    *
    * Default position is absolute.
    *
    * # Argument
    * `relative` - True to set Audio Source relative to the
    * listener false to set the Audio Source position absolute.
    */
	fn set_relative(&mut self, relative : bool) -> ();

	/**
    * Is the Audio Source relative to the listener or not ?
    *
    * # Return
    * True if the Audio Source is relative to the listener false otherwise
    */
	fn is_relative(&mut self) -> bool;

	/**
    * Set the Audio Source location in three dimensional space.
    *
    * OpenAL, like OpenGL, uses a right handed coordinate system, where in a
    * frontal default view X (thumb) points right, Y points up (index finger), and
    * Z points towards the viewer/camera (middle finger).
    * To switch from a left handed coordinate system, flip the sign on the Z
    * coordinate.
    *
    * Default position is [0., 0., 0.].
    *
    * # Argument
    * * `position` - A three dimensional vector of f32 containing the position of the listener [x, y, z].
    */
	fn set_position(&mut self, position : [f32, ..3]) -> ();

	/**
    * Get the position of the Audio Source in three dimensional space.
    *
    * # Return
    * A three dimensional vector of f32 containing the position of the listener [x, y, z].
    */
	fn get_position(&self) -> [f32, ..3];

	/**
    * Set the direction of the Audio Source.
    *
    * Specifies the current direction in local space.
    *
    * The default direction is: [0., 0., 0.]
    *
    * # Argument
    * `direction` - The new direction of the Audio Source.
    */
	fn set_direction(&mut self, direction : [f32, ..3]) -> ();

	/**
    * Get the direction of the Audio Source.
    *
    * # Return
    * The current direction of the Audio Source.
    */
	fn get_direction(&self)  -> [f32, ..3];

	/**
    * Set the maximum distance of the Audio Source.
    *
    * The distance above which the source is not attenuated any further with a
    * clamped distance model, or where attenuation reaches 0.0 gain for linear
    * distance models with a default rolloff factor.
    *
    * The default maximum distance is +inf.
    *
    * # Argument
    * `max_distance` - The new maximum distance in the range [0., +inf]
    */
	fn set_max_distance(&mut self, max_distance : f32) -> ();

	/**
    * Get the maximum distance of the Audio Source.
    *
    * # Return
    * The maximum distance of the Audio Source in the range [0., +inf]
    */
	fn get_max_distance(&self) -> f32;

	/**
    * Set the reference distance of the Audio Source.
    *
    * The distance in units that no attenuation occurs.
    * At 0.0, no distance attenuation ever occurs on non-linear attenuation models.
    *
    * The default distance reference is 1.
    *
    * # Argument
    * * `ref_distance` - The new reference distance of the Audio Source.
    */
	fn set_reference_distance(&mut self, ref_distance : f32) -> ();

	/**
    * Get the reference distance of the Audio Source.
    *
    * # Return
    * The current reference distance of the Audio Source.
    */
	fn get_reference_distance(&self) -> f32;

	/**
    * Set the attenuation of a Audio Source.
    *
    * Multiplier to exaggerate or diminish distance attenuation.
    * At 0.0, no distance attenuation ever occurs.
    *
    * The default attenuation is 1.
    *
    * # Arguments
    * `attenuation` - The new attenuation for the Audio Source in the range [0., 1.].
    */
	fn set_attenuation(&mut self, attenuation : f32) -> ();

	/**
    * Get the attenuation of a Sound.
    *
    * # Return
    * The current attenuation for the Audio Source in the range [0., 1.].
    */
	fn get_attenuation(&self) -> f32;
}

<commit_msg>update formating<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2013 Jeremy Letang (letang.jeremy@gmail.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

/*!
* The functionnality that a Sound or a Music should implement.
*/

use states::State;

/// The functionnality that an Audio Source should implement.
pub trait AudioController {
    /**
     * Play or resume the Audio Source.
     */
    fn play(&mut self) -> ();

    /**
     * Pause the Audio Source.
     */
    fn pause(&mut self) -> ();

    /**
     * Stop the Audio Source.
     */
    fn stop(&mut self) -> ();

    /**
     * Check if the Audio Source is playing or not.
     *
     * # Return
     * true if the Audio Source is playing, false otherwise.
     */
    fn is_playing(&self) -> bool;

    /**
     * Get the current state of the Audio Source
     *
     * # Return
     * The state of the Audio Source as a variant of the enum State
     */
    fn get_state(&self) -> State;

    /**
     * Set the volume of the Audio Source.
     *
     * A value of 1.0 means unattenuated. Each division by 2 equals an attenuation
     * of about -6dB. Each multiplicaton by 2 equals an amplification of about
     * +6dB.
     *
     * # Argument
     * * `volume` - The volume of the Audio Source, should be between 0. and 1.
     */
    fn set_volume(&mut self, volume : f32) -> ();

    /**
     * Get the volume of the Audio Source.
     *
     * # Return
     * The volume of the Audio Source between 0. and 1.
     */
    fn get_volume(&self) -> f32;

    /**
     * Set the minimal volume for a Audio Source.
     *
     * The minimum volume allowed for a source, after distance and cone attenation is
     * applied (if applicable).
     *
     * # Argument
     * * `min_volume` - The new minimal volume of the Audio Source should be between 0. and 1.
     */
    fn set_min_volume(&mut self, min_volume : f32) -> ();

    /**
     * Get the minimal volume of the Audio Source.
     *
     * # Return
     * The minimal volume of the Audio Source between 0. and 1.
     */
    fn get_min_volume(&self) -> f32;

    /**
     * Set the maximal volume for a Audio Source.
     *
     * The maximum volume allowed for a sound, after distance and cone attenation is
     * applied (if applicable).
     *
     * # Argument
     * * `max_volume` - The new maximal volume of the Audio Source should be between 0. and 1.
     */
    fn set_max_volume(&mut self, max_volume : f32) -> ();

    /**
     * Get the maximal volume of the Audio Source.
     *
     * # Return
     * The maximal volume of the Audio Source between 0. and 1.
     */
    fn get_max_volume(&self) -> f32;

    /**
     * Set the Audio Source looping or not
     *
     * The default looping is false.
     *
     * # Arguments
     * `looping` - The new looping state.
     */
    fn set_looping(&mut self, looping : bool) -> ();

    /**
     * Check if the Audio Source is looping or not
     *
     * # Return
     * True if the Audio Source is looping, false otherwise.
     */
    fn is_looping(&self) -> bool;

    /**
     * Set the pitch of the source.
     *
     * A multiplier for the frequency (sample rate) of the source's buffer.
     *
     * Default pitch is 1.0.
     *
     * # Argument
     * * `new_pitch` - The new pitch of the Audio Source in the range [0.5 - 2.0]
     */
    fn set_pitch(&mut self, pitch : f32) -> ();

    /**
     * Set the pitch of the source.
     *
     * # Return
     * The pitch of the Audio Source in the range [0.5 - 2.0]
     */
    fn get_pitch(&self) -> f32;

    /**
     * Set the position of the Audio Source relative to the listener or absolute.
     *
     * Default position is absolute.
     *
     * # Argument
     * `relative` - True to set Audio Source relative to the
     * listener false to set the Audio Source position absolute.
     */
    fn set_relative(&mut self, relative : bool) -> ();

    /**
     * Is the Audio Source relative to the listener or not ?
     *
     * # Return
     * True if the Audio Source is relative to the listener false otherwise
     */
    fn is_relative(&mut self) -> bool;

    /**
     * Set the Audio Source location in three dimensional space.
     *
     * OpenAL, like OpenGL, uses a right handed coordinate system, where in a
     * frontal default view X (thumb) points right, Y points up (index finger), and
     * Z points towards the viewer/camera (middle finger).
     * To switch from a left handed coordinate system, flip the sign on the Z
     * coordinate.
     *
     * Default position is [0., 0., 0.].
     *
     * # Argument
     * * `position` - A three dimensional vector of f32 containing the position of the listener [x, y, z].
     */
    fn set_position(&mut self, position : [f32, ..3]) -> ();

    /**
     * Get the position of the Audio Source in three dimensional space.
     *
     * # Return
     * A three dimensional vector of f32 containing the position of the listener [x, y, z].
     */
    fn get_position(&self) -> [f32, ..3];

    /**
     * Set the direction of the Audio Source.
     *
     * Specifies the current direction in local space.
     *
     * The default direction is: [0., 0., 0.]
     *
     * # Argument
     * `direction` - The new direction of the Audio Source.
     */
    fn set_direction(&mut self, direction : [f32, ..3]) -> ();

    /**
     * Get the direction of the Audio Source.
     *
     * # Return
     * The current direction of the Audio Source.
     */
    fn get_direction(&self)  -> [f32, ..3];

    /**
     * Set the maximum distance of the Audio Source.
     *
     * The distance above which the source is not attenuated any further with a
     * clamped distance model, or where attenuation reaches 0.0 gain for linear
     * distance models with a default rolloff factor.
     *
     * The default maximum distance is +inf.
     *
     * # Argument
     * `max_distance` - The new maximum distance in the range [0., +inf]
     */
    fn set_max_distance(&mut self, max_distance : f32) -> ();

    /**
     * Get the maximum distance of the Audio Source.
     *
     * # Return
     * The maximum distance of the Audio Source in the range [0., +inf]
     */
    fn get_max_distance(&self) -> f32;

    /**
     * Set the reference distance of the Audio Source.
     *
     * The distance in units that no attenuation occurs.
     * At 0.0, no distance attenuation ever occurs on non-linear attenuation models.
     *
     * The default distance reference is 1.
     *
     * # Argument
     * * `ref_distance` - The new reference distance of the Audio Source.
     */
    fn set_reference_distance(&mut self, ref_distance : f32) -> ();

    /**
     * Get the reference distance of the Audio Source.
     *
     * # Return
     * The current reference distance of the Audio Source.
     */
    fn get_reference_distance(&self) -> f32;

    /**
     * Set the attenuation of a Audio Source.
     *
     * Multiplier to exaggerate or diminish distance attenuation.
     * At 0.0, no distance attenuation ever occurs.
     *
     * The default attenuation is 1.
     *
     * # Arguments
     * `attenuation` - The new attenuation for the Audio Source in the range [0., 1.].
     */
    fn set_attenuation(&mut self, attenuation : f32) -> ();

    /**
     * Get the attenuation of a Sound.
     *
     * # Return
     * The current attenuation for the Audio Source in the range [0., 1.].
     */
    fn get_attenuation(&self) -> f32;
}

<|endoftext|>


<commit_before>extern crate clap;
extern crate regex;
extern crate walkdir;

use clap::{Arg, App};
use regex::Regex;
use std::fs;
use std::borrow::Borrow;
use std::path::Path;
use walkdir::{ DirEntry, WalkDir };

fn main() {
  let matches = App::new("mvb")
      .version("0.1.0")
      .author("Peter Teixeira")
      .about("Bulk renames files")
      .arg(Arg::with_name("from_pattern").required(true).index(1))
      .arg(Arg::with_name("to_pattern").required(true).index(2))
      .get_matches();

  let from_pattern = matches.value_of("from_pattern").unwrap();
  let to_pattern = matches.value_of("to_pattern").unwrap();
  let re = Regex::new(from_pattern)
      .expect("Could not parse input pattern");

  for entry in WalkDir::new(".").into_iter().filter_map(|e| e.ok()) {
      try_move_file(entry, &to_pattern, &re);
  }
}

fn try_move_file(entry: DirEntry, target_pattern: &str, re: &Regex) -> Option<()> {
  let filename = entry.file_name().to_str()?;

  if !re.is_match(filename) {
      return None;
  }

  let replaced_name = re.replace(filename, target_pattern);
  let target_file_name: &str = replaced_name.borrow();
  let target_file_path = Path::new(target_file_name);

  println!("Renaming {} to {:?}", entry.path().display(), target_file_name);
  return match fs::rename(entry.path(), target_file_path) {
      Ok(_) => None,
      Err(e) => panic!(e),
  }
}
<commit_msg>Add backup option; don't panic<commit_after>extern crate clap;
extern crate regex;
extern crate walkdir;

use clap::{App, Arg};
use regex::Regex;
use std::borrow::Borrow;
use std::fs;
use std::io;
use std::path::Path;
use walkdir::{DirEntry, WalkDir};

fn main() {
    let matches = App::new("mvb")
        .author("Peter Teixeira")
        .about("Bulk renames files")
        .arg(Arg::with_name("from_pattern").required(true).index(1))
        .arg(Arg::with_name("to_pattern").required(true).index(2))
        .arg(
            Arg::with_name("preserve")
                .required(false)
                .short("p")
                .long("preserve")
                .help("Preserve original files (make copies at new location)"),
        )
        .get_matches();

    let from_pattern = matches.value_of("from_pattern").unwrap();
    let to_pattern = matches.value_of("to_pattern").unwrap();
    let backup = matches.is_present("preserve");
    let re = Regex::new(from_pattern).expect("Could not parse input pattern");

    for entry in WalkDir::new(".").into_iter().filter_map(|e| e.ok()) {
        if backup {
            try_copy_file(entry, &to_pattern, &re);
        } else {
            try_move_file(entry, &to_pattern, &re);
        }
    }
}

fn try_move_file(entry: DirEntry, target_pattern: &str, re: &Regex) -> Option<io::Result<()>> {
    let filename = entry.file_name().to_str()?;

    if !re.is_match(filename) {
        return None;
    }

    let replaced_name = re.replace(filename, target_pattern);
    let target_file_name: &str = replaced_name.borrow();
    let target_file_path = Path::new(target_file_name);

    Some(fs::rename(entry.path(), target_file_path))
}

fn try_copy_file(entry: DirEntry, target_pattern: &str, re: &Regex) -> Option<io::Result<()>> {
    let filename = entry.file_name().to_str()?;

    if !re.is_match(filename) {
        return None;
    }

    let replaced_name = re.replace(filename, target_pattern);
    let target_file_name: &str = replaced_name.borrow();
    let target_file_path = Path::new(target_file_name);

    return match fs::copy(entry.path(), target_file_path) {
        Ok(_) => Some(Ok(())),
        Err(e) => Some(Err(e))
    }
}
<|endoftext|>


<commit_before>/* kernel::sgash.rs */
#[allow(unused_imports)];
use core::*;
use core::str::*;
use core::option::{Some, Option, None};
use core::iter::Iterator;
use kernel::*;
use super::super::platform::*;
use kernel::memory::Allocator;
use kernel::memory::BuddyAlloc;
use kernel::memory::Bitv;
use kernel::memory::BitvStorage;
use kernel::memory::Alloc;

pub static mut buffer: cstr = cstr {
				p: 0 as *mut u8,
				p_cstr_i: 0,
				max: 0
			      };

pub fn putchar(key: char) {
    unsafe {
	/*
	 * We need to include a blank asm call to prevent rustc
	 * from optimizing this part out
	 */
	asm!("");
	io::write_char(key, io::UART0);
    }
}

fn putstr(msg: &str) {
    for c in slice::iter(as_bytes(msg)) {
	   putchar(*c as char);
    }
}

pub unsafe fn drawstr(msg: &str) {
    let old_fg = super::super::io::FG_COLOR;
    let mut x: u32 = 0x6699AAFF;
    for c in slice::iter(as_bytes(msg)) {
    	x = (x << 8) + (x >> 24);
    	super::super::io::set_fg(x);
    	drawchar(*c as char);
    }
    super::super::io::set_fg(old_fg);
}

unsafe fn drawchar(x: char)
{
    io::restore();
    if x == '\n' {
    	io::CURSOR_Y += io::CURSOR_HEIGHT;
    	io::CURSOR_X = 0u32;
    }
    else {
    	io::draw_char(x);
    	io::CURSOR_X += io::CURSOR_WIDTH;
    }
    io::backup();
    io::draw_cursor();
}

unsafe fn backspace()
{
    io::restore();
    if (io::CURSOR_X >= io::CURSOR_WIDTH) {
    	io::CURSOR_X -= io::CURSOR_WIDTH;
    	io::draw_char(' ');
    }
    io::backup();
    io::draw_cursor();
}

pub unsafe fn parsekey(x: char) {
    let x = x as u8;
    // Set this to false to learn the keycodes of various keys!
    // Key codes are printed backwards because life is hard

    match x {
	13		=>	{
	    putstr(&"\n");
	    drawstr(&"\n");
        echo();
        putstr(&"sgash> ");
        drawstr(&"sgash> ");
        buffer.reset();
	}
	127		=>	{
	    putchar('');
	    putchar(' ');
	    putchar('');
	    backspace();
        buffer.delete_char();

	}
	_		=>	{
	    if io::CURSOR_X < io::SCREEN_WIDTH-io::CURSOR_WIDTH  && buffer.add_char(x) {
    		putchar(x as char);
    		drawchar(x as char);
	    }
	}
    }
}

fn screen() {
    putstr(&"\n                                                               ");
    putstr(&"\n                                                               ");
    putstr(&"\n                       7=..~$=..:7                             ");
    putstr(&"\n                  +$: =$$$+$$$?$$$+ ,7?                        ");
    putstr(&"\n                  $$$$$$$$$$$$$$$$$$Z$$                        ");
    putstr(&"\n              7$$$$$$$$$$$$. .Z$$$$$Z$$$$$$                    ");
    putstr(&"\n           ~..7$$Z$$$$$7+7$+.?Z7=7$$Z$$Z$$$..:                 ");
    putstr(&"\n          ~$$$$$$$$7:     :ZZZ,     :7ZZZZ$$$$=                ");
    putstr(&"\n           Z$$$$$?                    .+ZZZZ$$                 ");
    putstr(&"\n       +$ZZ$$$Z7                         7ZZZ$Z$$I.            ");
    putstr(&"\n        $$$$ZZZZZZZZZZZZZZZZZZZZZZZZI,    ,ZZZ$$Z              ");
    putstr(&"\n      :+$$$$ZZZZZZZZZZZZZZZZZZZZZZZZZZZ=    $ZZ$$+~,           ");
    putstr(&"\n     ?$Z$$$$ZZZZZZZZZZZZZZZZZZZZZZZZZZZZI   7ZZZ$ZZI           ");
    putstr(&"\n      =Z$$+7Z$$7ZZZZZZZZ$$$$$$$ZZZZZZZZZZ  ~Z$?$ZZ?            ");
    putstr(&"\n    :$Z$Z...$Z  $ZZZZZZZ~       ~ZZZZZZZZ,.ZZ...Z$Z$~          ");
    putstr(&"\n    7ZZZZZI$ZZ  $ZZZZZZZ~       =ZZZZZZZ7..ZZ$?$ZZZZ$          ");
    putstr(&"\n      ZZZZ$:    $ZZZZZZZZZZZZZZZZZZZZZZ=     ~$ZZZ$:           ");
    putstr(&"\n    7Z$ZZ$,     $ZZZZZZZZZZZZZZZZZZZZ7         ZZZ$Z$          ");
    putstr(&"\n   =ZZZZZZ,     $ZZZZZZZZZZZZZZZZZZZZZZ,       ZZZ$ZZ+         ");
    putstr(&"\n     ,ZZZZ,     $ZZZZZZZ:     =ZZZZZZZZZ     ZZZZZ$:           ");
    putstr(&"\n    =$ZZZZ+     ZZZZZZZZ~       ZZZZZZZZ~   =ZZZZZZZI          ");
    putstr(&"\n    $ZZ$ZZZ$$Z$$ZZZZZZZZZ$$$$   IZZZZZZZZZ$ZZZZZZZZZ$          ");
    putstr(&"\n      :ZZZZZZZZZZZZZZZZZZZZZZ   ~ZZZZZZZZZZZZZZZZZ~            ");
    putstr(&"\n     ,Z$$ZZZZZZZZZZZZZZZZZZZZ    ZZZZZZZZZZZZZZZZZZ~           ");
    putstr(&"\n     =$ZZZZZZZZZZZZZZZZZZZZZZ     $ZZZZZZZZZZZZZZZ$+           ");
    putstr(&"\n        IZZZZZ:.                        . ,ZZZZZ$              ");
    putstr(&"\n       ~$ZZZZZZZZZZZ                 ZZZZ$ZZZZZZZ+             ");
    putstr(&"\n           Z$ZZZ. ,Z~               =Z:.,ZZZ$Z                 ");
    putstr(&"\n          ,ZZZZZ..~Z$.             .7Z:..ZZZZZ:                ");
    putstr(&"\n          ~7+:$ZZZZZZZZI=:.   .,=IZZZZZZZ$Z:=7=                ");
    putstr(&"\n              $$ZZZZZZZZZZZZZZZZZZZZZZ$ZZZZ                    ");
    putstr(&"\n              ==..$ZZZ$ZZZZZZZZZZZ$ZZZZ .~+                    ");
    putstr(&"\n                  I$?.?ZZZ$ZZZ$ZZZI =$7                        ");
    putstr(&"\n                       $7..I$7..I$,                            ");
    putstr(&"\n");
    putstr(&"\n _                     _     _                         _  ");
    putstr(&"\n| |                   (_)   | |                       | | ");
    putstr(&"\n| | ____ ___  ____     _____| |_____  ____ ____  _____| | ");
    putstr(&"\n| |/ ___) _ \\|  _ \\   |  _   _) ___ |/ ___)  _ \\| ___ | | ");
    putstr(&"\n| | |  | |_| | | | |  | |  \\ \\| ____| |   | | | | ____| | ");
    putstr(&"\n|_|_|  \\____/|_| |_|  |_|   \\_\\_____)_|   |_| |_|_____)__)\n\n");
}

pub unsafe fn init() {
	buffer = cstr::new(256);
    screen();
    //buffer.add_char('c' as u8);
    //putstr(&buffer);
    // let mut string: cstr = cstr::new(256);
    // putstr("Hello");
    // string.add_char('x' as u8);
}

pub unsafe fn echo() -> bool{
    let s = buffer.p as uint;
    let e = buffer.max;
    let mut i = 0;
    while i < e {
        let theChar : u8 = *((s+i) as *mut u8);
        if(theChar as char != '\0') {
            putchar(theChar as char);
            drawchar(theChar as char);
            i +=1;
        }
        else {
            drawstr(&"\n");
            putstr(&"\n");
            return true;
        }
    }
    return false;
}

struct cstr {
    p: *mut u8,
    p_cstr_i: uint,
    max: uint
}

impl cstr {

    pub unsafe fn new(size: uint) -> cstr {
        // Sometimes this doesn't allocate enough memory and gets stuck..

        let (x,y) = heap.alloc(size);

        let this = cstr {
            p: x,
            p_cstr_i: 0,
            max: y
        };
        *(((this.p as uint)+this.p_cstr_i) as *mut char) = '\0';
        this
    }

    #[allow(dead_code)]
    fn len(&self) -> uint {
        self.p_cstr_i
    }

    unsafe fn add_char(&mut self, x: u8) -> bool{
        //putstr("1");
        if (self.p_cstr_i == self.max) {
            return false;
        }
        //putstr("2");
        *(((self.p as uint)+self.p_cstr_i) as *mut u8) = x;
        //putstr("3");
        self.p_cstr_i += 1;
        *(((self.p as uint)+self.p_cstr_i) as *mut char) = '\0';
        //putstr("4");
        true
    }

    unsafe fn delete_char(&mut self) -> bool {
        if (self.p_cstr_i == 0) { return false; }
        self.p_cstr_i -= 1;
        *(((self.p as uint)+self.p_cstr_i) as *mut char) = '\0';
        true
    }

    unsafe fn reset(&mut self) {
        self.p_cstr_i = 0;
        *(self.p as *mut char) = '\0';
    }

    unsafe fn eq(&self, other: &cstr) -> bool {
        if (self.len() != other.len()) { return false; }
        else {
            let mut x = 0;
            let mut selfp: uint = self.p as uint;
            let mut otherp: uint = other.p as uint;
            while x < self.len() {
                if (*(selfp as *char) != *(otherp as *char)) { return false; }
                selfp += 1;
                otherp += 1;
                x += 1;
            }
            true
        }
    }
}<commit_msg>starting code for problem 5<commit_after>/* kernel::sgash.rs */
#[allow(unused_imports)];
use std::path::*;
use core::*;
use core::str::*;
use core::option::{Some, Option, None};
use core::iter::Iterator;
use kernel::*;
use super::super::platform::*;
use kernel::memory::Allocator;
use kernel::memory::BuddyAlloc;
use kernel::memory::Bitv;
use kernel::memory::BitvStorage;
use kernel::memory::Alloc;

pub static mut buffer: cstr = cstr {
				p: 0 as *mut u8,
				p_cstr_i: 0,
				max: 0
			      };

pub fn putchar(key: char) {
    unsafe {
	/*
	 * We need to include a blank asm call to prevent rustc
	 * from optimizing this part out
	 */
	asm!("");
	io::write_char(key, io::UART0);
    }
}

fn putstr(msg: &str) {
    for c in slice::iter(as_bytes(msg)) {
	   putchar(*c as char);
    }
}

pub unsafe fn drawstr(msg: &str) {
    let old_fg = super::super::io::FG_COLOR;
    let mut x: u32 = 0x6699AAFF;
    for c in slice::iter(as_bytes(msg)) {
    	x = (x << 8) + (x >> 24);
    	super::super::io::set_fg(x);
    	drawchar(*c as char);
    }
    super::super::io::set_fg(old_fg);
}

unsafe fn drawchar(x: char)
{
    io::restore();
    if x == '\n' {
    	io::CURSOR_Y += io::CURSOR_HEIGHT;
    	io::CURSOR_X = 0u32;
    }
    else {
    	io::draw_char(x);
    	io::CURSOR_X += io::CURSOR_WIDTH;
    }
    io::backup();
    io::draw_cursor();
}

unsafe fn backspace()
{
    io::restore();
    if (io::CURSOR_X >= io::CURSOR_WIDTH) {
    	io::CURSOR_X -= io::CURSOR_WIDTH;
    	io::draw_char(' ');
    }
    io::backup();
    io::draw_cursor();
}

pub unsafe fn parsekey(x: char) {
    let x = x as u8;
    // Set this to false to learn the keycodes of various keys!
    // Key codes are printed backwards because life is hard

    match x {
	13		=>	{
		parse();
		putstr(&"\nsgash> ");
		drawstr(&"\nsgash> ");
        buffer.reset();
	}
	127		=>	{
	    putchar('');
	    putchar(' ');
	    putchar('');
	    backspace();
        buffer.delete_char();

	}
	_		=>	{
	    if io::CURSOR_X < io::SCREEN_WIDTH-io::CURSOR_WIDTH  && buffer.add_char(x) {
    		putchar(x as char);
    		drawchar(x as char);
	    }
	}
    }
}

unsafe fn parse(){
	if(buffer.equals(&"freeze")){
		putstr(&"\nTHIS IS A STICK UP!!");
		drawstr(&"\nTHIS IS A STICK UP!!");
	};
	// cd, rm, mkdir, pwd
	// match buffer.getarg(' ', 0) {
	//     Some(a) => {
	//     	if(a.equals(&"echo")) {
	//     		echo();
	// 		}
	// 		if(a.equals(&"ls")) {
	// 		    putstr(&"\nfile list");
	// 		    drawstr(&"\nfile list");
	// 		}
	// 		if(a.equals(&"pwd")) {
	// 		    putstr(&"\nmy directory");
	// 		    drawstr(&"\nmy directory");
	// 		}
	// 		if(a.equals(&"mkdir")) {
	// 			match buffer.getarg(' ', 1){
	// 				Some(b) =>{
	// 					putstr(&"");
	// 					drawstr(&a);
	// 				}
	// 				None => {}
	// 			};
	// 		}
	// 		f(a.equals(&"cat")) {
	// 			match buffer.getarg(' ', 1){
	// 				Some(b) =>{
	// 					putstr(&a);
	// 					drawstr(&a);
	// 				}
	// 				None => {}
	// 			};
	// 		}
	//     }
	//     None => { }
	// };
	// buffer.reset();
}

fn screen() {
    putstr(&"\n                                                               ");
    putstr(&"\n                                                               ");
    putstr(&"\n                       7=..~$=..:7                             ");
    putstr(&"\n                  +$: =$$$+$$$?$$$+ ,7?                        ");
    putstr(&"\n                  $$$$$$$$$$$$$$$$$$Z$$                        ");
    putstr(&"\n              7$$$$$$$$$$$$. .Z$$$$$Z$$$$$$                    ");
    putstr(&"\n           ~..7$$Z$$$$$7+7$+.?Z7=7$$Z$$Z$$$..:                 ");
    putstr(&"\n          ~$$$$$$$$7:     :ZZZ,     :7ZZZZ$$$$=                ");
    putstr(&"\n           Z$$$$$?                    .+ZZZZ$$                 ");
    putstr(&"\n       +$ZZ$$$Z7                         7ZZZ$Z$$I.            ");
    putstr(&"\n        $$$$ZZZZZZZZZZZZZZZZZZZZZZZZI,    ,ZZZ$$Z              ");
    putstr(&"\n      :+$$$$ZZZZZZZZZZZZZZZZZZZZZZZZZZZ=    $ZZ$$+~,           ");
    putstr(&"\n     ?$Z$$$$ZZZZZZZZZZZZZZZZZZZZZZZZZZZZI   7ZZZ$ZZI           ");
    putstr(&"\n      =Z$$+7Z$$7ZZZZZZZZ$$$$$$$ZZZZZZZZZZ  ~Z$?$ZZ?            ");
    putstr(&"\n    :$Z$Z...$Z  $ZZZZZZZ~       ~ZZZZZZZZ,.ZZ...Z$Z$~          ");
    putstr(&"\n    7ZZZZZI$ZZ  $ZZZZZZZ~       =ZZZZZZZ7..ZZ$?$ZZZZ$          ");
    putstr(&"\n      ZZZZ$:    $ZZZZZZZZZZZZZZZZZZZZZZ=     ~$ZZZ$:           ");
    putstr(&"\n    7Z$ZZ$,     $ZZZZZZZZZZZZZZZZZZZZ7         ZZZ$Z$          ");
    putstr(&"\n   =ZZZZZZ,     $ZZZZZZZZZZZZZZZZZZZZZZ,       ZZZ$ZZ+         ");
    putstr(&"\n     ,ZZZZ,     $ZZZZZZZ:     =ZZZZZZZZZ     ZZZZZ$:           ");
    putstr(&"\n    =$ZZZZ+     ZZZZZZZZ~       ZZZZZZZZ~   =ZZZZZZZI          ");
    putstr(&"\n    $ZZ$ZZZ$$Z$$ZZZZZZZZZ$$$$   IZZZZZZZZZ$ZZZZZZZZZ$          ");
    putstr(&"\n      :ZZZZZZZZZZZZZZZZZZZZZZ   ~ZZZZZZZZZZZZZZZZZ~            ");
    putstr(&"\n     ,Z$$ZZZZZZZZZZZZZZZZZZZZ    ZZZZZZZZZZZZZZZZZZ~           ");
    putstr(&"\n     =$ZZZZZZZZZZZZZZZZZZZZZZ     $ZZZZZZZZZZZZZZZ$+           ");
    putstr(&"\n        IZZZZZ:.                        . ,ZZZZZ$              ");
    putstr(&"\n       ~$ZZZZZZZZZZZ                 ZZZZ$ZZZZZZZ+             ");
    putstr(&"\n           Z$ZZZ. ,Z~               =Z:.,ZZZ$Z                 ");
    putstr(&"\n          ,ZZZZZ..~Z$.             .7Z:..ZZZZZ:                ");
    putstr(&"\n          ~7+:$ZZZZZZZZI=:.   .,=IZZZZZZZ$Z:=7=                ");
    putstr(&"\n              $$ZZZZZZZZZZZZZZZZZZZZZZ$ZZZZ                    ");
    putstr(&"\n              ==..$ZZZ$ZZZZZZZZZZZ$ZZZZ .~+                    ");
    putstr(&"\n                  I$?.?ZZZ$ZZZ$ZZZI =$7                        ");
    putstr(&"\n                       $7..I$7..I$,                            ");
    putstr(&"\n");
    putstr(&"\n _                     _     _                         _  ");
    putstr(&"\n| |                   (_)   | |                       | | ");
    putstr(&"\n| | ____ ___  ____     _____| |_____  ____ ____  _____| | ");
    putstr(&"\n| |/ ___) _ \\|  _ \\   |  _   _) ___ |/ ___)  _ \\| ___ | | ");
    putstr(&"\n| | |  | |_| | | | |  | |  \\ \\| ____| |   | | | | ____| | ");
    putstr(&"\n|_|_|  \\____/|_| |_|  |_|   \\_\\_____)_|   |_| |_|_____)__)\n\n");
}

pub unsafe fn init() {
	buffer = cstr::new(256);
    screen();
   	putstr(&"\nsgash> ");
	//drawstr(&"\nsgash> ");
	buffer.reset();
}

pub unsafe fn echo() -> bool{
    let s = buffer.p as uint;
    let e = buffer.max;
    let mut i = 0;
    while i < e {
        let theChar : u8 = *((s+i) as *mut u8);
        if(theChar as char != '\0') {
            putchar(theChar as char);
            drawchar(theChar as char);
            i +=1;
        }
        else {
            drawstr(&"\n");
            putstr(&"\n");
            return true;
        }
    }
    return false;
}

struct cstr {
    p: *mut u8,
    p_cstr_i: uint,
    max: uint
}

impl cstr {

    pub unsafe fn new(size: uint) -> cstr {
        // Sometimes this doesn't allocate enough memory and gets stuck..

        let (x,y) = heap.alloc(size);

        let this = cstr {
            p: x,
            p_cstr_i: 0,
            max: y
        };
        *(((this.p as uint)+this.p_cstr_i) as *mut char) = '\0';
        this
    }

    #[allow(dead_code)]
    fn len(&self) -> uint {
        self.p_cstr_i
    }

    unsafe fn add_char(&mut self, x: u8) -> bool{
        //putstr("1");
        if (self.p_cstr_i == self.max) {
            return false;
        }
        //putstr("2");
        *(((self.p as uint)+self.p_cstr_i) as *mut u8) = x;
        //putstr("3");
        self.p_cstr_i += 1;
        *(((self.p as uint)+self.p_cstr_i) as *mut char) = '\0';
        //putstr("4");
        true
    }

    unsafe fn delete_char(&mut self) -> bool {
        if (self.p_cstr_i == 0) { return false; }
        self.p_cstr_i -= 1;
        *(((self.p as uint)+self.p_cstr_i) as *mut char) = '\0';
        true
    }

    unsafe fn reset(&mut self) {
        self.p_cstr_i = 0;
        *(self.p as *mut char) = '\0';
    }

    unsafe fn equals(&self, other: &str) -> bool {
    	// save val of self.p, which is u8, as a unit
    	let mut selfp: uint = self.p as uint;
    	// iterate through the str "other"
    	for c in slice::iter(as_bytes(other)){
    		// return false if any character does not match
    		if( *c != *(selfp as *u8) ) { return false; }
    		selfp += 1;
    	};
    	return true;
    	*(selfp as *char) == '\0'
    }

	unsafe fn getarg(&self, delim: char, mut k: uint) -> Option<cstr> {
		let mut ind: uint = 0;
		let mut found = k == 0;
		let mut selfp: uint = self.p as uint;
		let mut s = cstr::new(256);
		loop {
			if (*(selfp as *char) == '\0') {
				// End of string
				if (found) { return Some(s); }
				else { return None; }
			};
			if (*(selfp as *u8) == delim as u8) {
				if (found) { return Some(s); }
				k -= 1;
			};
			if (found) {
				s.add_char(*(selfp as *u8));
			};
			found = k == 0;
			selfp += 1;
			ind += 1;
			if (ind == self.max) {
				putstr(&"\nSomething broke!");
				return None;
			}
		}
	}
}<|endoftext|>


<commit_before>#![cfg(target_os = "linux")]

use BuilderAttribs;
use CreationError;
use GlRequest;
use Api;

use libc;
use std::ffi::CString;
use std::{mem, ptr};

pub mod ffi;

pub struct Context {
    egl: ffi::egl::Egl,
    display: ffi::egl::types::EGLDisplay,
    context: ffi::egl::types::EGLContext,
    surface: ffi::egl::types::EGLSurface,
}

impl Context {
    pub fn new(egl: ffi::egl::Egl, builder: BuilderAttribs,
               native_display: Option<ffi::EGLNativeDisplayType>,
               native_window: ffi::EGLNativeWindowType) -> Result<Context, CreationError>
    {
        if builder.sharing.is_some() {
            unimplemented!()
        }

        let display = unsafe {
            let display = egl.GetDisplay(native_display.unwrap_or(mem::transmute(ffi::egl::DEFAULT_DISPLAY)));
            if display.is_null() {
                return Err(CreationError::OsError("No EGL display connection available".to_string()));
            }
            display
        };

        let (_major, _minor) = unsafe {
            let mut major: ffi::egl::types::EGLint = mem::uninitialized();
            let mut minor: ffi::egl::types::EGLint = mem::uninitialized();

            if egl.Initialize(display, &mut major, &mut minor) == 0 {
                return Err(CreationError::OsError(format!("eglInitialize failed")))
            }

            (major, minor)
        };

        let use_gles2 = match builder.gl_version {
            GlRequest::Specific(Api::OpenGlEs, (2, _)) => true,
            GlRequest::Specific(Api::OpenGlEs, _) => false,
            GlRequest::Specific(_, _) => return Err(CreationError::NotSupported),
            GlRequest::GlThenGles { opengles_version: (2, _), .. } => true,
            _ => false,
        };

        let mut attribute_list = vec!();
        attribute_list.push(ffi::egl::RENDERABLE_TYPE as i32);
        attribute_list.push(ffi::egl::OPENGL_ES2_BIT as i32);

        attribute_list.push(ffi::egl::CONFORMANT as i32);
        attribute_list.push(ffi::egl::OPENGL_ES2_BIT as i32);

        attribute_list.push(ffi::egl::SURFACE_TYPE as i32);
        attribute_list.push(ffi::egl::WINDOW_BIT as i32);

        {
            let (red, green, blue) = match builder.color_bits.unwrap_or(24) {
                24 => (8, 8, 8),
                16 => (6, 5, 6),
                _ => panic!("Bad color_bits"),
            };

            attribute_list.push(ffi::egl::RED_SIZE as i32);
            attribute_list.push(red);
            attribute_list.push(ffi::egl::GREEN_SIZE as i32);
            attribute_list.push(green);
            attribute_list.push(ffi::egl::BLUE_SIZE as i32);
            attribute_list.push(blue);
        }

        attribute_list.push(ffi::egl::DEPTH_SIZE as i32);
        attribute_list.push(builder.depth_bits.unwrap_or(8) as i32);

        attribute_list.push(ffi::egl::NONE as i32);

        let config = unsafe {
            let mut num_config: ffi::egl::types::EGLint = mem::uninitialized();
            let mut config: ffi::egl::types::EGLConfig = mem::uninitialized();
            if egl.ChooseConfig(display, attribute_list.as_ptr(), &mut config, 1,
                                &mut num_config) == 0
            {
                return Err(CreationError::OsError(format!("eglChooseConfig failed")))
            }

            if num_config <= 0 {
                return Err(CreationError::OsError(format!("eglChooseConfig returned no available config")))
            }

            config
        };

        let surface = unsafe {
            let surface = egl.CreateWindowSurface(display, config, native_window, ptr::null());
            if surface.is_null() {
                return Err(CreationError::OsError(format!("eglCreateWindowSurface failed")))
            }
            surface
        };

        let context = unsafe {
            let mut context_attributes = vec!();
            context_attributes.push(ffi::egl::CONTEXT_CLIENT_VERSION as i32);
            context_attributes.push(2);
            context_attributes.push(ffi::egl::NONE as i32);

            let context = egl.CreateContext(display, config, ptr::null(),
                                            context_attributes.as_ptr());
            if context.is_null() {
                return Err(CreationError::OsError(format!("eglCreateContext failed")))
            }
            context
        };

        Ok(Context {
            egl: egl,
            display: display,
            context: context,
            surface: surface,
        })
    }

    pub fn make_current(&self) {
        let ret = unsafe {
            self.egl.MakeCurrent(self.display, self.surface, self.surface, self.context)
        };

        if ret == 0 {
            panic!("eglMakeCurrent failed");
        }
    }

    pub fn is_current(&self) -> bool {
        unsafe { self.egl.GetCurrentContext() == self.context }
    }

    pub fn get_proc_address(&self, addr: &str) -> *const () {
        let addr = CString::new(addr.as_bytes()).unwrap();
        let addr = addr.as_ptr();
        unsafe {
            self.egl.GetProcAddress(addr) as *const ()
        }
    }

    pub fn swap_buffers(&self) {
        let ret = unsafe {
            self.egl.SwapBuffers(self.display, self.surface)
        };

        if ret == 0 {
            panic!("eglSwapBuffers failed");
        }
    }

    pub fn get_api(&self) -> ::Api {
        ::Api::OpenGlEs
    }
}

unsafe impl Send for Context {}
unsafe impl Sync for Context {}

impl Drop for Context {
    fn drop(&mut self) {
        use std::ptr;

        unsafe {
            // we don't call MakeCurrent(0, 0) because we are not sure that the context
            // is still the current one
            self.egl.DestroyContext(self.display, self.context);
            self.egl.DestroySurface(self.display, self.surface);
            self.egl.Terminate(self.display);
        }
    }
}
<commit_msg>Rework EGL<commit_after>#![cfg(target_os = "linux")]

use BuilderAttribs;
use CreationError;
use GlRequest;
use PixelFormat;
use Api;

use libc;
use std::ffi::CString;
use std::{mem, ptr};

pub mod ffi;

pub struct Context {
    egl: ffi::egl::Egl,
    display: ffi::egl::types::EGLDisplay,
    context: ffi::egl::types::EGLContext,
    surface: ffi::egl::types::EGLSurface,
    api: Api,
    pixel_format: PixelFormat,
}

impl Context {
    pub fn new(egl: ffi::egl::Egl, builder: BuilderAttribs,
               native_display: Option<ffi::EGLNativeDisplayType>,
               native_window: ffi::EGLNativeWindowType) -> Result<Context, CreationError>
    {
        if builder.sharing.is_some() {
            unimplemented!()
        }

        let display = unsafe {
            let display = egl.GetDisplay(native_display.unwrap_or(mem::transmute(ffi::egl::DEFAULT_DISPLAY)));
            if display.is_null() {
                return Err(CreationError::OsError("No EGL display connection available".to_string()));
            }
            display
        };

        let egl_version = unsafe {
            let mut major: ffi::egl::types::EGLint = mem::uninitialized();
            let mut minor: ffi::egl::types::EGLint = mem::uninitialized();

            if egl.Initialize(display, &mut major, &mut minor) == 0 {
                return Err(CreationError::OsError(format!("eglInitialize failed")))
            }

            (major, minor)
        };

        // binding the right API and choosing the version
        let (version, api) = unsafe {
            match builder.gl_version {
                GlRequest::Latest => {
                    if egl_version >= (1, 4) {
                        if egl.BindAPI(ffi::egl::OPENGL_API) != 0 {
                            (None, Api::OpenGl)
                        } else if egl.BindAPI(ffi::egl::OPENGL_ES_API) != 0 {
                            (None, Api::OpenGlEs)
                        } else {
                            return Err(CreationError::NotSupported);
                        }
                    } else {
                        (None, Api::OpenGlEs)
                    }
                },
                GlRequest::Specific(Api::OpenGlEs, version) => {
                    if egl_version >= (1, 2) {
                        if egl.BindAPI(ffi::egl::OPENGL_ES_API) == 0 {
                            return Err(CreationError::NotSupported);
                        }
                    }
                    (Some(version), Api::OpenGlEs)
                },
                GlRequest::Specific(Api::OpenGl, version) => {
                    if egl_version < (1, 4) {
                        return Err(CreationError::NotSupported);
                    }
                    if egl.BindAPI(ffi::egl::OPENGL_API) == 0 {
                        return Err(CreationError::NotSupported);
                    }
                    (Some(version), Api::OpenGl)
                },
                GlRequest::Specific(_, _) => return Err(CreationError::NotSupported),
                GlRequest::GlThenGles { opengles_version, opengl_version } => {
                    if egl_version >= (1, 4) {
                        if egl.BindAPI(ffi::egl::OPENGL_API) != 0 {
                            (Some(opengl_version), Api::OpenGl)
                        } else if egl.BindAPI(ffi::egl::OPENGL_ES_API) != 0 {
                            (Some(opengles_version), Api::OpenGlEs)
                        } else {
                            return Err(CreationError::NotSupported);
                        }
                    } else {
                        (Some(opengles_version), Api::OpenGlEs)
                    }
                },
            }
        };

        let configs = unsafe { try!(enumerate_configs(&egl, display, &egl_version, api, version)) };
        let (config_id, pixel_format) = try!(builder.choose_pixel_format(configs.into_iter()));

        let surface = unsafe {
            let surface = egl.CreateWindowSurface(display, config_id, native_window, ptr::null());
            if surface.is_null() {
                return Err(CreationError::OsError(format!("eglCreateWindowSurface failed")))
            }
            surface
        };

        let context = unsafe {
            if let Some(version) = version {
                try!(create_context(&egl, display, &egl_version, api, version, config_id,
                                    builder.gl_debug).map_err(|_| CreationError::NotSupported))

            } else if api == Api::OpenGlEs {
                if let Ok(ctxt) = create_context(&egl, display, &egl_version, api, (2, 0),
                                                 config_id, builder.gl_debug)
                {
                    ctxt
                } else if let Ok(ctxt) = create_context(&egl, display, &egl_version, api, (1, 0),
                                                        config_id, builder.gl_debug)
                {
                    ctxt
                } else {
                    return Err(CreationError::NotSupported);
                }

            } else {
                if let Ok(ctxt) = create_context(&egl, display, &egl_version, api, (3, 2),
                                                 config_id, builder.gl_debug)
                {
                    ctxt
                } else if let Ok(ctxt) = create_context(&egl, display, &egl_version, api, (3, 1),
                                                        config_id, builder.gl_debug)
                {
                    ctxt
                } else if let Ok(ctxt) = create_context(&egl, display, &egl_version, api, (1, 0),
                                                        config_id, builder.gl_debug)
                {
                    ctxt
                } else {
                    return Err(CreationError::NotSupported);
                }
            }
        };

        Ok(Context {
            egl: egl,
            display: display,
            context: context,
            surface: surface,
            api: api,
            pixel_format: pixel_format,
        })
    }

    pub fn make_current(&self) {
        let ret = unsafe {
            self.egl.MakeCurrent(self.display, self.surface, self.surface, self.context)
        };

        if ret == 0 {
            panic!("eglMakeCurrent failed");
        }
    }

    pub fn get_pixel_format(&self) -> &PixelFormat {
        &self.pixel_format
    }

    pub fn is_current(&self) -> bool {
        unsafe { self.egl.GetCurrentContext() == self.context }
    }

    pub fn get_proc_address(&self, addr: &str) -> *const () {
        let addr = CString::new(addr.as_bytes()).unwrap();
        let addr = addr.as_ptr();
        unsafe {
            self.egl.GetProcAddress(addr) as *const ()
        }
    }

    pub fn swap_buffers(&self) {
        let ret = unsafe {
            self.egl.SwapBuffers(self.display, self.surface)
        };

        if ret == 0 {
            panic!("eglSwapBuffers failed");
        }
    }

    pub fn get_api(&self) -> Api {
        self.api
    }
}

unsafe impl Send for Context {}
unsafe impl Sync for Context {}

impl Drop for Context {
    fn drop(&mut self) {
        use std::ptr;

        unsafe {
            // we don't call MakeCurrent(0, 0) because we are not sure that the context
            // is still the current one
            self.egl.DestroyContext(self.display, self.context);
            self.egl.DestroySurface(self.display, self.surface);
            self.egl.Terminate(self.display);
        }
    }
}

unsafe fn enumerate_configs(egl: &ffi::egl::Egl, display: ffi::egl::types::EGLDisplay,
                            egl_version: &(ffi::egl::types::EGLint, ffi::egl::types::EGLint),
                            api: Api, version: Option<(u8, u8)>)
                            -> Result<Vec<(ffi::egl::types::EGLConfig, PixelFormat)>, CreationError>
{
    let mut num_configs = mem::uninitialized();
    if egl.GetConfigs(display, ptr::null_mut(), 0, &mut num_configs) == 0 {
        return Err(CreationError::OsError(format!("eglGetConfigs failed")));
    }

    let mut configs_ids = Vec::with_capacity(num_configs as usize);
    if egl.GetConfigs(display, configs_ids.as_mut_ptr(),
                      configs_ids.capacity() as ffi::egl::types::EGLint,
                      &mut num_configs) == 0
    {
        return Err(CreationError::OsError(format!("eglGetConfigs failed")));
    }
    configs_ids.set_len(num_configs as usize);

    // analyzing each config
    let mut result = Vec::with_capacity(num_configs as usize);
    for config_id in configs_ids {
        macro_rules! attrib {
            ($egl:expr, $display:expr, $config:expr, $attr:expr) => (
                {
                    let mut value = mem::uninitialized();
                    let res = $egl.GetConfigAttrib($display, $config,
                                                   $attr as ffi::egl::types::EGLint, &mut value);
                    if res == 0 {
                        return Err(CreationError::OsError(format!("eglGetConfigAttrib failed")));
                    }
                    value
                }
            )
        };

        let renderable = attrib!(egl, display, config_id, ffi::egl::RENDERABLE_TYPE) as u32;
        let conformant = attrib!(egl, display, config_id, ffi::egl::CONFORMANT) as u32;

        if api == Api::OpenGlEs {
            if let Some(version) = version {
                if version.0 == 3 && (renderable & ffi::egl::OPENGL_ES3_BIT == 0 ||
                                      conformant & ffi::egl::OPENGL_ES3_BIT == 0)
                {
                    continue;
                }

                if version.0 == 2 && (renderable & ffi::egl::OPENGL_ES2_BIT == 0 ||
                                      conformant & ffi::egl::OPENGL_ES2_BIT == 0)
                {
                    continue;
                }

                if version.0 == 1 && (renderable & ffi::egl::OPENGL_ES_BIT == 0 ||
                                      conformant & ffi::egl::OPENGL_ES_BIT == 0)
                {
                    continue;
                }
            }

        } else if api == Api::OpenGl {
            if renderable & ffi::egl::OPENGL_BIT == 0 ||
               conformant & ffi::egl::OPENGL_BIT == 0
            {
                continue;
            }
        }

        if attrib!(egl, display, config_id, ffi::egl::SURFACE_TYPE) & ffi::egl::WINDOW_BIT as i32 == 0 {
            continue;
        }

        if attrib!(egl, display, config_id, ffi::egl::TRANSPARENT_TYPE) != ffi::egl::NONE as i32 {
            continue;
        }

        if attrib!(egl, display, config_id, ffi::egl::COLOR_BUFFER_TYPE) != ffi::egl::RGB_BUFFER as i32 {
            continue;
        }

        result.push((config_id, PixelFormat {
            hardware_accelerated: attrib!(egl, display, config_id, ffi::egl::CONFIG_CAVEAT)
                                          != ffi::egl::SLOW_CONFIG as i32,
            red_bits: attrib!(egl, display, config_id, ffi::egl::RED_SIZE) as u8,
            green_bits: attrib!(egl, display, config_id, ffi::egl::BLUE_SIZE) as u8,
            blue_bits: attrib!(egl, display, config_id, ffi::egl::GREEN_SIZE) as u8,
            alpha_bits: attrib!(egl, display, config_id, ffi::egl::ALPHA_SIZE) as u8,
            depth_bits: attrib!(egl, display, config_id, ffi::egl::DEPTH_SIZE) as u8,
            stencil_bits: attrib!(egl, display, config_id, ffi::egl::STENCIL_SIZE) as u8,
            stereoscopy: false,
            double_buffer: true,
            multisampling: match attrib!(egl, display, config_id, ffi::egl::SAMPLES) {
                0 | 1 => None,
                a => Some(a as u16),
            },
            srgb: false,        // TODO: use EGL_KHR_gl_colorspace to know that
        }));
    }

    Ok(result)
}

unsafe fn create_context(egl: &ffi::egl::Egl, display: ffi::egl::types::EGLDisplay,
                         egl_version: &(ffi::egl::types::EGLint, ffi::egl::types::EGLint),
                         api: Api, version: (u8, u8), config_id: ffi::egl::types::EGLConfig,
                         gl_debug: bool)
                         -> Result<ffi::egl::types::EGLContext, ()>
{
    let mut context_attributes = vec![];

    if egl_version >= &(1, 5) {
        context_attributes.push(ffi::egl::CONTEXT_MAJOR_VERSION as i32);
        context_attributes.push(version.0 as i32);
        context_attributes.push(ffi::egl::CONTEXT_MINOR_VERSION as i32);
        context_attributes.push(version.1 as i32);

        if gl_debug {
            context_attributes.push(ffi::egl::CONTEXT_OPENGL_DEBUG as i32);
            context_attributes.push(ffi::egl::TRUE as i32);
        }

    } else {
        if api == Api::OpenGlEs {
            context_attributes.push(ffi::egl::CONTEXT_CLIENT_VERSION as i32);
            context_attributes.push(version.0 as i32);
        }
    }

    context_attributes.push(ffi::egl::NONE as i32);

    let context = egl.CreateContext(display, config_id, ptr::null(),
                                    context_attributes.as_ptr());

    if context.is_null() {
        return Err(());
    }

    Ok(context)
}
<|endoftext|>


<commit_before>// This file is part of libfringe, a low-level green threading library.
// Copyright (c) edef <edef@edef.eu>,
//               whitequark <whitequark@whitequark.org>
// See the LICENSE file included in this distribution.

//! To understand the code in this file, keep in mind these two facts:
//! * x86_64 SysV C ABI has a "red zone": 128 bytes under the top of the stack
//!   that is defined to be unmolested by signal handlers, interrupts, etc.
//!   Leaf functions can use the red zone without adjusting rsp or rbp.
//! * x86_64 SysV C ABI requires the stack to be aligned at function entry,
//!   so that (%rsp+8) is a multiple of 16. Aligned operands are a requirement
//!   of SIMD instructions, and making this the responsibility of the caller
//!   avoids having to maintain a frame pointer, which is necessary when
//!   a function has to realign the stack from an unknown state.
//! * x86_64 SysV C ABI passes the first argument in %rdi. We also use %rdi
//!   to pass a value while swapping context; this is an arbitrary choice
//!   (we clobber all registers and could use any of them) but this allows us
//!   to reuse the swap function to perform the initial call.

use stack::Stack;

#[derive(Debug)]
pub struct StackPointer(*mut usize);

impl StackPointer {
  unsafe fn new(stack: &Stack) -> StackPointer {
    StackPointer(stack.top() as *mut usize)
  }

  unsafe fn push(&mut self, val: usize) {
    self.0 = self.0.offset(-1);
    *self.0 = val
  }
}

pub unsafe fn init(stack: &Stack, f: unsafe extern "C" fn(usize) -> !) -> StackPointer {
  let mut sp = StackPointer::new(stack);
  sp.push(0); // alignment
  sp.push(f as usize);
  sp
}

#[inline(always)]
pub unsafe fn swap(arg: usize, old_sp: &mut StackPointer, new_sp: &StackPointer) -> usize {
  let ret: usize;
  asm!(
    r#"
      # Save frame pointer explicitly; LLVM doesn't spill it even if it is
      # marked as clobbered.
      pushq   %rbp
      # Push instruction pointer of the old context and switch to
      # the new context.
      call    1f
      # Restore frame pointer.
      popq    %rbp
      # Continue executing old context.
      jmp     2f

    1:
      # Remember stack pointer of the old context, in case %rdx==%rsi.
      movq    %rsp, %rbx
      # Load stack pointer of the new context.
      movq    (%rdx), %rsp
      # Save stack pointer of the old context.
      movq    %rbx, (%rsi)

      # Pop instruction pointer of the new context (placed onto stack by
      # the call above) and jump there; don't use `ret` to avoid return
      # address mispredictions (~8ns on Ivy Bridge).
      popq    %rbx
      jmpq    *%rbx
    2:
    "#
    : "={rdi}" (ret)
    : "{rdi}" (arg)
      "{rsi}" (old_sp)
      "{rdx}" (new_sp)
    : "rax",   "rbx",   "rcx",   "rdx",   "rsi",   "rdi", //"rbp",   "rsp",
      "r8",    "r9",    "r10",   "r11",   "r12",   "r13",   "r14",   "r15",
      "xmm0",  "xmm1",  "xmm2",  "xmm3",  "xmm4",  "xmm5",  "xmm6",  "xmm7",
      "xmm8",  "xmm9",  "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15",
      "xmm16", "xmm17", "xmm18", "xmm19", "xmm20", "xmm21", "xmm22", "xmm23",
      "xmm24", "xmm25", "xmm26", "xmm27", "xmm28", "xmm29", "xmm30", "xmm31"
      "cc", "fpsr", "flags", "memory"
      // Ideally, we would set the LLVM "noredzone" attribute on this function
      // (and it would be propagated to the call site). Unfortunately, rustc
      // provides no such functionality. Fortunately, by a lucky coincidence,
      // the "alignstack" LLVM inline assembly option does exactly the same
      // thing on x86_64.
    : "volatile", "alignstack");
  ret
}
<commit_msg>Fix Windows x64 ABI<commit_after>// This file is part of libfringe, a low-level green threading library.
// Copyright (c) edef <edef@edef.eu>,
//               whitequark <whitequark@whitequark.org>
// See the LICENSE file included in this distribution.

//! To understand the code in this file, keep in mind these two facts:
//! * x86_64 SysV C ABI has a "red zone": 128 bytes under the top of the stack
//!   that is defined to be unmolested by signal handlers, interrupts, etc.
//!   Leaf functions can use the red zone without adjusting rsp or rbp.
//! * x86_64 SysV C ABI requires the stack to be aligned at function entry,
//!   so that (%rsp+8) is a multiple of 16. Aligned operands are a requirement
//!   of SIMD instructions, and making this the responsibility of the caller
//!   avoids having to maintain a frame pointer, which is necessary when
//!   a function has to realign the stack from an unknown state.
//! * x86_64 SysV C ABI passes the first argument in %rdi. We also use %rdi
//!   to pass a value while swapping context; this is an arbitrary choice
//!   (we clobber all registers and could use any of them) but this allows us
//!   to reuse the swap function to perform the initial call.

use stack::Stack;

#[derive(Debug)]
pub struct StackPointer(*mut usize);

impl StackPointer {
  unsafe fn new(stack: &Stack) -> StackPointer {
    StackPointer(stack.top() as *mut usize)
  }

  unsafe fn push(&mut self, val: usize) {
    self.0 = self.0.offset(-1);
    *self.0 = val
  }
}

pub unsafe fn init(stack: &Stack, f: unsafe extern "C" fn(usize) -> !) -> StackPointer {
  let mut sp = StackPointer::new(stack);
  sp.push(0); // alignment
  sp.push(f as usize);
  sp
}

#[inline(always)]
pub unsafe fn swap(arg: usize, old_sp: &mut StackPointer, new_sp: &StackPointer) -> usize {
  macro_rules! swap_body {
    () => {
      r#"
        # Save frame pointer explicitly; LLVM doesn't spill it even if it is
        # marked as clobbered.
        pushq   %rbp
        # Push instruction pointer of the old context and switch to
        # the new context.
        call    1f
        # Restore frame pointer.
        popq    %rbp
        # Continue executing old context.
        jmp     2f

      1:
        # Remember stack pointer of the old context, in case %rdx==%rsi.
        movq    %rsp, %rbx
        # Load stack pointer of the new context.
        movq    (%rdx), %rsp
        # Save stack pointer of the old context.
        movq    %rbx, (%rsi)

        # Pop instruction pointer of the new context (placed onto stack by
        # the call above) and jump there; don't use `ret` to avoid return
        # address mispredictions (~8ns on Ivy Bridge).
        popq    %rbx
        jmpq    *%rbx
      2:
      "#
    }
  }

  #[cfg(not(windows))]
  #[inline(always)]
  unsafe fn swap_impl(arg: usize, old_sp: &mut StackPointer, new_sp: &StackPointer) -> usize {
    let ret: usize;
    asm!(swap_body!()
      : "={rdi}" (ret)
      : "{rdi}" (arg)
        "{rsi}" (old_sp)
        "{rdx}" (new_sp)
      : "rax",   "rbx",   "rcx",   "rdx",   "rsi",   "rdi", //"rbp",   "rsp",
        "r8",    "r9",    "r10",   "r11",   "r12",   "r13",   "r14",   "r15",
        "xmm0",  "xmm1",  "xmm2",  "xmm3",  "xmm4",  "xmm5",  "xmm6",  "xmm7",
        "xmm8",  "xmm9",  "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15",
        "xmm16", "xmm17", "xmm18", "xmm19", "xmm20", "xmm21", "xmm22", "xmm23",
        "xmm24", "xmm25", "xmm26", "xmm27", "xmm28", "xmm29", "xmm30", "xmm31"
        "cc", "fpsr", "flags", "memory"
        // Ideally, we would set the LLVM "noredzone" attribute on this function
        // (and it would be propagated to the call site). Unfortunately, rustc
        // provides no such functionality. Fortunately, by a lucky coincidence,
        // the "alignstack" LLVM inline assembly option does exactly the same
        // thing on x86_64.
      : "volatile", "alignstack");
    ret
  }

  #[cfg(windows)]
  #[inline(always)]
  unsafe fn swap_impl(arg: usize, old_sp: &mut StackPointer, new_sp: &StackPointer) -> usize {
    let ret: usize;
    asm!(swap_body!()
      : "={rcx}" (ret)
      : "{rcx}" (arg)
        "{rsi}" (old_sp)
        "{rdx}" (new_sp)
      : "rax",   "rbx",   "rcx",   "rdx",   "rsi",   "rdi", //"rbp",   "rsp",
        "r8",    "r9",    "r10",   "r11",   "r12",   "r13",   "r14",   "r15",
        "xmm0",  "xmm1",  "xmm2",  "xmm3",  "xmm4",  "xmm5",  "xmm6",  "xmm7",
        "xmm8",  "xmm9",  "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15",
        "xmm16", "xmm17", "xmm18", "xmm19", "xmm20", "xmm21", "xmm22", "xmm23",
        "xmm24", "xmm25", "xmm26", "xmm27", "xmm28", "xmm29", "xmm30", "xmm31"
        "cc", "fpsr", "flags", "memory"
        // Ideally, we would set the LLVM "noredzone" attribute on this function
        // (and it would be propagated to the call site). Unfortunately, rustc
        // provides no such functionality. Fortunately, by a lucky coincidence,
        // the "alignstack" LLVM inline assembly option does exactly the same
        // thing on x86_64.
      : "volatile", "alignstack");
    ret
  }

  swap_impl(arg, old_sp, new_sp)
}
<|endoftext|>


<commit_before>//! Awesome compatibilty modules
use xcb::{xkb, Connection};

use rlua::{self, Lua, Table, LightUserData};

use std::mem;

pub mod keygrabber;
pub mod mousegrabber;
//pub mod awful;
//mod awesome;
//mod client;
mod screen;
mod button;
//mod tag;
//mod key;
//mod drawin;
//mod drawable;
//mod mouse;
//mod root;
pub mod signal;
mod object;
mod class;
mod property;
mod xproperty;

pub use self::object::Object;
pub use self::keygrabber::keygrabber_handle;
pub use self::mousegrabber::mousegrabber_handle;

pub const GLOBAL_SIGNALS: &'static str = "__awesome_global_signals";
pub const XCB_CONNECTION_HANDLE: &'static str = "__xcb_connection";

use std::env;
use std::path::PathBuf;

pub fn init(lua: &Lua) -> rlua::Result<()> {
    setup_awesome_path(lua)?;
    setup_global_signals(lua)?;
    setup_xcb_connection(lua)?;
    button::init(lua)?;
    //awesome::init(lua)?;
    //key::init(lua)?;
    //client::init(lua)?;
    screen::init(lua)?;
    keygrabber::init(lua)?;
    //root::init(lua)?;
    //mouse::init(lua)?;
    //tag::init(lua)?;
    //drawin::init(lua)?;
    //drawable::init(lua)?;
    mousegrabber::init(lua)?;
    //awful::init(lua)?;
    Ok(())
}

fn setup_awesome_path(lua: &Lua) -> rlua::Result<()> {
    let globals = lua.globals();
    let package: Table = globals.get("package")?;
    let mut path = package.get::<_, String>("path")?;
    let mut cpath = package.get::<_, String>("cpath")?;
    let mut xdg_data_path: PathBuf = env::var("XDG_DATA_DIRS").unwrap_or("/usr/share".into()).into();
    xdg_data_path.push("awesome/lib");
    path.push_str(&format!(";{0}/?.lua;{0}/?/init.lua",
                             xdg_data_path.as_os_str().to_string_lossy()));
    package.set("path", path)?;
    let mut xdg_config_path: PathBuf = env::var("XDG_CONFIG_DIRS").unwrap_or("/etc/xdg".into()).into();
    xdg_config_path.push("awesome");
    cpath.push_str(&format!(";{}/?.so;{}/?.so",
                            xdg_config_path.into_os_string().to_string_lossy(),
                            xdg_data_path.into_os_string().to_string_lossy()));
    package.set("cpath", cpath)?;

    Ok(())
}

/// Set up global signals value
///
/// We need to store this in Lua, because this make it safer to use.
fn setup_global_signals(lua: &Lua) -> rlua::Result<()> {
    let globals = lua.globals();
    globals.set::<_, Table>(GLOBAL_SIGNALS, lua.create_table()?)
}

/// Sets up the xcb connection and stores it in Lua (for us to access it later)
fn setup_xcb_connection(lua: &Lua) -> rlua::Result<()> {
    let con = match Connection::connect(None) {
        Err(err) => {
            error!("xcb: Could not connect to xwayland instance. Is it running?");
            error!("{:?}", err);
            return Ok(())
        },
        Ok(con) => con.0
    };
    // Tell xcb we are using the xkb extension
    match xkb::use_extension(&con, 1, 0).get_reply() {
        Ok(r) => {
            if !r.supported() {
                panic!("xkb-1.0 is not supported");
            }
        },
        Err(err) => {
            panic!("Could not get xkb extension supported version {:?}", err);
        }
    }
    lua.globals().set(XCB_CONNECTION_HANDLE, LightUserData(con.get_raw_conn() as _))?;
    mem::forget(con);
    Ok(())
}

pub fn dummy<'lua>(_: &'lua Lua, _: rlua::Value) -> rlua::Result<()> { Ok(()) }
<commit_msg>Awful and Awesome are untouched<commit_after>//! Awesome compatibilty modules
use xcb::{xkb, Connection};

use rlua::{self, Lua, Table, LightUserData};

use std::mem;

pub mod keygrabber;
pub mod mousegrabber;
pub mod awful;
mod awesome;
//mod client;
mod screen;
mod button;
//mod tag;
//mod key;
//mod drawin;
//mod drawable;
//mod mouse;
//mod root;
pub mod signal;
mod object;
mod class;
mod property;
mod xproperty;

pub use self::object::Object;
pub use self::keygrabber::keygrabber_handle;
pub use self::mousegrabber::mousegrabber_handle;

pub const GLOBAL_SIGNALS: &'static str = "__awesome_global_signals";
pub const XCB_CONNECTION_HANDLE: &'static str = "__xcb_connection";

use std::env;
use std::path::PathBuf;

pub fn init(lua: &Lua) -> rlua::Result<()> {
    setup_awesome_path(lua)?;
    setup_global_signals(lua)?;
    setup_xcb_connection(lua)?;
    button::init(lua)?;
    awesome::init(lua)?;
    //key::init(lua)?;
    //client::init(lua)?;
    screen::init(lua)?;
    keygrabber::init(lua)?;
    //root::init(lua)?;
    //mouse::init(lua)?;
    //tag::init(lua)?;
    //drawin::init(lua)?;
    //drawable::init(lua)?;
    mousegrabber::init(lua)?;
    awful::init(lua)?;
    Ok(())
}

fn setup_awesome_path(lua: &Lua) -> rlua::Result<()> {
    let globals = lua.globals();
    let package: Table = globals.get("package")?;
    let mut path = package.get::<_, String>("path")?;
    let mut cpath = package.get::<_, String>("cpath")?;
    let mut xdg_data_path: PathBuf = env::var("XDG_DATA_DIRS").unwrap_or("/usr/share".into()).into();
    xdg_data_path.push("awesome/lib");
    path.push_str(&format!(";{0}/?.lua;{0}/?/init.lua",
                             xdg_data_path.as_os_str().to_string_lossy()));
    package.set("path", path)?;
    let mut xdg_config_path: PathBuf = env::var("XDG_CONFIG_DIRS").unwrap_or("/etc/xdg".into()).into();
    xdg_config_path.push("awesome");
    cpath.push_str(&format!(";{}/?.so;{}/?.so",
                            xdg_config_path.into_os_string().to_string_lossy(),
                            xdg_data_path.into_os_string().to_string_lossy()));
    package.set("cpath", cpath)?;

    Ok(())
}

/// Set up global signals value
///
/// We need to store this in Lua, because this make it safer to use.
fn setup_global_signals(lua: &Lua) -> rlua::Result<()> {
    let globals = lua.globals();
    globals.set::<_, Table>(GLOBAL_SIGNALS, lua.create_table()?)
}

/// Sets up the xcb connection and stores it in Lua (for us to access it later)
fn setup_xcb_connection(lua: &Lua) -> rlua::Result<()> {
    let con = match Connection::connect(None) {
        Err(err) => {
            error!("xcb: Could not connect to xwayland instance. Is it running?");
            error!("{:?}", err);
            return Ok(())
        },
        Ok(con) => con.0
    };
    // Tell xcb we are using the xkb extension
    match xkb::use_extension(&con, 1, 0).get_reply() {
        Ok(r) => {
            if !r.supported() {
                panic!("xkb-1.0 is not supported");
            }
        },
        Err(err) => {
            panic!("Could not get xkb extension supported version {:?}", err);
        }
    }
    lua.globals().set(XCB_CONNECTION_HANDLE, LightUserData(con.get_raw_conn() as _))?;
    mem::forget(con);
    Ok(())
}

pub fn dummy<'lua>(_: &'lua Lua, _: rlua::Value) -> rlua::Result<()> { Ok(()) }
<|endoftext|>