<commit_before>
use std::marker::PhantomData;

use Construct;
use Data;
use Count;
use Of;
use Subspace;
use ToIndex;
use ToPos;
use Zero;

/// A discrete space that can model spatial operations over arbitrary states,
/// therefore useful for context analysis.
///
/// It can be constructed by taking a N-dimensional space,
/// for each dimension create a pair subspace and sum over the dimensions.
/// It can also be thought of as the edges in an undirected graph,
/// where each node is described by a N-dimensional coordinate,
/// and all nodes are connected which differ by one axis.
///
/// Dimensions of size 2 gives the edges on a hypercube of the number of dimensions.
/// For example, `[2, 2, 2]` gives edges on a cube in 3 dimensions.
pub struct Context<T = Data>(PhantomData<T>);

/// Computes subspace offset from which index that changes.
/// The space is divided into N subspaces,
/// because only one axis can change at a time.
///
/// ```ignore
/// [(a, x), b, c]
/// [a, (b, x), c]
/// [a, b, (c, x)]
/// ```
fn subspace_offset(v: &[usize], ind: usize) -> usize {
    use Pair;

    let pair: Pair<Data> = Construct::new();
    let mut sum = 0;
    for i in 0..ind {
        let mut prod = 1;
        for j in 0..v.len() {
            if i == j { continue; }
            prod *= v[j];
        }
        sum += pair.count(v[i]) * prod;
    }
    sum
}

/// Computes the index of the axis that changes from index position.
/// This works because the layout are separated by which
/// axis that changes, and the subspace offset can be computed.
/// Returns `(ind, offset)`
fn ind_from_index(v: &[usize], index: usize) -> (usize, usize) {
    use Pair;

    let pair: Pair<Data> = Construct::new();
    let mut sum = 0;
    for i in 0..v.len() {
        let mut prod = 1;
        for j in 0..v.len() {
            if i == j { continue; }
            prod *= v[j];
        }
        let add = pair.count(v[i]) * prod;
        if sum + add > index { return (i, sum); }
        sum += add;
    }
    (v.len(), sum)
}

impl<T> Construct for Context<T> {
    fn new() -> Context<T> { Context(PhantomData) }
}

impl<'a> Count<&'a [usize]> for Context<Data> {
    fn count(&self, dim: &'a [usize]) -> usize {
        use Pair;

        let pair: Pair<Data> = Construct::new();
        let mut sum = pair.count(dim[0]);
        let mut prod = dim[0];
        for &d in &dim[1..] {
            sum = d * sum + pair.count(d) * prod;
            prod *= d;
        }
        sum
    }
}

impl<'a, T, U> Count<(&'a [usize], U)> for Context<Subspace<T>>
    where
        T: Construct + Count<U>
{
    fn count(&self, (n, dim): (&'a [usize], U)) -> usize {
        let sub: T = Construct::new();
        let data: Context<Data> = Construct::new();
        data.count(n) * sub.count(dim)
    }
}

impl<'a, T, U> Count<&'a [U]> for Context<Of<T>>
    where
        T: Construct + Count<U>,
        U: Copy
{
    fn count(&self, dim: &'a [U]) -> usize {
        use Pair;

        let of: T = Construct::new();
        let pair: Pair<Data> = Construct::new();
        let mut sum = pair.count(of.count(dim[0]));
        let mut prod = of.count(dim[0]);
        for &d in &dim[1..] {
            let d = of.count(d);
            sum = d * sum + pair.count(d) * prod;
            prod *= d;
        }
        sum
    }
}

impl<'a> Zero<&'a [usize], (Vec<usize>, usize, usize)> for Context<Data> {
    fn zero(&self, dim: &'a [usize]) -> (Vec<usize>, usize, usize) {
        (vec![0; dim.len()], 0, 0)
    }
}

impl<'a> ToIndex<&'a [usize], (&'a [usize], usize, usize)> for Context<Data> {
    fn to_index(&self, dim: &'a [usize], (p, ind, b): (&'a [usize], usize, usize)) -> usize {
        use std::cmp::{ min, max };
        use Pair;

        let offset = subspace_offset(dim, ind);
        let pair: Pair<Data> = Construct::new();
        let mut prod = 1;
        for j in 0..dim.len() {
            if ind == j { continue; }
            prod *= dim[j];
        }
        // Pair doesn't care about dimension.
        let single = pair.to_index(0, (min(p[ind], b), max(p[ind], b)));
        let pos_offset = single * prod;
        let mut dim_index = 0;
        for i in (0..p.len()).rev() {
            if ind == i { continue; }
            dim_index = dim_index * dim[i] + p[i];
        }
        offset + pos_offset + dim_index
    }
}

impl<'a, T, U, V>
ToIndex<((&'a [usize]), U), ((&'a [usize], usize, usize), V)>
for Context<Subspace<T>>
    where
        T: Construct + Count<U> + ToIndex<U, V>,
        U: Copy
{
    fn to_index(
        &self,
        (my_dim, dim): (&'a [usize], U),
        (my_pos, pos): ((&'a [usize], usize, usize), V)
    ) -> usize {
        let subspace: T = Construct::new();
        let count = subspace.count(dim);
        let data: Context<Data> = Construct::new();
        data.to_index(my_dim, my_pos) * count + subspace.to_index(dim, pos)
    }
}

impl<'a> ToPos<&'a [usize], (Vec<usize>, usize, usize)> for Context<Data> {
    fn to_pos(
        &self,
        dim: &'a [usize],
        index: usize,
        &mut (ref mut p, ref mut ind, ref mut b): &mut (Vec<usize>, usize, usize)
    ) {
        use Pair;

        p.clear();
        let pair_space: Pair<Data> = Construct::new();
        let (ind_val, offset) = ind_from_index(dim, index);
        // Get rid of offset.
        // The rest equals: single * prod + dim_index
        let index = index - offset;
        let mut prod = 1;
        for j in 0..dim.len() {
            p.push(0); // zero position
            if ind_val == j { continue; }
            prod *= dim[j];
        }
        let single = index / prod;

        let mut pair = (0, 0);
        // Pair doesn't care about dimension.
        pair_space.to_pos(0, single, &mut pair);
        let (min, max) = pair;

        // Resolve other dimension components.
        let mut dim_index = index - single * prod;
        for i in (0..p.len()).rev() {
            if ind_val == i { continue; }
            prod /= dim[i];
            let p_i = dim_index / prod;
            p[i] = p_i;
            dim_index -= p_i * prod;
        }
        p[ind_val] = min;
        *b = max;
        *ind = ind_val;

    }
}

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

    #[test]
    fn features() {
        does_count::<Context, &[usize]>();
        does_count::<Context<Subspace<Pair>>, (&[usize], usize)>();
        does_count::<Context<Of<Pair>>, &[usize]>();
        does_to_index::<Context, &[usize], (&[usize], usize, usize)>();
        does_to_index::<Context<Subspace<Pair>>, (&[usize], usize),
            ((&[usize], usize, usize), (usize, usize))>();
    }

    #[test]
    fn data() {
        let x: Context = Construct::new();
        let dim = &[2, 2, 2];
        // 12 edges on a cube
        assert_eq!(x.count(dim), 12);
        assert_eq!(x.to_index(dim, (&[0, 0, 0], 0, 1)), 0);
        for i in 0..x.count(dim) {
            let mut pos = (vec![], 0, 0);
            x.to_pos(dim, i, &mut pos);
            assert_eq!(x.to_index(dim, (&pos.0, pos.1, pos.2)), i);
        }
    }

    #[test]
    fn subspace() {
        let x: Context<Subspace<Pair>> = Construct::new();
        let dim = (&*vec![2, 2], 3);
        assert_eq!(x.to_index(dim, ((&[0, 0], 0, 1), (0, 1))), 0);
        assert_eq!(x.to_index(dim, ((&[0, 0], 0, 1), (0, 2))), 1);
        assert_eq!(x.to_index(dim, ((&[0, 0], 0, 1), (1, 2))), 2);
        assert_eq!(x.to_index(dim, ((&[0, 1], 0, 1), (0, 1))), 3);
        assert_eq!(x.to_index(dim, ((&[0, 1], 0, 1), (0, 2))), 4);
        assert_eq!(x.to_index(dim, ((&[0, 1], 0, 1), (1, 2))), 5);
        assert_eq!(x.to_index(dim, ((&[0, 1], 1, 0), (0, 1))), 6);
    }

    #[test]
    fn of() {
        let x: Context<Of<Pair>> = Construct::new();
        let dim = &[3];
        assert_eq!(x.count(dim), 3);
        let dim = &[3, 3];
        assert_eq!(x.count(dim), 18);
    }
}
<commit_msg>Implemented `ToIndex` for `Context<Of<T>>`<commit_after>
use std::marker::PhantomData;

use Construct;
use Data;
use Count;
use Of;
use Subspace;
use ToIndex;
use ToPos;
use Zero;

/// A discrete space that can model spatial operations over arbitrary states,
/// therefore useful for context analysis.
///
/// It can be constructed by taking a N-dimensional space,
/// for each dimension create a pair subspace and sum over the dimensions.
/// It can also be thought of as the edges in an undirected graph,
/// where each node is described by a N-dimensional coordinate,
/// and all nodes are connected which differ by one axis.
///
/// Dimensions of size 2 gives the edges on a hypercube of the number of dimensions.
/// For example, `[2, 2, 2]` gives edges on a cube in 3 dimensions.
pub struct Context<T = Data>(PhantomData<T>);

/// Computes subspace offset from which index that changes.
/// The space is divided into N subspaces,
/// because only one axis can change at a time.
///
/// ```ignore
/// [(a, x), b, c]
/// [a, (b, x), c]
/// [a, b, (c, x)]
/// ```
fn subspace_offset(v: &[usize], ind: usize) -> usize {
    use Pair;

    let pair: Pair<Data> = Construct::new();
    let mut sum = 0;
    for i in 0..ind {
        let mut prod = 1;
        for j in 0..v.len() {
            if i == j { continue; }
            prod *= v[j];
        }
        sum += pair.count(v[i]) * prod;
    }
    sum
}

/// Computes the index of the axis that changes from index position.
/// This works because the layout are separated by which
/// axis that changes, and the subspace offset can be computed.
/// Returns `(ind, offset)`
fn ind_from_index(v: &[usize], index: usize) -> (usize, usize) {
    use Pair;

    let pair: Pair<Data> = Construct::new();
    let mut sum = 0;
    for i in 0..v.len() {
        let mut prod = 1;
        for j in 0..v.len() {
            if i == j { continue; }
            prod *= v[j];
        }
        let add = pair.count(v[i]) * prod;
        if sum + add > index { return (i, sum); }
        sum += add;
    }
    (v.len(), sum)
}

impl<T> Construct for Context<T> {
    fn new() -> Context<T> { Context(PhantomData) }
}

impl<'a> Count<&'a [usize]> for Context<Data> {
    fn count(&self, dim: &'a [usize]) -> usize {
        use Pair;

        let pair: Pair<Data> = Construct::new();
        let mut sum = pair.count(dim[0]);
        let mut prod = dim[0];
        for &d in &dim[1..] {
            sum = d * sum + pair.count(d) * prod;
            prod *= d;
        }
        sum
    }
}

impl<'a, T, U> Count<(&'a [usize], U)> for Context<Subspace<T>>
    where
        T: Construct + Count<U>
{
    fn count(&self, (n, dim): (&'a [usize], U)) -> usize {
        let sub: T = Construct::new();
        let data: Context<Data> = Construct::new();
        data.count(n) * sub.count(dim)
    }
}

impl<'a, T, U> Count<&'a [U]> for Context<Of<T>>
    where
        T: Construct + Count<U>,
        U: Copy
{
    fn count(&self, dim: &'a [U]) -> usize {
        use Pair;

        let of: T = Construct::new();
        let pair: Pair<Data> = Construct::new();
        let mut sum = pair.count(of.count(dim[0]));
        let mut prod = of.count(dim[0]);
        for &d in &dim[1..] {
            let d = of.count(d);
            sum = d * sum + pair.count(d) * prod;
            prod *= d;
        }
        sum
    }
}

impl<'a> Zero<&'a [usize], (Vec<usize>, usize, usize)> for Context<Data> {
    fn zero(&self, dim: &'a [usize]) -> (Vec<usize>, usize, usize) {
        (vec![0; dim.len()], 0, 0)
    }
}

impl<'a> ToIndex<&'a [usize], (&'a [usize], usize, usize)> for Context<Data> {
    fn to_index(
        &self,
        dim: &'a [usize],
        (p, ind, b): (&'a [usize], usize, usize)
    ) -> usize {
        use std::cmp::{ min, max };
        use Pair;

        let offset = subspace_offset(dim, ind);
        let pair: Pair<Data> = Construct::new();
        let mut prod = 1;
        for j in 0..dim.len() {
            if ind == j { continue; }
            prod *= dim[j];
        }
        // Pair doesn't care about dimension.
        let single = pair.to_index(0, (min(p[ind], b), max(p[ind], b)));
        let pos_offset = single * prod;
        let mut dim_index = 0;
        for i in (0..p.len()).rev() {
            if ind == i { continue; }
            dim_index = dim_index * dim[i] + p[i];
        }
        offset + pos_offset + dim_index
    }
}

impl<'a, T, U, V>
ToIndex<((&'a [usize]), U), ((&'a [usize], usize, usize), V)>
for Context<Subspace<T>>
    where
        T: Construct + Count<U> + ToIndex<U, V>,
        U: Copy
{
    fn to_index(
        &self,
        (my_dim, dim): (&'a [usize], U),
        (my_pos, pos): ((&'a [usize], usize, usize), V)
    ) -> usize {
        let subspace: T = Construct::new();
        let count = subspace.count(dim);
        let data: Context<Data> = Construct::new();
        data.to_index(my_dim, my_pos) * count + subspace.to_index(dim, pos)
    }
}

impl<'a, T, U, V> ToIndex<&'a [U], (&'a [V], usize, V)> for Context<Of<T>>
    where
        T: Construct + Count<U> + ToIndex<U, V>,
        U: Copy,
        V: Copy
{
    fn to_index(
        &self,
        dim: &'a [U],
        (p, ind, b): (&'a [V], usize, V)
    ) -> usize {
        fn subspace_offset<T, U>(v: &[U], ind: usize) -> usize
            where T: Construct + Count<U>,
                  U: Copy
        {
            use Pair;

            let of: T = Construct::new();
            let pair: Pair<Data> = Construct::new();
            let mut sum = 0;
            for i in 0..ind {
                let mut prod = 1;
                for j in 0..v.len() {
                    if i == j { continue; }
                    prod *= of.count(v[j]);
                }
                sum += pair.count(of.count(v[i])) * prod;
            }
            sum
        }

        use std::cmp::{ min, max };
        use Pair;

        let of: T = Construct::new();
        let offset = subspace_offset::<T, U>(dim, ind);
        let pair: Pair<Data> = Construct::new();
        let mut prod = 1;
        for j in 0..dim.len() {
            if ind == j { continue; }
            prod *= of.count(dim[j]);
        }
        // Pair doesn't care about dimension.
        let single = pair.to_index(0,
            (min(of.to_index(dim[ind], p[ind]), of.to_index(dim[ind], b)),
             max(of.to_index(dim[ind], p[ind]), of.to_index(dim[ind], b))));
        let pos_offset = single * prod;
        let mut dim_index = 0;
        for i in (0..p.len()).rev() {
            if ind == i { continue; }
            dim_index = dim_index * of.count(dim[i]) + of.to_index(dim[i], p[i]);
        }
        offset + pos_offset + dim_index
    }
}

impl<'a> ToPos<&'a [usize], (Vec<usize>, usize, usize)> for Context<Data> {
    fn to_pos(
        &self,
        dim: &'a [usize],
        index: usize,
        &mut (ref mut p, ref mut ind, ref mut b): &mut (Vec<usize>, usize, usize)
    ) {
        use Pair;

        p.clear();
        let pair_space: Pair<Data> = Construct::new();
        let (ind_val, offset) = ind_from_index(dim, index);
        // Get rid of offset.
        // The rest equals: single * prod + dim_index
        let index = index - offset;
        let mut prod = 1;
        for j in 0..dim.len() {
            p.push(0); // zero position
            if ind_val == j { continue; }
            prod *= dim[j];
        }
        let single = index / prod;

        let mut pair = (0, 0);
        // Pair doesn't care about dimension.
        pair_space.to_pos(0, single, &mut pair);
        let (min, max) = pair;

        // Resolve other dimension components.
        let mut dim_index = index - single * prod;
        for i in (0..p.len()).rev() {
            if ind_val == i { continue; }
            prod /= dim[i];
            let p_i = dim_index / prod;
            p[i] = p_i;
            dim_index -= p_i * prod;
        }
        p[ind_val] = min;
        *b = max;
        *ind = ind_val;

    }
}

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

    #[test]
    fn features() {
        does_count::<Context, &[usize]>();
        does_count::<Context<Subspace<Pair>>, (&[usize], usize)>();
        does_count::<Context<Of<Pair>>, &[usize]>();
        does_to_index::<Context, &[usize], (&[usize], usize, usize)>();
        does_to_index::<Context<Subspace<Pair>>, (&[usize], usize),
            ((&[usize], usize, usize), (usize, usize))>();
        does_to_index::<Context<Of<Pair>>, &[usize],
            (&[(usize, usize)], usize, (usize, usize))>();
    }

    #[test]
    fn data() {
        let x: Context = Construct::new();
        let dim = &[2, 2, 2];
        // 12 edges on a cube
        assert_eq!(x.count(dim), 12);
        assert_eq!(x.to_index(dim, (&[0, 0, 0], 0, 1)), 0);
        for i in 0..x.count(dim) {
            let mut pos = (vec![], 0, 0);
            x.to_pos(dim, i, &mut pos);
            assert_eq!(x.to_index(dim, (&pos.0, pos.1, pos.2)), i);
        }
    }

    #[test]
    fn subspace() {
        let x: Context<Subspace<Pair>> = Construct::new();
        let dim = (&*vec![2, 2], 3);
        assert_eq!(x.to_index(dim, ((&[0, 0], 0, 1), (0, 1))), 0);
        assert_eq!(x.to_index(dim, ((&[0, 0], 0, 1), (0, 2))), 1);
        assert_eq!(x.to_index(dim, ((&[0, 0], 0, 1), (1, 2))), 2);
        assert_eq!(x.to_index(dim, ((&[0, 1], 0, 1), (0, 1))), 3);
        assert_eq!(x.to_index(dim, ((&[0, 1], 0, 1), (0, 2))), 4);
        assert_eq!(x.to_index(dim, ((&[0, 1], 0, 1), (1, 2))), 5);
        assert_eq!(x.to_index(dim, ((&[0, 1], 1, 0), (0, 1))), 6);
    }

    #[test]
    fn of() {
        let x: Context<Of<Pair>> = Construct::new();
        let dim = &[3];
        assert_eq!(x.count(dim), 3);
        assert_eq!(x.to_index(dim, (&[(0, 1)], 0, (0, 2))), 0);
        assert_eq!(x.to_index(dim, (&[(0, 1)], 0, (1, 2))), 1);
        assert_eq!(x.to_index(dim, (&[(0, 2)], 0, (1, 2))), 2);
        let dim = &[3, 3];
        assert_eq!(x.count(dim), 18);
        assert_eq!(x.to_index(dim, (&[(0, 1), (0, 1)], 0, (0, 2))), 0);
        assert_eq!(x.to_index(dim, (&[(0, 1), (0, 2)], 0, (0, 2))), 1);
        assert_eq!(x.to_index(dim, (&[(0, 1), (1, 2)], 0, (0, 2))), 2);
        assert_eq!(x.to_index(dim, (&[(0, 1), (0, 1)], 0, (1, 2))), 3);
        assert_eq!(x.to_index(dim, (&[(0, 1), (0, 2)], 0, (1, 2))), 4);
        assert_eq!(x.to_index(dim, (&[(0, 1), (1, 2)], 0, (1, 2))), 5);
        assert_eq!(x.to_index(dim, (&[(0, 2), (0, 1)], 0, (1, 2))), 6);
        assert_eq!(x.to_index(dim, (&[(0, 2), (0, 2)], 0, (1, 2))), 7);
        assert_eq!(x.to_index(dim, (&[(0, 2), (1, 2)], 0, (1, 2))), 8);
        assert_eq!(x.to_index(dim, (&[(0, 1), (0, 1)], 1, (0, 2))), 9);
        assert_eq!(x.to_index(dim, (&[(0, 2), (0, 1)], 1, (0, 2))), 10);
        assert_eq!(x.to_index(dim, (&[(1, 2), (0, 1)], 1, (0, 2))), 11);
        assert_eq!(x.to_index(dim, (&[(0, 1), (0, 1)], 1, (1, 2))), 12);
        assert_eq!(x.to_index(dim, (&[(0, 2), (0, 1)], 1, (1, 2))), 13);
        assert_eq!(x.to_index(dim, (&[(1, 2), (0, 1)], 1, (1, 2))), 14);
        assert_eq!(x.to_index(dim, (&[(0, 1), (0, 2)], 1, (1, 2))), 15);
        assert_eq!(x.to_index(dim, (&[(0, 2), (0, 2)], 1, (1, 2))), 16);
        assert_eq!(x.to_index(dim, (&[(1, 2), (0, 2)], 1, (1, 2))), 17);
    }
}
<|endoftext|>


<commit_before>use ndarray::*;
use pyo3::Python;

use std::iter::Iterator;
use std::mem::size_of;
use std::os::raw::c_void;
use std::ptr::null_mut;

use super::*;

pub trait IntoPyArray {
    fn into_pyarray(self, Python, &PyArrayModule) -> PyArray;
}

impl<T: TypeNum> IntoPyArray for Vec<T> {
    fn into_pyarray(self, py: Python, np: &PyArrayModule) -> PyArray {
        let dims = [self.len()];
        unsafe { PyArray::new_::<T>(py, np, &dims, null_mut(), into_raw(self)) }
    }
}

impl<A: TypeNum, D: Dimension> IntoPyArray for Array<A, D> {
    fn into_pyarray(self, py: Python, np: &PyArrayModule) -> PyArray {
        let dims: Vec<_> = self.shape().iter().cloned().collect();
        let mut strides: Vec<_> = self.strides()
            .into_iter()
            .map(|n| n * size_of::<A>() as npy_intp)
            .collect();
        unsafe {
            let data = into_raw(self.into_raw_vec());
            PyArray::new_::<A>(py, np, &dims, strides.as_mut_ptr(), data)
        }
    }
}

unsafe fn into_raw<T>(x: Vec<T>) -> *mut c_void {
    let ptr: *mut [T] = Box::into_raw(x.into_boxed_slice());
    (*ptr).as_ref().as_ptr() as *mut c_void
}

pub trait ToPyArray {
    fn to_pyarray(self, Python, &PyArrayModule) -> PyArray;
}

impl<Iter, T: TypeNum> ToPyArray for Iter
where
    Iter: Iterator<Item = T> + Sized,
{
    fn to_pyarray(self, py: Python, np: &PyArrayModule) -> PyArray {
        let vec: Vec<T> = self.collect();
        vec.into_pyarray(py, np)
    }
}
<commit_msg>Implement IntoPyArray for Vec<Vec<T>><commit_after>use ndarray::*;
use pyo3::Python;

use std::iter::Iterator;
use std::mem::size_of;
use std::os::raw::c_void;
use std::ptr::null_mut;

use super::*;

pub trait IntoPyArray {
    fn into_pyarray(self, Python, &PyArrayModule) -> PyArray;
}

impl<T: TypeNum> IntoPyArray for Box<[T]> {
    fn into_pyarray(self, py: Python, np: &PyArrayModule) -> PyArray {
        let dims = [self.len()];
        let ptr = Box::into_raw(self);
        unsafe { PyArray::new_::<T>(py, np, &dims, null_mut(), ptr as *mut c_void) }
    }
}

impl<T: TypeNum> IntoPyArray for Vec<T> {
    fn into_pyarray(self, py: Python, np: &PyArrayModule) -> PyArray {
        let dims = [self.len()];
        unsafe { PyArray::new_::<T>(py, np, &dims, null_mut(), into_raw(self)) }
    }
}

impl<T: TypeNum> IntoPyArray for Vec<Vec<T>> {
    fn into_pyarray(self, py: Python, np: &PyArrayModule) -> PyArray {
        let inner_dim = self.last().map(Vec::len).unwrap_or(0);
        let dims = [self.len(), inner_dim];
        let vec: Vec<_> = self.into_iter().flatten().collect();
        unsafe { PyArray::new_::<T>(py, np, &dims, null_mut(), into_raw(vec)) }
    }
}

impl<A: TypeNum, D: Dimension> IntoPyArray for Array<A, D> {
    fn into_pyarray(self, py: Python, np: &PyArrayModule) -> PyArray {
        let dims: Vec<_> = self.shape().iter().cloned().collect();
        let mut strides: Vec<_> = self.strides()
            .into_iter()
            .map(|n| n * size_of::<A>() as npy_intp)
            .collect();
        unsafe {
            let data = into_raw(self.into_raw_vec());
            PyArray::new_::<A>(py, np, &dims, strides.as_mut_ptr(), data)
        }
    }
}

unsafe fn into_raw<T>(x: Vec<T>) -> *mut c_void {
    let ptr = Box::into_raw(x.into_boxed_slice());
    ptr as *mut c_void
}

pub trait ToPyArray {
    fn to_pyarray(self, Python, &PyArrayModule) -> PyArray;
}

impl<Iter, T: TypeNum> ToPyArray for Iter
where
    Iter: Iterator<Item = T> + Sized,
{
    fn to_pyarray(self, py: Python, np: &PyArrayModule) -> PyArray {
        let vec: Vec<T> = self.collect();
        vec.into_pyarray(py, np)
    }
}

#[test]
fn vec2_test() {
    let vec2 = vec![vec![1, 2, 3]; 2];
    let gil = pyo3::Python::acquire_gil();
    let np = PyArrayModule::import(gil.python()).unwrap();
    let pyarray = vec2.into_pyarray(gil.python(), &np);
    println!("{:?}", pyarray);
}
<|endoftext|>


<commit_before>extern crate num;
extern crate rand;
extern crate bincode;
extern crate rustc_serialize;
extern crate vec_map;
extern crate image;
extern crate euclid;
#[macro_use]
extern crate lazy_static;
extern crate vitral;
extern crate vitral_atlas;
extern crate calx_alg;
extern crate calx_grid;
extern crate calx_color;
#[macro_use]
extern crate calx_ecs;
#[macro_use]
extern crate calx_resource;

use std::collections::HashSet;
use euclid::{Point2D, Rect, Size2D};

mod ability;

mod brush;
pub use brush::{Brush, BrushBuilder, Color, Frame, ImageRef, Splat};

mod command;
pub use command::Command;

mod components;
mod field;
mod flags;
mod form;
mod fov;
pub mod init;
mod item;

mod location;
pub use location::{Location, Portal};

mod location_set;
// TODO: Make private, trigger mapgen internally using higher-level API
pub mod mapgen;
mod mutate;

mod query;
pub use query::Query;

mod spatial;
mod stats;

mod terraform;
pub use terraform::Terraform;
pub use terraform::TerrainQuery;

pub mod terrain;

mod world;
pub use world::{World, Ecs};

#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum FovStatus {
    Seen,
    Remembered,
}

/// Return whether the given chart point is on the currently visible screen.
///
/// It is assumed that the chart point 0, 0 is at the center of the screen.
///
/// Since various bits of game logic are tied to the screen boundaries, the screen size is fixed as
/// a constant.
fn on_screen(chart_pos: Point2D<i32>) -> bool {
    const W: i32 = 39;
    const H: i32 = 22;
    let (x, y) = (chart_pos.x, chart_pos.y);

    x <= y + (W + 1) / 2 // east
        && x >= y - (W - 1) / 2 // west
        && x >= -H - y // north
        && x <= H - 1 - y // south
}

pub fn onscreen_locations() -> &'static HashSet<Point2D<i32>> {
    lazy_static! {
        static ref ONSCREEN_LOCATIONS: HashSet<Point2D<i32>> = {
            let mut m = HashSet::new();

            // XXX: Hardcoded limits, tied to W and H in on-screen but expressed differently here.
            for y in -21..21 {
                for x in -21..21 {
                    let point = Point2D::new(x, y);
                    if on_screen(point) {
                        m.insert(point);
                    }
                }
            }
            m
        };
    }

    &*ONSCREEN_LOCATIONS
}
<commit_msg>Use Vec for the onscreen locations container<commit_after>extern crate num;
extern crate rand;
extern crate bincode;
extern crate rustc_serialize;
extern crate vec_map;
extern crate image;
extern crate euclid;
#[macro_use]
extern crate lazy_static;
extern crate vitral;
extern crate vitral_atlas;
extern crate calx_alg;
extern crate calx_grid;
extern crate calx_color;
#[macro_use]
extern crate calx_ecs;
#[macro_use]
extern crate calx_resource;

use std::collections::HashSet;
use euclid::{Point2D, Rect, Size2D};

mod ability;

mod brush;
pub use brush::{Brush, BrushBuilder, Color, Frame, ImageRef, Splat};

mod command;
pub use command::Command;

mod components;
mod field;
mod flags;
mod form;
mod fov;
pub mod init;
mod item;

mod location;
pub use location::{Location, Portal};

mod location_set;
// TODO: Make private, trigger mapgen internally using higher-level API
pub mod mapgen;
mod mutate;

mod query;
pub use query::Query;

mod spatial;
mod stats;

mod terraform;
pub use terraform::Terraform;
pub use terraform::TerrainQuery;

pub mod terrain;

mod world;
pub use world::{World, Ecs};

#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum FovStatus {
    Seen,
    Remembered,
}

/// Return whether the given chart point is on the currently visible screen.
///
/// It is assumed that the chart point 0, 0 is at the center of the screen.
///
/// Since various bits of game logic are tied to the screen boundaries, the screen size is fixed as
/// a constant.
fn on_screen(chart_pos: Point2D<i32>) -> bool {
    const W: i32 = 39;
    const H: i32 = 22;
    let (x, y) = (chart_pos.x, chart_pos.y);

    x <= y + (W + 1) / 2 // east
        && x >= y - (W - 1) / 2 // west
        && x >= -H - y // north
        && x <= H - 1 - y // south
}

pub fn onscreen_locations() -> &'static Vec<Point2D<i32>> {
    lazy_static! {
        static ref ONSCREEN_LOCATIONS: Vec<Point2D<i32>> = {
            let mut m = Vec::new();

            // XXX: Hardcoded limits, tied to W and H in on-screen but expressed differently here.
            for y in -21..22 {
                for x in -21..21 {
                    let point = Point2D::new(x, y);
                    if on_screen(point) {
                        m.push(point);
                    }
                }
            }
            m
        };
    }

    &*ONSCREEN_LOCATIONS
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(clippy)]

#![deny(out_of_bounds_indexing)]

fn main() {
    let x = [1,2,3,4];
    x[0];
    x[3];
    x[4]; //~ERROR: const index-expr is out of bounds
    x[1 << 3]; //~ERROR: const index-expr is out of bounds
}
<commit_msg>Remove x rights on a test file<commit_after>#![feature(plugin)]
#![plugin(clippy)]

#![deny(out_of_bounds_indexing)]

fn main() {
    let x = [1,2,3,4];
    x[0];
    x[3];
    x[4]; //~ERROR: const index-expr is out of bounds
    x[1 << 3]; //~ERROR: const index-expr is out of bounds
}
<|endoftext|>


<commit_before>//
// zhtta.rs
//
// Running on Rust 0.8
//
// Starting code for PS3
//
// Note: it would be very unwise to run this server on a machine that is
// on the Internet and contains any sensitive files!
//
// University of Virginia - cs4414 Fall 2013
// Weilin Xu and David Evans
// Version 0.3

extern mod extra;

use std::rt::io::*;
use std::rt::io::net::ip::SocketAddr;
use std::io::println;
use std::cell::Cell;
use std::{os, str, io};
use extra::arc;
use std::comm::*;

use std::rt::io::net::tcp::TcpStream;

static PORT: int = 4414;
static IP: &'static str = "127.0.0.1";

struct sched_msg {
    stream: Option<std::rt::io::net::tcp::TcpStream>,
    filepath: ~std::path::PosixPath
}

// determine if the request is from a Charlottesville client

fn is_Wahoo_Client(peer_addr: ~str) ->bool
{
	let WahooIPs: ~[~str] = ~[~"128.143.", ~"137.54."]; // probably add some more ip addresses on the way
	let mut isWahoo = false;
	let mut index = 0;

	while index < WahooIPs.len()
	{
		if peer_addr.starts_with(WahooIPs[index])
		{
			isWahoo = true;
			break;
		}
		index += 1;
	}
	//println( fmt!("is wahoo? : %?\n", isWahoo) );
	return isWahoo;
}

// get the size of a file

fn get_fileSize(file_path: &Path) -> int
{
	let mut filestream = std::rt::io::file::open(file_path, Open, Read);
	let mut size:int = 0;

	// find the File size
	match filestream{
		Some(ref mut reader) =>
		{
			reader.seek(0,SeekEnd);
			size = reader.tell() as int;
			reader.seek(0, SeekSet); // rewind the file back

			println(fmt!("\nfile size: %? bytes \n", size ));
		},
		None => { fail!("\nCannot read the storage file \n");},
	}
	return size;
}

fn main() {

    let visitor_count: uint = 0; // @@@@@@@

    let mut isWahoo: bool = false;

    let req_vec: ~[sched_msg] = ~[];
    let shared_req_vec = arc::RWArc::new(req_vec);
    let add_vec = shared_req_vec.clone();
    let take_vec = shared_req_vec.clone();

    let (port, chan) = stream();
    let chan = SharedChan::new(chan);

    // dequeue file requests, and send responses.
    // FIFO
    do spawn {
        let (sm_port, sm_chan) = stream();

        // a task for sending responses.
        do spawn {
            loop {
                let mut tf: sched_msg = sm_port.recv(); // wait for the dequeued request to handle
                match io::read_whole_file(tf.filepath) { // killed if file size is larger than memory size.
                    Ok(file_data) => {
                        println(fmt!("begin serving file [%?]", tf.filepath));
                        // A web server should always reply a HTTP header for any legal HTTP request.
                        tf.stream.write("HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n".as_bytes());
                        tf.stream.write(file_data);
                        println(fmt!("finish file [%?]", tf.filepath));
                    }
                    Err(err) => {
                        println(err);
                    }
                }
            }
        }

        loop {
            port.recv(); // wait for arrving notification
            do take_vec.write |vec| {
                if ((*vec).len() > 0) {
                    // LIFO didn't make sense in service scheduling, so we modify it as FIFO by using shift_opt() rather than pop().
                    let tf_opt: Option<sched_msg> = (*vec).shift_opt();
                    let tf = tf_opt.unwrap();
                    println(fmt!("shift from queue, size: %ud", (*vec).len()));
                    sm_chan.send(tf); // send the request to send-response-task to serve.
                }
            }
        }
    }

    let ip = match FromStr::from_str(IP) { Some(ip) => ip,
					   None     => {println(fmt!("Error: Invalid IP address <%s>", IP));
						        return;}
 					 };

    let socket = net::tcp::TcpListener::bind(SocketAddr {ip: ip, port: PORT as u16});

    println(fmt!("Listening on %s:%d ...", ip.to_str(), PORT));
    let mut acceptor = socket.listen().unwrap();

    let shared_count = arc::RWArc::new( visitor_count ); // @@@@@@

    for stream in acceptor.incoming() {
	let mut stream = stream; // @@@@@@
	let mut peer_addr: ~str = ~"";

	match stream {
		Some(ref mut s) =>
		{
			match s.peer_name() {
				Some(pn) =>
				{ 	peer_addr = pn.to_str();
					println( fmt!("\nPeer address: %s", peer_addr ));
				},
				None 	 => ()
			}
		}
		None => ()
	} 			// @@@@@

	isWahoo = is_Wahoo_Client(peer_addr);
	println( fmt!("is wahoo? : %?\n", isWahoo) );

	let stream = Cell::new(stream);

	let (count_port, count_chan): (Port< extra::arc::RWArc<uint> >, Chan< extra::arc::RWArc<uint> >) = std::comm::stream(); // @@@@@@
        let count_chan = SharedChan::new(count_chan); // @@@@@@
        count_chan.send(shared_count.clone() ); // @@@@@@

        // Start a new task to handle the connection
        let child_chan = chan.clone();
	let child_add_vec = add_vec.clone();

        do spawn {

	    let shared_count_copy = count_port.recv(); // @@@@@@

	    /* Get Write Access */
	    do shared_count_copy.write |count|{
			*count = *count + 1;
			println( fmt!("count: %? \n", *count as int) );
    	    }

            let mut stream = stream.take();
            let mut buf = [0, ..500];
            stream.read(buf);
            let request_str = str::from_utf8(buf);

            let req_group : ~[&str]= request_str.splitn_iter(' ', 3).collect();
            if req_group.len() > 2 {
                let path = req_group[1];
                println(fmt!("Request for path: \n%?", path));

                let file_path = ~os::getcwd().push(path.replace("/../", ""));

                if !os::path_exists(file_path) || os::path_is_dir(file_path)
		{
                    println(fmt!("Request received:\n%s", request_str));

		    /* Get Read Access */
		    do shared_count_copy.read |count|
		    {
   			let response: ~str = fmt!(
                        "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
			<doctype !html>
			<title>Hello, Rust!</title>

Greetings, Krusty!

Visitor count: %u

			\r\n", *count);

			stream.write(response.as_bytes());
    	    	    }

                }
                else {
                    // Requests scheduling

		    let size:int = get_fileSize(file_path); // @@@@@@@@@@@

                    let msg: sched_msg = sched_msg{stream: stream, filepath: file_path.clone()};
                    let (sm_port, sm_chan) = std::comm::stream();
                    sm_chan.send(msg);

                    do child_add_vec.write |vec| {
                        let msg = sm_port.recv();
                        (*vec).push(msg); // enqueue new request.
                        println("add to queue");
                    }
                    child_chan.send(""); //notify the new arriving request.

                    println(fmt!("get file request: %?", file_path));
                }
            }
            println!("connection terminates\n")
        }
    }
}

<commit_msg>Implemented basic caching, checks if file is cached and serves cached version if file has not been modified since being cached.<commit_after>//
// zhtta.rs
//
// Running on Rust 0.8
//
// Starting code for PS3
//
// Note: it would be very unwise to run this server on a machine that is
// on the Internet and contains any sensitive files!
//
// University of Virginia - cs4414 Fall 2013
// Weilin Xu and David Evans
// Version 0.3

extern mod extra;

use std::rt::io::*;
use std::rt::io::net::ip::SocketAddr;
use std::io::println;
use std::cell::Cell;
use std::{os, str, io};
use extra::arc;
use extra::time;
use std::comm::*;
use std::hashmap::HashMap;

use std::rt::io::net::tcp::TcpStream;

static PORT: int = 4414;
static IP: &'static str = "127.0.0.1";

struct sched_msg {
    stream: Option<std::rt::io::net::tcp::TcpStream>,
    filepath: ~std::path::PosixPath
}

// determine if the request is from a Charlottesville client

fn is_Wahoo_Client(peer_addr: ~str) ->bool
{
	let WahooIPs: ~[~str] = ~[~"128.143.", ~"137.54."]; // probably add some more ip addresses on the way
	let mut isWahoo = false;
	let mut index = 0;

	while index < WahooIPs.len()
	{
		if peer_addr.starts_with(WahooIPs[index])
		{
			isWahoo = true;
			break;
		}
		index += 1;
	}
	//println( fmt!("is wahoo? : %?\n", isWahoo) );
	return isWahoo;
}

// get the size of a file

fn get_fileSize(file_path: &Path) -> int
{
	let mut filestream = std::rt::io::file::open(file_path, Open, Read);
	let mut size:int = 0;

	// find the File size
	match filestream{
		Some(ref mut reader) =>
		{
			reader.seek(0,SeekEnd);
			size = reader.tell() as int;
			reader.seek(0, SeekSet); // rewind the file back

			println(fmt!("\nfile size: %? bytes \n", size ));
		},
		None => { fail!("\nCannot read the storage file \n");},
	}
	return size;
}

fn main() {

    let visitor_count: uint = 0; // @@@@@@@

    let mut isWahoo: bool = false;

    let req_vec: ~[sched_msg] = ~[];
    let shared_req_vec = arc::RWArc::new(req_vec);
    let add_vec = shared_req_vec.clone();
    let take_vec = shared_req_vec.clone();

    let (port, chan) = stream();
    let chan = SharedChan::new(chan);

    // dequeue file requests, and send responses.
    // FIFO
    do spawn {
        let (sm_port, sm_chan) = stream();

        // a task for sending responses.
        do spawn {
	    let mut cache: HashMap<~str, ~[u8]> = std::hashmap::HashMap::new();
	    let mut cacheTimes: HashMap<~str, ~i64> = std::hashmap::HashMap::new();
            loop {
                let mut tf: sched_msg = sm_port.recv(); // wait for the dequeued request to handle
		let modifiedTime = match file::stat(tf.filepath) {
			Some(s) => {
					s.modified
				   }
			None => {
					-1
				}
		};
		if cache.contains_key_equiv(&tf.filepath.to_str()) &&
				*cacheTimes.get_copy(&tf.filepath.to_str()) as u64 > modifiedTime {
			println(fmt!("begin serving file [%?]", tf.filepath));
                        // A web server should always reply a HTTP header for any legal HTTP request.
                        tf.stream.write("HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n".as_bytes());
			let data = cache.get_copy(&tf.filepath.to_str());
                        tf.stream.write(data);
                        println(fmt!("finish file [%?]", tf.filepath));
		}
		else {
		     let file = io::read_whole_file(tf.filepath);
   	             match file { // killed if file size is larger than memory size.
                	    Ok(file_data) => {
                 	       println(fmt!("begin serving file [%?]", tf.filepath));
                 	       // A web server should always reply a HTTP header for any legal HTTP request.
                 	       tf.stream.write("HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n".as_bytes());
                        	tf.stream.write(file_data);
                        	println(fmt!("finish file [%?]", tf.filepath));
				cache.insert(tf.filepath.to_str(), file_data);
				cacheTimes.insert(tf.filepath.to_str(), ~time::get_time().sec);
                    	    }
                    	    Err(err) => {
                        	println(err);
                    	    }
                    }
		}
            }
        }

        loop {
            port.recv(); // wait for arrving notification
            do take_vec.write |vec| {
                if ((*vec).len() > 0) {
                    // LIFO didn't make sense in service scheduling, so we modify it as FIFO by using shift_opt() rather than pop().
                    let tf_opt: Option<sched_msg> = (*vec).shift_opt();
                    let tf = tf_opt.unwrap();
                    println(fmt!("shift from queue, size: %ud", (*vec).len()));
                    sm_chan.send(tf); // send the request to send-response-task to serve.
                }
            }
        }
    }

    let ip = match FromStr::from_str(IP) { Some(ip) => ip,
					   None     => {println(fmt!("Error: Invalid IP address <%s>", IP));
						        return;}
 					 };

    let socket = net::tcp::TcpListener::bind(SocketAddr {ip: ip, port: PORT as u16});

    println(fmt!("Listening on %s:%d ...", ip.to_str(), PORT));
    let mut acceptor = socket.listen().unwrap();

    let shared_count = arc::RWArc::new( visitor_count ); // @@@@@@

    for stream in acceptor.incoming() {
	let mut stream = stream; // @@@@@@
	let mut peer_addr: ~str = ~"";

	match stream {
		Some(ref mut s) =>
		{
			match s.peer_name() {
				Some(pn) =>
				{ 	peer_addr = pn.to_str();
					println( fmt!("\nPeer address: %s", peer_addr ));
				},
				None 	 => ()
			}
		}
		None => ()
	} 			// @@@@@

	isWahoo = is_Wahoo_Client(peer_addr);
	println( fmt!("is wahoo? : %?\n", isWahoo) );

	let stream = Cell::new(stream);

	let (count_port, count_chan): (Port< extra::arc::RWArc<uint> >, Chan< extra::arc::RWArc<uint> >) = std::comm::stream(); // @@@@@@
        let count_chan = SharedChan::new(count_chan); // @@@@@@
        count_chan.send(shared_count.clone() ); // @@@@@@

        // Start a new task to handle the connection
        let child_chan = chan.clone();
	let child_add_vec = add_vec.clone();

        do spawn {

	    let shared_count_copy = count_port.recv(); // @@@@@@

	    /* Get Write Access */
	    do shared_count_copy.write |count|{
			*count = *count + 1;
			println( fmt!("count: %? \n", *count as int) );
    	    }

            let mut stream = stream.take();
            let mut buf = [0, ..500];
            stream.read(buf);
            let request_str = str::from_utf8(buf);

            let req_group : ~[&str]= request_str.splitn_iter(' ', 3).collect();
            if req_group.len() > 2 {
                let path = req_group[1];
                println(fmt!("Request for path: \n%?", path));

                let file_path = ~os::getcwd().push(path.replace("/../", ""));

                if !os::path_exists(file_path) || os::path_is_dir(file_path)
		{
                    println(fmt!("Request received:\n%s", request_str));

		    /* Get Read Access */
		    do shared_count_copy.read |count|
		    {
   			let response: ~str = fmt!(
                        "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
			<doctype !html>
			<title>Hello, Rust!</title>

Greetings, Krusty!

Visitor count: %u

			\r\n", *count);

			stream.write(response.as_bytes());
    	    	    }

                }
                else {
                    // Requests scheduling

		    let size:int = get_fileSize(file_path); // @@@@@@@@@@@

                    let msg: sched_msg = sched_msg{stream: stream, filepath: file_path.clone()};
                    let (sm_port, sm_chan) = std::comm::stream();
                    sm_chan.send(msg);

                    do child_add_vec.write |vec| {
                        let msg = sm_port.recv();
                        (*vec).push(msg); // enqueue new request.
                        println("add to queue");
                    }
                    child_chan.send(""); //notify the new arriving request.

                    println(fmt!("get file request: %?", file_path));
                }
            }
            println!("connection terminates\n")
        }
    }
}

<|endoftext|>


<commit_before>struct Foo {
    _inner: i32,
}

fn main() {
    unsafe {
        let foo = Foo {
            _inner: std::mem::uninitialized(),
        };
        let _bar = foo;
    }
}
<commit_msg>fix test using mem::uninitialized<commit_after>#![allow(deprecated)]

struct Foo {
    _inner: i32,
}

fn main() {
    unsafe {
        let foo = Foo {
            _inner: std::mem::uninitialized(),
        };
        let _bar = foo;
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate glium;
extern crate calx_system;
extern crate calx_window;
extern crate cgmath;

use std::default::Default;
use calx_window::{WindowBuilder, Event, Key};
use cgmath::Angle;

/// Cube face.
#[derive(Copy, Clone)]
enum Face {
    East,
    North,
    Up,
    West,
    South,
    Down,
}

impl Face {
    /// Normal vector for the face.
    pub fn normal(&self) -> [f32; 3] {
        match *self {
            Face::East => [1.0, 0.0, 0.0],
            Face::North => [0.0, 1.0, 0.0],
            Face::Up => [0.0, 0.0, 1.0],
            Face::West => [-1.0, 0.0, 0.0],
            Face::South => [0.0, -1.0, 0.0],
            Face::Down => [0.0, 0.0, -1.0],
        }
    }

    /// Counter-clockwise vertex list using cube vertex indices.
    #[inline]
    pub fn vertices(&self) -> [usize; 4] {
        [[1, 3, 7, 5],
         [2, 6, 7, 3],
         [4, 5, 7, 6],
         [0, 4, 6, 2],
         [0, 1, 5, 4],
         [0, 2, 3, 1]][*self as usize]
    }
}

/// Vertex of a default [0, 0, 0] - [1, 1, 1] cube.
///
/// There are 8 indices, corresponding to 3 bits. The low bit denotes x-axis
/// extension, the middle bit y-axis extension and the high bit z-axis
/// extension.
///
/// ```notrust
///     6 --- 7
///    /:    /|
///   4 --- 5 |
///   | :   | |      Z
///   | 2 ..|.3      | Y
///   |.    |/       |/
///   0 --- 1        o---X
///
/// ```
#[inline]
fn cube_vertex(index: usize) -> [f32; 3] {
    [[0.0, 0.0, 0.0],
     [0.1, 0.0, 0.0],
     [0.0, 0.1, 0.0],
     [0.1, 0.1, 0.0],
     [0.0, 0.0, 0.1],
     [0.1, 0.0, 0.1],
     [0.0, 0.1, 0.1],
     [0.1, 0.1, 0.1]][index]
}

#[derive(Copy, Clone)]
pub struct Vertex {
    pub pos: [f32; 3],
    pub normal: [f32; 3], // pub color: [f32; 4],
}
implement_vertex!(Vertex, pos, normal, color);

struct Voxel {
    color: [f32; 4],
}

fn get_voxel(voxelPos: [i32; 3]) -> Option<Voxel> {
    // TODO: Perlin noise landscape or something.
    if voxelPos[2] < 0 {
        Some(Voxel { color: [0.0, 1.0, 0.0, 1.0] })
    } else {
        None
    }
}

fn main() {
    let mut window = WindowBuilder::new().set_title("Voxel demo").build();

    let shader = program!(&window.display,
            150 => {
            vertex: "
                #version 150 core

                uniform mat4 projection;
                uniform mat4 modelview;

                in vec3 position;
                in vec3 normal;
                out vec3 v_position;
                out vec3 v_normal;

                void main() {
                    v_position = position;
                    v_normal = normal;
                    gl_Position = projection * modelview * vec4(v_position, 1.0);
                }
            ",

            fragment: "
                #version 150 core

                in vec3 v_normal;
                out vec4 f_color;
                const vec3 LIGHT = vec3(-0.2, 0.8, 0.1);

                void main() {
                    float lum = max(dot(normalize(v_normal), normalize(LIGHT)), 0.0);
                    vec3 color = (0.3 + 0.7 * lum) * vec3(1.0, 1.0, 1.0);
                    f_color = vec4(color, 1.0);
                }
            ",
            }
        ).unwrap();

    loop {
        for e in window.events().into_iter() {
            match e {
                Event::Quit => return,
                Event::KeyPress(Key::Escape) => return,
                Event::KeyPress(Key::F12) => {
                    calx_system::save_screenshot("calx", window.screenshot())
                        .unwrap();
                }
                _ => (),
            }
        }
        window.clear(0x7799DDFF);

        // Camera setup

        let projection: cgmath::Matrix4<f32> =
            cgmath::PerspectiveFov {
                fovy: cgmath::Deg::new(90.0).into(),
                aspect: 380.0 / 640.0, // XXX: Hardcoding
                near: 1.0,
                far: 1024.0,
            }
            .into();

        let modelview: cgmath::Matrix4<f32> =
            cgmath::Matrix4::look_at(cgmath::Point3::new(0.0, -10.0, 10.0),
                                     cgmath::Point3::new(0.0, 0.0, 0.0),
                                     cgmath::vec3(0.0, 0.0, 1.0));

        // Convert to the format the shader expects.
        let projection: [[f32; 4]; 4] = projection.into();
        let modelview: [[f32; 4]; 4] = modelview.into();

        let uniforms = uniform! {
            projection: projection,
            modelview: modelview,
        };

        // Draw parameters

        let params = glium::DrawParameters {
            depth: glium::Depth {
                test: glium::DepthTest::IfLess,
                write: true,
                ..Default::default()
            },
            ..Default::default()
        };

        // Setup the cube model
        let faces = [Face::East,
                     Face::North,
                     Face::Up,
                     Face::West,
                     Face::South,
                     Face::Down];
        let mut vertices = Vec::new();
        let mut indices = Vec::new();
        for f in 0..6 {
            normal = faces[f].normal();
            let idx = vertices.len() as u16;
            for v_idx in faces[f].vertices().iter() {
                vertices.push(Vertex {
                    pos: cube_vertex(v_idx),
                    normal: normal,
                });

            }
            indices.push(idx);
            indices.push(idx + 1);
            indices.push(idx + 2);
            indices.push(idx);
            indices.push(idx + 2);
            indices.push(idx + 3);
        }
        let v_buf = glium::VertexBuffer::new(&window.display, &vertices);
        let i_buf =
            glium::IndexBuffer::new(&window.display,
                                    glium::index::PrimitiveType::TrianglesList,
                                    &indices)
                .unwrap();

        // Draw the thing

        let mut target = window.display.draw();
        target.draw(&v_buf, &i_buf, &shader, &uniforms, &params).unwrap();
        target.finish().unwrap();

        // window.display(&mut room);

        window.end_frame();
    }
}
<commit_msg>Voxel demo hello world<commit_after>#[macro_use]
extern crate glium;
extern crate calx_system;
extern crate calx_window;
extern crate cgmath;

use std::default::Default;
use calx_window::{WindowBuilder, Event, Key};
use cgmath::Angle;
use glium::Surface;

/// Cube face.
#[derive(Copy, Clone)]
enum Face {
    East,
    North,
    Up,
    West,
    South,
    Down,
}

impl Face {
    /// Normal vector for the face.
    pub fn normal(&self) -> [f32; 3] {
        match *self {
            Face::East => [1.0, 0.0, 0.0],
            Face::North => [0.0, 1.0, 0.0],
            Face::Up => [0.0, 0.0, 1.0],
            Face::West => [-1.0, 0.0, 0.0],
            Face::South => [0.0, -1.0, 0.0],
            Face::Down => [0.0, 0.0, -1.0],
        }
    }

    /// Counter-clockwise vertex list using cube vertex indices.
    #[inline]
    pub fn vertices(&self) -> [usize; 4] {
        [[1, 3, 7, 5],
         [2, 6, 7, 3],
         [4, 5, 7, 6],
         [0, 4, 6, 2],
         [0, 1, 5, 4],
         [0, 2, 3, 1]][*self as usize]
    }
}

/// Vertex of a default [0, 0, 0] - [1, 1, 1] cube.
///
/// There are 8 indices, corresponding to 3 bits. The low bit denotes x-axis
/// extension, the middle bit y-axis extension and the high bit z-axis
/// extension.
///
/// ```notrust
///     6 --- 7
///    /:    /|
///   4 --- 5 |
///   | :   | |      Z
///   | 2 ..|.3      | Y
///   |.    |/       |/
///   0 --- 1        o---X
///
/// ```
#[inline]
fn cube_vertex(index: usize) -> [f32; 3] {
    [[0.0, 0.0, 0.0],
     [0.1, 0.0, 0.0],
     [0.0, 0.1, 0.0],
     [0.1, 0.1, 0.0],
     [0.0, 0.0, 0.1],
     [0.1, 0.0, 0.1],
     [0.0, 0.1, 0.1],
     [0.1, 0.1, 0.1]][index]
}

#[derive(Copy, Clone)]
pub struct Vertex {
    pub pos: [f32; 3],
    pub normal: [f32; 3],
    pub color: [f32; 4],
}
implement_vertex!(Vertex, pos, normal, color);

struct Voxel {
    color: [f32; 4],
}

fn get_voxel(voxel_pos: [i32; 3]) -> Option<Voxel> {
    // TODO: Perlin noise landscape or something.
    if voxel_pos[2] < 0 {
        Some(Voxel { color: [0.0, 1.0, 0.0, 1.0] })
    } else {
        None
    }
}

fn main() {
    let mut window = WindowBuilder::new().set_title("Voxel demo").build();

    let shader = program!(&window.display,
            150 => {
            vertex: "
                #version 150 core

                uniform mat4 projection;
                uniform mat4 modelview;

                in vec3 pos;
                in vec3 normal;
                in vec4 color;
                out vec3 v_pos;
                out vec3 v_normal;
                out vec4 v_color;

                void main() {
                    v_pos = pos;
                    v_normal = normal;
                    v_color = color;
                    gl_Position = projection * modelview * vec4(v_pos, 1.0);
                }
            ",

            fragment: "
                #version 150 core

                in vec3 v_normal;
                in vec4 v_color;
                out vec4 f_color;
                const vec3 LIGHT = vec3(-0.2, 0.8, 0.1);

                void main() {
                    float lum = max(dot(normalize(v_normal), normalize(LIGHT)), 0.0);
                    f_color = (0.3 + 0.7 * lum) * v_color;
                }
            ",
            }
        ).unwrap();

    loop {
        for e in window.events().into_iter() {
            match e {
                Event::Quit => return,
                Event::KeyPress(Key::Escape) => return,
                Event::KeyPress(Key::F12) => {
                    calx_system::save_screenshot("calx", window.screenshot())
                        .unwrap();
                }
                _ => (),
            }
        }
        window.clear(0x7799DDFF);

        // Camera setup

        let projection: cgmath::Matrix4<f32> =
            cgmath::PerspectiveFov {
                fovy: cgmath::Deg::new(90.0).into(),
                aspect: 640.0 / 380.0, // XXX: Hardcoding
                near: 0.01,
                far: 1024.0,
            }
            .into();

        let modelview: cgmath::Matrix4<f32> =
            cgmath::Matrix4::look_at(cgmath::Point3::new(1.0, -1.0, 2.0),
                                     cgmath::Point3::new(0.0, 0.0, 0.0),
                                     cgmath::vec3(0.0, 0.0, 1.0));

        // Convert to the format the shader expects.
        let projection: [[f32; 4]; 4] = projection.into();
        let modelview: [[f32; 4]; 4] = modelview.into();

        let uniforms = uniform! {
            projection: projection,
            modelview: modelview,
        };

        // Draw parameters

        let params = glium::DrawParameters {
            depth: glium::Depth {
                test: glium::DepthTest::IfLess,
                write: true,
                ..Default::default()
            },
            ..Default::default()
        };

        // Setup the cube model
        let faces = [Face::East,
                     Face::North,
                     Face::Up,
                     Face::West,
                     Face::South,
                     Face::Down];
        let mut vertices = Vec::new();
        let mut indices = Vec::new();
        for f in 0..6 {
            let normal = faces[f].normal();
            let idx = vertices.len() as u16;
            for &v_idx in faces[f].vertices().into_iter() {
                vertices.push(Vertex {
                    pos: cube_vertex(v_idx),
                    normal: normal,
                    color: [1.0, 0.0, 0.0, 1.0],
                });

            }
            indices.push(idx);
            indices.push(idx + 1);
            indices.push(idx + 2);
            indices.push(idx);
            indices.push(idx + 2);
            indices.push(idx + 3);
        }
        let v_buf = glium::VertexBuffer::new(&window.display, &vertices).unwrap();
        let i_buf =
            glium::IndexBuffer::new(&window.display,
                                    glium::index::PrimitiveType::TrianglesList,
                                    &indices)
                .unwrap();

        // Draw the thing

        {
            let mut target = window.get_framebuffer_target();
            target.draw(&v_buf, &i_buf, &shader, &uniforms, &params).unwrap();
        }

        // window.display(&mut room);

        window.end_frame();
    }
}
<|endoftext|>


<commit_before>//! Misc low level stuff

export TypeDesc;
export get_type_desc;
export size_of;
export min_align_of;
export pref_align_of;
export refcount;
export log_str;
export shape_eq, shape_lt, shape_le;

// Corresponds to runtime type_desc type
enum TypeDesc = {
    size: uint,
    align: uint
    // Remaining fields not listed
};

#[abi = "cdecl"]
extern mod rustrt {
    pure fn shape_log_str(t: *sys::TypeDesc, data: *()) -> ~str;
}

#[abi = "rust-intrinsic"]
extern mod rusti {
    fn get_tydesc<T>() -> *();
    fn size_of<T>() -> uint;
    fn pref_align_of<T>() -> uint;
    fn min_align_of<T>() -> uint;
}

/// Compares contents of two pointers using the default method.
/// Equivalent to `*x1 == *x2`.  Useful for hashtables.
pure fn shape_eq<T>(x1: &T, x2: &T) -> bool {
    *x1 == *x2
}

pure fn shape_lt<T>(x1: &T, x2: &T) -> bool {
    *x1 < *x2
}

pure fn shape_le<T>(x1: &T, x2: &T) -> bool {
    *x1 < *x2
}

/**
 * Returns a pointer to a type descriptor.
 *
 * Useful for calling certain function in the Rust runtime or otherwise
 * performing dark magick.
 */
pure fn get_type_desc<T>() -> *TypeDesc {
    unchecked { rusti::get_tydesc::<T>() as *TypeDesc }
}

/// Returns the size of a type
#[inline(always)]
pure fn size_of<T>() -> uint {
    unchecked { rusti::size_of::<T>() }
}

/**
 * Returns the ABI-required minimum alignment of a type
 *
 * This is the alignment used for struct fields. It may be smaller
 * than the preferred alignment.
 */
#[inline(always)]
pure fn min_align_of<T>() -> uint {
    unchecked { rusti::min_align_of::<T>() }
}

/// Returns the preferred alignment of a type
#[inline(always)]
pure fn pref_align_of<T>() -> uint {
    unchecked { rusti::pref_align_of::<T>() }
}

/// Returns the refcount of a shared box (as just before calling this)
pure fn refcount<T>(+t: @T) -> uint {
    unsafe {
        let ref_ptr: *uint = unsafe::reinterpret_cast(t);
        *ref_ptr - 1
    }
}

pure fn log_str<T>(t: T) -> ~str {
    unsafe {
        let data_ptr: *() = unsafe::reinterpret_cast(ptr::addr_of(t));
        rustrt::shape_log_str(get_type_desc::<T>(), data_ptr)
    }
}

#[cfg(test)]
mod tests {

    #[test]
    fn size_of_basic() {
        assert size_of::<u8>() == 1u;
        assert size_of::<u16>() == 2u;
        assert size_of::<u32>() == 4u;
        assert size_of::<u64>() == 8u;
    }

    #[test]
    #[cfg(target_arch = "x86")]
    #[cfg(target_arch = "arm")]
    fn size_of_32() {
        assert size_of::<uint>() == 4u;
        assert size_of::<*uint>() == 4u;
    }

    #[test]
    #[cfg(target_arch = "x86_64")]
    fn size_of_64() {
        assert size_of::<uint>() == 8u;
        assert size_of::<*uint>() == 8u;
    }

    #[test]
    fn align_of_basic() {
        assert pref_align_of::<u8>() == 1u;
        assert pref_align_of::<u16>() == 2u;
        assert pref_align_of::<u32>() == 4u;
    }

    #[test]
    #[cfg(target_arch = "x86")]
    #[cfg(target_arch = "arm")]
    fn align_of_32() {
        assert pref_align_of::<uint>() == 4u;
        assert pref_align_of::<*uint>() == 4u;
    }

    #[test]
    #[cfg(target_arch = "x86_64")]
    fn align_of_64() {
        assert pref_align_of::<uint>() == 8u;
        assert pref_align_of::<*uint>() == 8u;
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>Add sys::Closure type<commit_after>//! Misc low level stuff

export TypeDesc;
export get_type_desc;
export size_of;
export min_align_of;
export pref_align_of;
export refcount;
export log_str;
export shape_eq, shape_lt, shape_le;

// Corresponds to runtime type_desc type
enum TypeDesc = {
    size: uint,
    align: uint
    // Remaining fields not listed
};

/// The representation of a Rust closure
struct Closure {
    code: *();
    env: *();
}

#[abi = "cdecl"]
extern mod rustrt {
    pure fn shape_log_str(t: *sys::TypeDesc, data: *()) -> ~str;
}

#[abi = "rust-intrinsic"]
extern mod rusti {
    fn get_tydesc<T>() -> *();
    fn size_of<T>() -> uint;
    fn pref_align_of<T>() -> uint;
    fn min_align_of<T>() -> uint;
}

/// Compares contents of two pointers using the default method.
/// Equivalent to `*x1 == *x2`.  Useful for hashtables.
pure fn shape_eq<T>(x1: &T, x2: &T) -> bool {
    *x1 == *x2
}

pure fn shape_lt<T>(x1: &T, x2: &T) -> bool {
    *x1 < *x2
}

pure fn shape_le<T>(x1: &T, x2: &T) -> bool {
    *x1 < *x2
}

/**
 * Returns a pointer to a type descriptor.
 *
 * Useful for calling certain function in the Rust runtime or otherwise
 * performing dark magick.
 */
pure fn get_type_desc<T>() -> *TypeDesc {
    unchecked { rusti::get_tydesc::<T>() as *TypeDesc }
}

/// Returns the size of a type
#[inline(always)]
pure fn size_of<T>() -> uint {
    unchecked { rusti::size_of::<T>() }
}

/**
 * Returns the ABI-required minimum alignment of a type
 *
 * This is the alignment used for struct fields. It may be smaller
 * than the preferred alignment.
 */
#[inline(always)]
pure fn min_align_of<T>() -> uint {
    unchecked { rusti::min_align_of::<T>() }
}

/// Returns the preferred alignment of a type
#[inline(always)]
pure fn pref_align_of<T>() -> uint {
    unchecked { rusti::pref_align_of::<T>() }
}

/// Returns the refcount of a shared box (as just before calling this)
pure fn refcount<T>(+t: @T) -> uint {
    unsafe {
        let ref_ptr: *uint = unsafe::reinterpret_cast(t);
        *ref_ptr - 1
    }
}

pure fn log_str<T>(t: T) -> ~str {
    unsafe {
        let data_ptr: *() = unsafe::reinterpret_cast(ptr::addr_of(t));
        rustrt::shape_log_str(get_type_desc::<T>(), data_ptr)
    }
}

#[cfg(test)]
mod tests {

    #[test]
    fn size_of_basic() {
        assert size_of::<u8>() == 1u;
        assert size_of::<u16>() == 2u;
        assert size_of::<u32>() == 4u;
        assert size_of::<u64>() == 8u;
    }

    #[test]
    #[cfg(target_arch = "x86")]
    #[cfg(target_arch = "arm")]
    fn size_of_32() {
        assert size_of::<uint>() == 4u;
        assert size_of::<*uint>() == 4u;
    }

    #[test]
    #[cfg(target_arch = "x86_64")]
    fn size_of_64() {
        assert size_of::<uint>() == 8u;
        assert size_of::<*uint>() == 8u;
    }

    #[test]
    fn align_of_basic() {
        assert pref_align_of::<u8>() == 1u;
        assert pref_align_of::<u16>() == 2u;
        assert pref_align_of::<u32>() == 4u;
    }

    #[test]
    #[cfg(target_arch = "x86")]
    #[cfg(target_arch = "arm")]
    fn align_of_32() {
        assert pref_align_of::<uint>() == 4u;
        assert pref_align_of::<*uint>() == 4u;
    }

    #[test]
    #[cfg(target_arch = "x86_64")]
    fn align_of_64() {
        assert pref_align_of::<uint>() == 8u;
        assert pref_align_of::<*uint>() == 8u;
    }

    #[test]
    fn synthesize_closure() unsafe {
        let x = 10;
        let f: fn(int) -> int = |y| x + y;

        assert f(20) == 30;

        let original_closure: Closure = unsafe::transmute(f);

        let actual_function_pointer = original_closure.code;
        let environment = original_closure.env;

        let new_closure = Closure {
            code: actual_function_pointer,
            env: environment
        };

        let new_f: fn(int) -> int = unsafe::transmute(new_closure);
        assert new_f(20) == 30;
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


<commit_before>#[link(name = "knob",
       vers = "0.5",
       uuid = "3299B6C2-99DE-44FD-8867-8EE7304959D7",
       url = "http://github.com/skade/knob")];

#[crate_type = "lib"];

extern mod extra;

use std::hashmap::*;
use std::rt::io::net::ip::{SocketAddr, IpAddr, Ipv4Addr};
use std::os;
use extra::getopts::groups::*;

#[deriving(Clone)]
pub struct Settings {
  priv store: HashMap<~str,~str>,
  priv options: ~[OptGroup],
}

impl Settings {
  pub fn new() -> Settings {
    Settings { store: HashMap::new(), options: ~[] }
  }

  pub fn load_args(&mut self) {
    debug!("compiling options");

    let args = os::args();
    let ref prog_name = args[0];

    self.set("knob.progname", prog_name.clone());

    let matches = match getopts(args.tail(), self.options) {
      Ok(m) => { m }
      Err(f) => { fail!(f.to_err_msg()) }
    };

    debug!(matches);

    let given_options = self.options.clone();
    for opt in given_options.iter() {
      let opt_strings = &[opt.short_name.clone(), opt.long_name.clone()];
      self.set_opt(opt.long_name.clone(), matches.opts_str(opt_strings))
    };
  }

  pub fn opt(&mut self, opt: OptGroup) {
    self.options.push(opt);
  }

  pub fn set<A: ToStr, T: ToStr>(&mut self, setting: A, value: T) {
    self.store.swap(setting.to_str(), value.to_str());
  }

  pub fn set_opt<A: ToStr, T: ToStr>(&mut self, setting: A, value: Option<T>) {
    if !value.is_none() {
      self.store.swap(setting.to_str(), value.unwrap().to_str());
    }
  }

  pub fn fetch_with<A: ToStr, T: FromStr>(&self, setting: A, f: &fn(Option<T>) -> T) -> T {
    let value = self.fetch(setting.to_str());
    f(value)
  }

  pub fn fetch<A: ToStr, T: FromStr>(&self, setting: A) -> Option<T> {
    match self.store.find(&setting.to_str()) {
      Some(string) => { from_str(string.to_owned()) },
      None => { None }
    }
  }
}

pub trait SocketSettings {
  fn socket(&self) -> SocketAddr;
  fn port(&self) -> u16;
  fn ip(&self) -> IpAddr;
}

impl SocketSettings for Settings {
  fn socket(&self) -> SocketAddr {
    do self.fetch_with("addr") |addr| {
      match addr {
        Some(socket_addr) => { socket_addr },
        None => {
          let port: u16 = self.port();
          let ip: IpAddr = self.ip();
          SocketAddr { ip: ip, port: port }
        }
      }
    }
  }

  fn port(&self) -> u16 {
    self.fetch("port").unwrap_or(8080)
  }

  fn ip(&self) -> IpAddr {
    self.fetch("ip").unwrap_or(Ipv4Addr(127,0,0,1))
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  #[test]
  fn test_insert() {
    let mut settings = Settings::new();
    settings.set("port", "12345");
    settings.set("ip", "127.0.0.1");
    settings.socket();
  }
}<commit_msg>Implement a testsuite<commit_after>#[link(name = "knob",
       vers = "0.5",
       uuid = "3299B6C2-99DE-44FD-8867-8EE7304959D7",
       url = "http://github.com/skade/knob")];

#[crate_type = "lib"];

extern mod extra;

use std::hashmap::*;
use std::os;

use extra::getopts::groups::{OptGroup,getopts,usage};
use extra::getopts::Fail_;

// The settings structure we save the options and settings in.
#[deriving(Clone)]
pub struct Settings {
  priv store: HashMap<~str,~str>,
  priv options: ~[OptGroup],
}

impl Settings {
  pub fn new() -> Settings {
    Settings { store: HashMap::new(), options: ~[] }
  }

  pub fn opt(&mut self, opt: OptGroup) {
    self.options.push(opt);
  }

  pub fn set<A: ToStr, T: ToStr>(&mut self, setting: A, value: T) {
    self.store.swap(setting.to_str(), value.to_str());
  }

  pub fn set_opt<A: ToStr, T: ToStr>(&mut self, setting: A, value: Option<T>) {
    if !value.is_none() {
      self.store.swap(setting.to_str(), value.unwrap().to_str());
    }
  }

  pub fn fetch_with<A: ToStr, T: FromStr>(&self, setting: A, f: &fn(Option<T>) -> T) -> T {
    let value = self.fetch(setting.to_str());
    f(value)
  }

  pub fn fetch<A: ToStr, T: FromStr>(&self, setting: A) -> Option<T> {
    match self.store.find(&setting.to_str()) {
      Some(string) => { from_str(string.to_owned()) },
      None => { None }
    }
  }

  pub fn load_os_args(&mut self) {
    let args = os::args();
    self.load_args(args);
  }

  pub fn load_args(&mut self, args: ~[~str]) -> Option<Fail_> {
    let ref prog_name = args[0];

    self.set("knob.progname", prog_name.clone());

    let matches = match getopts(args.tail(), self.options) {
      Ok(m) => { m }
      Err(fail) => { return Some(fail) }
    };

    debug!(matches);

    let given_options = self.options.clone();
    for opt in given_options.iter() {
      let opt_strings = &[opt.short_name.clone(), opt.long_name.clone()];
      self.set_opt(opt.long_name.clone(), matches.opts_str(opt_strings))
    };
    None
  }

  pub fn usage(&self, brief: &str) -> ~str {
    usage(brief, self.options)
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use std::rt::io::net::ip::{SocketAddr, IpAddr, Ipv4Addr};
  use extra::getopts::groups::*;

  pub trait SocketSettings {
    fn socket(&self) -> SocketAddr;
    fn port(&self) -> u16;
    fn ip(&self) -> IpAddr;
  }

  impl SocketSettings for Settings {
    fn socket(&self) -> SocketAddr {
      do self.fetch_with("bind") |addr| {
        match addr {
          Some(socket_addr) => { socket_addr },
          None => {
            let port: u16 = self.port();
            let ip: IpAddr = self.ip();
            SocketAddr { ip: ip, port: port }
          }
        }
      }
    }

    fn port(&self) -> u16 {
      self.fetch("port").unwrap_or(8080)
    }

    fn ip(&self) -> IpAddr {
      self.fetch("ip").unwrap_or(Ipv4Addr(127,0,0,1))
    }
  }

  #[test]
  fn test_simple_conversion() {
    let mut settings = Settings::new();
    settings.set("port", 12345);
    let settings = settings.fetch("port");
    assert_eq!(Some(12345), settings)
  }

  #[test]
  fn test_compound_socket_settings() {
    let mut settings = Settings::new();
    settings.set("port", "12345");
    settings.set("ip", "127.0.0.1");
    let socket = settings.socket();
    assert_eq!(socket.to_str(), ~"127.0.0.1:12345")
  }

  #[test]
  fn test_socket_overrides_port() {
    let mut settings = Settings::new();
    settings.set("port", "12345");
    settings.set("ip", "127.0.0.1");
    settings.set("bind", "0.0.0.0:4567");
    let socket = settings.socket();
    assert_eq!(socket.to_str(), ~"0.0.0.0:4567")
  }

  #[test]
  fn test_opt_parse_optional() {
    let mut settings = Settings::new();
    settings.opt(optopt("p", "port", "The port to bind to", "eg: 4000"));

    let args = ~[~"myprog", ~"-p", ~"3000"];
    let error = settings.load_args(args);

    assert!(error.is_none());
    assert_eq!(settings.fetch("port"), Some(3000))
  }

  #[test]
  fn test_opt_parse_req_with_given() {
    let mut settings = Settings::new();
    settings.opt(reqopt("p", "port", "The port to bind to", "eg: 4000"));

    let args = ~[~"myprog", ~"-p", ~"3000"];
    let error = settings.load_args(args);

    assert!(error.is_none());
    assert_eq!(settings.fetch("port"), Some(3000))
  }

  #[test]
  fn test_opt_parse_req_without_given() {
    let mut settings = Settings::new();
    settings.opt(reqopt("p", "port", "The port to bind to", "eg: 4000"));

    let args = ~[~"myprog"];
    let error = settings.load_args(args);

    assert!(error.is_some());
    let port: Option<int> = settings.fetch("port");
    assert_eq!(port, None)
  }

  #[test]
  fn test_usage() {
    let mut settings = Settings::new();
    settings.opt(reqopt("p", "port", "The port to bind to", "eg: 4000"));
    let usage = settings.usage(&"this is how it works");

    assert!(usage.contains("this is how it works"))
    assert!(usage.contains("--port"))
  }
}<|endoftext|>


<commit_before>// Lumol, an extensible molecular simulation engine
// Copyright (C) 2015-2016 G. Fraux — BSD license
use toml::Table;
use std::path::PathBuf;

use lumol::sys::{read_molecule, molecule_type};
use lumol::sim::mc::*;
use lumol::units;

use error::{Error, Result};
use FromTomlWithData;
use extract;
use simulations::get_input_path;

impl FromTomlWithData for MonteCarlo {
    type Data = PathBuf;
    fn from_toml(config: &Table, root: PathBuf) -> Result<MonteCarlo> {
        let temperature = try!(extract::str("temperature", config, "Monte-Carlo propagator"));
        let temperature = try!(units::from_str(temperature));

        let mut mc = MonteCarlo::new(temperature);

        let moves = try!(extract::slice("moves", config, "Monte-Carlo propagator"));
        for mc_move in moves {
            let mc_move = try!(mc_move.as_table().ok_or(
                Error::from("All moves must be tables in Monte-Carlo")
            ));

            let frequency = if mc_move.get("frequency").is_some() {
                try!(extract::number("frequency", mc_move, "Monte-Carlo move"))
            } else {
                1.0
            };

            let mc_move: Box<MCMove> = match try!(extract::typ(mc_move, "Monte-Carlo move")) {
                "Translate" => Box::new(try!(Translate::from_toml(mc_move, root.clone()))),
                "Rotate" => Box::new(try!(Rotate::from_toml(mc_move, root.clone()))),
                other => return Err(Error::from(
                    format!("Unknown Monte-Carlo move '{}'", other)
                ))
            };

            mc.add(mc_move, frequency);
        }
        return Ok(mc);
    }
}

impl FromTomlWithData for Translate {
    type Data = PathBuf;
    fn from_toml(config: &Table, root: PathBuf) -> Result<Translate> {
        let delta = try!(extract::str("delta", config, "Translate move"));
        let delta = try!(units::from_str(delta));

        if config.get("molecule").is_some() {
            let molfile = try!(extract::str("molecule", config, "Translate move"));
            let molfile = get_input_path(root, molfile);
            let (molecule, atoms) = try!(read_molecule(molfile));
            let moltype = molecule_type(&molecule, &atoms);
            Ok(Translate::with_moltype(delta, moltype))
        } else {
            Ok(Translate::new(delta))
        }
    }
}

impl FromTomlWithData for Rotate {
    type Data = PathBuf;
    fn from_toml(config: &Table, root: PathBuf) -> Result<Rotate> {
        let delta = try!(extract::str("delta", config, "Rotate move"));
        let delta = try!(units::from_str(delta));

        if config.get("molecule").is_some() {
            let molfile = try!(extract::str("molecule", config, "Translate move"));
            let molfile = get_input_path(root, molfile);
            let (molecule, atoms) = try!(read_molecule(molfile));
            let moltype = molecule_type(&molecule, &atoms);
            Ok(Rotate::with_moltype(delta, moltype))
        } else {
            Ok(Rotate::new(delta))
        }
    }
}
<commit_msg>Added implementation for resize move.<commit_after>// Lumol, an extensible molecular simulation engine
// Copyright (C) 2015-2016 G. Fraux — BSD license
use toml::Table;
use std::path::PathBuf;

use lumol::sys::{read_molecule, molecule_type};
use lumol::sim::mc::*;
use lumol::units;

use error::{Error, Result};
use FromTomlWithData;
use extract;
use simulations::get_input_path;

impl FromTomlWithData for MonteCarlo {
    type Data = PathBuf;
    fn from_toml(config: &Table, root: PathBuf) -> Result<MonteCarlo> {
        let temperature = try!(extract::str("temperature", config, "Monte-Carlo propagator"));
        let temperature = try!(units::from_str(temperature));

        let mut mc = MonteCarlo::new(temperature);

        let moves = try!(extract::slice("moves", config, "Monte-Carlo propagator"));
        for mc_move in moves {
            let mc_move = try!(mc_move.as_table().ok_or(
                Error::from("All moves must be tables in Monte-Carlo")
            ));

            let frequency = if mc_move.get("frequency").is_some() {
                try!(extract::number("frequency", mc_move, "Monte-Carlo move"))
            } else {
                1.0
            };

            let mc_move: Box<MCMove> = match try!(extract::typ(mc_move, "Monte-Carlo move")) {
                "Translate" => Box::new(try!(Translate::from_toml(mc_move, root.clone()))),
                "Rotate" => Box::new(try!(Rotate::from_toml(mc_move, root.clone()))),
                "Resize" => Box::new(try!(Resize::from_toml(mc_move, root.clone()))),
                other => return Err(Error::from(
                    format!("Unknown Monte-Carlo move '{}'", other)
                ))
            };

            mc.add(mc_move, frequency);
        }
        return Ok(mc);
    }
}

impl FromTomlWithData for Translate {
    type Data = PathBuf;
    fn from_toml(config: &Table, root: PathBuf) -> Result<Translate> {
        let delta = try!(extract::str("delta", config, "Translate move"));
        let delta = try!(units::from_str(delta));

        if config.get("molecule").is_some() {
            let molfile = try!(extract::str("molecule", config, "Translate move"));
            let molfile = get_input_path(root, molfile);
            let (molecule, atoms) = try!(read_molecule(molfile));
            let moltype = molecule_type(&molecule, &atoms);
            Ok(Translate::with_moltype(delta, moltype))
        } else {
            Ok(Translate::new(delta))
        }
    }
}

impl FromTomlWithData for Rotate {
    type Data = PathBuf;
    fn from_toml(config: &Table, root: PathBuf) -> Result<Rotate> {
        let delta = try!(extract::str("delta", config, "Rotate move"));
        let delta = try!(units::from_str(delta));

        if config.get("molecule").is_some() {
            let molfile = try!(extract::str("molecule", config, "Rotate move"));
            let molfile = get_input_path(root, molfile);
            let (molecule, atoms) = try!(read_molecule(molfile));
            let moltype = molecule_type(&molecule, &atoms);
            Ok(Rotate::with_moltype(delta, moltype))
        } else {
            Ok(Rotate::new(delta))
        }
    }
}

impl FromTomlWithData for Resize {
    type Data = PathBuf;
    fn from_toml(config: &Table, root: PathBuf) -> Result<Resize> {
        let pressure = try!(extract::str("pressure", config, "Resize move"));
        let pressure = try!(units::from_str(pressure));

        let delta = try!(extract::str("delta", config, "Resize move"));
        let delta = try!(units::from_str(delta));

        Ok(Resize::new(pressure, delta))
    }
}
<|endoftext|>