<commit_before>#![cfg(feature = "use_std")]

use std::collections::HashMap;
use std::hash::Hash;
use std::iter::Iterator;

#[doc(hidden)]
/// A wrapper to allow for an easy [`into_grouping_map_by`](../trait.Itertools.html#method.into_grouping_map_by)
pub struct MapForGrouping<I, F>(I, F);

impl<I, F> MapForGrouping<I, F> {
    pub(crate) fn new(iter: I, key_mapper: F) -> Self {
        Self(iter, key_mapper)
    }
}

impl<K, V, I, F> Iterator for MapForGrouping<I, F>
where
    I: Iterator<Item = V>,
    K: Hash + Eq,
    F: FnMut(&V) -> K,
{
    type Item = (K, V);
    fn next(&mut self) -> Option<Self::Item> {
        let val = self.0.next()?;
        Some(((self.1)(&val), val))
    }
}

/// Creates a new `GroupingMap` from `iter`
pub fn new<I, K, V>(iter: I) -> GroupingMap<I>
where
    I: Iterator<Item = (K, V)>,
    K: Hash + Eq,
{
    GroupingMap { iter }
}

/// `GroupingMap` is an intermediate struct for efficient group-and-fold operations.
/// It groups elements by their key and at the same time fold each group
/// using some aggregating operation.
///
/// No method on this struct performs temporary allocations.
#[must_use = "GroupingMap is lazy and do nothing unless consumed"]
pub struct GroupingMap<I> {
    iter: I,
}

impl<I, K, V> GroupingMap<I>
where
    I: Iterator<Item = (K, V)>,
    K: Hash + Eq,
{
    /// This is the generic way to perform any operations on a `GroupingMap`.
    /// It's suggested to use this method only to implement custom operations
    /// when the already provided ones are not enough.
    ///
    /// Groups elements from the `GroupingMap` source by key and applies `operation` to the elements
    /// of each group sequentially, passing the previously accumulated value, a reference to the key
    /// and the current element as arguments, and stores the results in an `HashMap`.
    ///
    /// The `operation` function is invoked on each element with the following parameters:
    ///  - the current value of the accumulator of the group if there is currently one;
    ///  - a reference to the key of the group this element belongs to;
    ///  - the element from the source being aggregated;
    /// If `operation` returns `Some(element)` then the accumulator is updated with `element`,
    /// otherwise the previous accumulation is discarded.
    ///
    /// Return a `HashMap` associating the key of each group with the result of aggregation of the group elements.
    /// If there's no result then there won't be an entry associated to that key.
    ///
    /// ```
    /// use itertools::Itertools;
    ///
    /// let data = vec![2, 8, 5, 7, 9, 0, 4, 10];
    /// let lookup = data.into_iter()
    ///     .into_grouping_map_by(|&n| n % 4)
    ///     .aggregate(|acc, _, val| {
    ///         if val == 0 || val == 10 {
    ///             None
    ///         } else {
    ///             Some(acc.unwrap_or(0) + val)
    ///         }
    ///     });
    ///
    /// assert_eq!(lookup[&0], 4);        // 0 resets the accumulator so only 4 is summed
    /// assert_eq!(lookup[&1], 14);       // 5 + 9
    /// assert_eq!(lookup.get(&2), None); // 10 resets the accumulator and nothing is summed afterward
    /// assert_eq!(lookup[&3], 7);        // 7
    /// assert_eq!(lookup.len(), 3);      // The final keys are only 0, 1 and 2
    /// ```
    pub fn aggregate<FO, R>(self, mut operation: FO) -> HashMap<K, R>
    where
        FO: FnMut(Option<R>, &K, V) -> Option<R>,
    {
        let mut destination_map = HashMap::new();

        for (key, val) in self.iter {
            let acc = destination_map.remove(&key);
            if let Some(op_res) = operation(acc, &key, val) {
                destination_map.insert(key, op_res);
            }
        }

        destination_map
    }

    /// Groups elements from the `GroupingMap` source by key and applies `operation` to the elements
    /// of each group sequentially, passing the previously accumulated value, a reference to the key
    /// and the current element as arguments, and stores the results in a new map.
    ///
    /// `init` is the value from which will be cloned the initial value of each accumulator.
    ///
    /// `operation` is a function that is invoked on each element with the following parameters:
    ///  - the current value of the accumulator of the group;
    ///  - a reference to the key of the group this element belongs to;
    ///  - the element from the source being accumulated.
    ///
    /// Return a `HashMap` associating the key of each group with the result of folding the group elements.
    ///
    /// ```
    /// use itertools::Itertools;
    ///
    /// let lookup = (1..=7)
    ///     .into_grouping_map_by(|&n| n % 3)
    ///     .fold(0, |acc, _, val| acc + val);
    ///
    /// assert_eq!(lookup[&0], 9);   // 3 + 6
    /// assert_eq!(lookup[&1], 12);  // 1 + 4 + 7
    /// assert_eq!(lookup[&2], 7);   // 2 + 5
    /// assert_eq!(lookup.len(), 3);
    /// ```
    pub fn fold<FO, R>(self, init: R, mut operation: FO) -> HashMap<K, R>
    where
        R: Clone,
        FO: FnMut(R, &K, V) -> R,
    {
        self.aggregate(|acc, key, val| {
            let acc = acc.unwrap_or_else(|| init.clone());
            Some(operation(acc, key, val))
        })
    }

    /// Groups elements from the `GroupingMap` source by key and applies `operation` to the elements
    /// of each group sequentially, passing the previously accumulated value, a reference to the key
    /// and the current element as arguments, and stores the results in a new map.
    ///
    /// This is similar to [`fold`] but the initial value of the accumulator is the first element of the group.
    ///
    /// `operation` is a function that is invoked on each element with the following parameters:
    ///  - the current value of the accumulator of the group;
    ///  - a reference to the key of the group this element belongs to;
    ///  - the element from the source being accumulated.
    ///
    /// Return a `HashMap` associating the key of each group with the result of folding the group elements.
    ///
    /// [`fold`]: #tymethod.fold
    ///
    /// ```
    /// use itertools::Itertools;
    ///
    /// let lookup = (1..=7)
    ///     .into_grouping_map_by(|&n| n % 3)
    ///     .fold_first(|acc, _, val| acc + val);
    ///
    /// assert_eq!(lookup[&0], 9);   // 3 + 6
    /// assert_eq!(lookup[&1], 12);  // 1 + 4 + 7
    /// assert_eq!(lookup[&2], 7);   // 2 + 5
    /// assert_eq!(lookup.len(), 3);
    /// ```
    pub fn fold_first<FO>(self, mut operation: FO) -> HashMap<K, V>
    where
        FO: FnMut(V, &K, V) -> V,
    {
        self.aggregate(|acc, key, val| {
            Some(match acc {
                Some(acc) => operation(acc, key, val),
                None => val,
            })
        })
    }

    /// Groups elements from the `GroupingMap` source by key and collects the elements of each group in
    /// an instance of `C`. The iteration order is preserved when inserting elements.
    ///
    /// Return a `HashMap` associating the key of each group with the collection containing the elements of that group.
    ///
    /// ```
    /// use itertools::Itertools;
    /// use std::collections::HashSet;
    ///
    /// let lookup = vec![0, 1, 2, 3, 4, 5, 6, 2, 3, 6].into_iter()
    ///     .into_grouping_map_by(|&n| n % 3)
    ///     .collect::<HashSet<_>>();
    ///
    /// assert_eq!(lookup[&0], vec![0, 3, 6].into_iter().collect());
    /// assert_eq!(lookup[&1], vec![1, 4].into_iter().collect());
    /// assert_eq!(lookup[&2], vec![2, 5].into_iter().collect());
    /// assert_eq!(lookup.len(), 3);
    /// ```
    pub fn collect<C>(self) -> HashMap<K, C>
    where
        C: Default + Extend<V>,
    {
        self.aggregate(|acc, _, v| {
            let mut acc = acc.unwrap_or_else(C::default);
            acc.extend(Some(v));
            Some(acc)
        })
    }

    /// Groups elements from the `GroupingMap` source by key and counts them.
    ///
    /// Return a `HashMap` associating the key of each group with the number of elements in that group.
    ///
    /// ```
    /// use itertools::Itertools;
    ///
    /// let lookup = "This is a string".chars()
    ///     .into_grouping_map_by(|&c| c)
    ///     .count();
    ///
    /// assert_eq!(lookup[&'T'], 1);
    /// assert_eq!(lookup[&'h'], 1);
    /// assert_eq!(lookup[&'i'], 3);
    /// assert_eq!(lookup[&'s'], 3);
    /// assert_eq!(lookup[&' '], 3);
    /// assert_eq!(lookup[&'a'], 1);
    /// assert_eq!(lookup[&'t'], 1);
    /// assert_eq!(lookup[&'r'], 1);
    /// assert_eq!(lookup[&'n'], 1);
    /// assert_eq!(lookup[&'g'], 1);
    /// assert_eq!(lookup.len(), 10);
    /// ```
    pub fn count(self) -> HashMap<K, usize> {
        self.fold(0, |acc, _, _| acc + 1)
    }
}
<commit_msg>Formated where-clauses to be consistent with the rest of the repo<commit_after>#![cfg(feature = "use_std")]

use std::collections::HashMap;
use std::hash::Hash;
use std::iter::Iterator;

#[doc(hidden)]
/// A wrapper to allow for an easy [`into_grouping_map_by`](../trait.Itertools.html#method.into_grouping_map_by)
pub struct MapForGrouping<I, F>(I, F);

impl<I, F> MapForGrouping<I, F> {
    pub(crate) fn new(iter: I, key_mapper: F) -> Self {
        Self(iter, key_mapper)
    }
}

impl<K, V, I, F> Iterator for MapForGrouping<I, F>
    where I: Iterator<Item = V>,
          K: Hash + Eq,
          F: FnMut(&V) -> K,
{
    type Item = (K, V);
    fn next(&mut self) -> Option<Self::Item> {
        let val = self.0.next()?;
        Some(((self.1)(&val), val))
    }
}

/// Creates a new `GroupingMap` from `iter`
pub fn new<I, K, V>(iter: I) -> GroupingMap<I>
    where I: Iterator<Item = (K, V)>,
          K: Hash + Eq,
{
    GroupingMap { iter }
}

/// `GroupingMap` is an intermediate struct for efficient group-and-fold operations.
/// It groups elements by their key and at the same time fold each group
/// using some aggregating operation.
///
/// No method on this struct performs temporary allocations.
#[must_use = "GroupingMap is lazy and do nothing unless consumed"]
pub struct GroupingMap<I> {
    iter: I,
}

impl<I, K, V> GroupingMap<I>
    where I: Iterator<Item = (K, V)>,
          K: Hash + Eq,
{
    /// This is the generic way to perform any operations on a `GroupingMap`.
    /// It's suggested to use this method only to implement custom operations
    /// when the already provided ones are not enough.
    ///
    /// Groups elements from the `GroupingMap` source by key and applies `operation` to the elements
    /// of each group sequentially, passing the previously accumulated value, a reference to the key
    /// and the current element as arguments, and stores the results in an `HashMap`.
    ///
    /// The `operation` function is invoked on each element with the following parameters:
    ///  - the current value of the accumulator of the group if there is currently one;
    ///  - a reference to the key of the group this element belongs to;
    ///  - the element from the source being aggregated;
    /// If `operation` returns `Some(element)` then the accumulator is updated with `element`,
    /// otherwise the previous accumulation is discarded.
    ///
    /// Return a `HashMap` associating the key of each group with the result of aggregation of the group elements.
    /// If there's no result then there won't be an entry associated to that key.
    ///
    /// ```
    /// use itertools::Itertools;
    ///
    /// let data = vec![2, 8, 5, 7, 9, 0, 4, 10];
    /// let lookup = data.into_iter()
    ///     .into_grouping_map_by(|&n| n % 4)
    ///     .aggregate(|acc, _, val| {
    ///         if val == 0 || val == 10 {
    ///             None
    ///         } else {
    ///             Some(acc.unwrap_or(0) + val)
    ///         }
    ///     });
    ///
    /// assert_eq!(lookup[&0], 4);        // 0 resets the accumulator so only 4 is summed
    /// assert_eq!(lookup[&1], 14);       // 5 + 9
    /// assert_eq!(lookup.get(&2), None); // 10 resets the accumulator and nothing is summed afterward
    /// assert_eq!(lookup[&3], 7);        // 7
    /// assert_eq!(lookup.len(), 3);      // The final keys are only 0, 1 and 2
    /// ```
    pub fn aggregate<FO, R>(self, mut operation: FO) -> HashMap<K, R>
        where FO: FnMut(Option<R>, &K, V) -> Option<R>,
    {
        let mut destination_map = HashMap::new();

        for (key, val) in self.iter {
            let acc = destination_map.remove(&key);
            if let Some(op_res) = operation(acc, &key, val) {
                destination_map.insert(key, op_res);
            }
        }

        destination_map
    }

    /// Groups elements from the `GroupingMap` source by key and applies `operation` to the elements
    /// of each group sequentially, passing the previously accumulated value, a reference to the key
    /// and the current element as arguments, and stores the results in a new map.
    ///
    /// `init` is the value from which will be cloned the initial value of each accumulator.
    ///
    /// `operation` is a function that is invoked on each element with the following parameters:
    ///  - the current value of the accumulator of the group;
    ///  - a reference to the key of the group this element belongs to;
    ///  - the element from the source being accumulated.
    ///
    /// Return a `HashMap` associating the key of each group with the result of folding the group elements.
    ///
    /// ```
    /// use itertools::Itertools;
    ///
    /// let lookup = (1..=7)
    ///     .into_grouping_map_by(|&n| n % 3)
    ///     .fold(0, |acc, _, val| acc + val);
    ///
    /// assert_eq!(lookup[&0], 9);   // 3 + 6
    /// assert_eq!(lookup[&1], 12);  // 1 + 4 + 7
    /// assert_eq!(lookup[&2], 7);   // 2 + 5
    /// assert_eq!(lookup.len(), 3);
    /// ```
    pub fn fold<FO, R>(self, init: R, mut operation: FO) -> HashMap<K, R>
        where R: Clone,
              FO: FnMut(R, &K, V) -> R,
    {
        self.aggregate(|acc, key, val| {
            let acc = acc.unwrap_or_else(|| init.clone());
            Some(operation(acc, key, val))
        })
    }

    /// Groups elements from the `GroupingMap` source by key and applies `operation` to the elements
    /// of each group sequentially, passing the previously accumulated value, a reference to the key
    /// and the current element as arguments, and stores the results in a new map.
    ///
    /// This is similar to [`fold`] but the initial value of the accumulator is the first element of the group.
    ///
    /// `operation` is a function that is invoked on each element with the following parameters:
    ///  - the current value of the accumulator of the group;
    ///  - a reference to the key of the group this element belongs to;
    ///  - the element from the source being accumulated.
    ///
    /// Return a `HashMap` associating the key of each group with the result of folding the group elements.
    ///
    /// [`fold`]: #tymethod.fold
    ///
    /// ```
    /// use itertools::Itertools;
    ///
    /// let lookup = (1..=7)
    ///     .into_grouping_map_by(|&n| n % 3)
    ///     .fold_first(|acc, _, val| acc + val);
    ///
    /// assert_eq!(lookup[&0], 9);   // 3 + 6
    /// assert_eq!(lookup[&1], 12);  // 1 + 4 + 7
    /// assert_eq!(lookup[&2], 7);   // 2 + 5
    /// assert_eq!(lookup.len(), 3);
    /// ```
    pub fn fold_first<FO>(self, mut operation: FO) -> HashMap<K, V>
        where FO: FnMut(V, &K, V) -> V,
    {
        self.aggregate(|acc, key, val| {
            Some(match acc {
                Some(acc) => operation(acc, key, val),
                None => val,
            })
        })
    }

    /// Groups elements from the `GroupingMap` source by key and collects the elements of each group in
    /// an instance of `C`. The iteration order is preserved when inserting elements.
    ///
    /// Return a `HashMap` associating the key of each group with the collection containing the elements of that group.
    ///
    /// ```
    /// use itertools::Itertools;
    /// use std::collections::HashSet;
    ///
    /// let lookup = vec![0, 1, 2, 3, 4, 5, 6, 2, 3, 6].into_iter()
    ///     .into_grouping_map_by(|&n| n % 3)
    ///     .collect::<HashSet<_>>();
    ///
    /// assert_eq!(lookup[&0], vec![0, 3, 6].into_iter().collect());
    /// assert_eq!(lookup[&1], vec![1, 4].into_iter().collect());
    /// assert_eq!(lookup[&2], vec![2, 5].into_iter().collect());
    /// assert_eq!(lookup.len(), 3);
    /// ```
    pub fn collect<C>(self) -> HashMap<K, C>
        where C: Default + Extend<V>,
    {
        self.aggregate(|acc, _, v| {
            let mut acc = acc.unwrap_or_else(C::default);
            acc.extend(Some(v));
            Some(acc)
        })
    }

    /// Groups elements from the `GroupingMap` source by key and counts them.
    ///
    /// Return a `HashMap` associating the key of each group with the number of elements in that group.
    ///
    /// ```
    /// use itertools::Itertools;
    ///
    /// let lookup = "This is a string".chars()
    ///     .into_grouping_map_by(|&c| c)
    ///     .count();
    ///
    /// assert_eq!(lookup[&'T'], 1);
    /// assert_eq!(lookup[&'h'], 1);
    /// assert_eq!(lookup[&'i'], 3);
    /// assert_eq!(lookup[&'s'], 3);
    /// assert_eq!(lookup[&' '], 3);
    /// assert_eq!(lookup[&'a'], 1);
    /// assert_eq!(lookup[&'t'], 1);
    /// assert_eq!(lookup[&'r'], 1);
    /// assert_eq!(lookup[&'n'], 1);
    /// assert_eq!(lookup[&'g'], 1);
    /// assert_eq!(lookup.len(), 10);
    /// ```
    pub fn count(self) -> HashMap<K, usize> {
        self.fold(0, |acc, _, _| acc + 1)
    }
}
<|endoftext|>


<commit_before>use na::{Mat2, DMat};
use std::collections::HashMap;
use std::num::*;
use itertools::Itertools;
use std::cell::RefCell;
use std::rc::Rc;

mod test;

#[test]
fn test_which_grid() {
    let loc = (-6., 6.);
    let i_rn = (-10.0, 10.0);
    let j_rn = (-10.0, 10.0);
    let i_bins = 10 as usize;
    let j_bins = 10 as usize;

    let result = grid_helpers::which_grid(loc, i_rn, j_rn, i_bins, j_bins).unwrap();
    assert_eq!((2, 8), result);

}

mod grid_helpers {
    pub fn which_grid(val: (f64, f64), i_range: (f64, f64), j_range: (f64, f64), i_bins: usize, j_bins: usize) -> Result<(usize, usize), String> {
        let i_size = (i_range.1 - i_range.0) / i_bins as f64;
        let i_number_of_sizes = ((val.0 - i_range.0) / i_size) as usize;
        let j_size = (j_range.1 - j_range.0) / j_bins as f64;
        let j_number_of_sizes = ((val.1 - j_range.0) / j_size) as usize;

        assert!(i_number_of_sizes < i_bins);
        assert!(j_number_of_sizes < j_bins);

        Ok((i_number_of_sizes, j_number_of_sizes))
    }

//
//        fn get_value_at_time(&self, time: u32, lambda: f64, dats: Vec<((usize,usize),Dat)>) -> Result<f64, String> {
//
//    //TODO time - 1 is wrong, it should be biggest time smaller than current
//    let coeff = self.compute_decay_coeff_at_time(time, time - 5, lambda);
//
//    let sum_vals = dats.iter().fold(0.0, |sum, x| sum + x.1.val);
//    println!("sum vals: {}", sum_vals);
//    let new_d = coeff * sum_vals + 1.0;
//    println!("new D: {}", new_d);
//
//    Ok(new_d)
//    }

//        fn compute_decay_coeff_at_time(&self, t_n: u32, t_l: u32, lambda: f64) -> f64 {
//    lambda.powf((t_n - t_l) as f64)
//    }
}

impl Default for DStreamProps {
    fn default() -> DStreamProps {
        DStreamProps {
            c_m: 3.0,
            c_l: 0.8,
            lambda: 0.998,
            beta: 0.3,
            i_bins: 10 as usize,
            j_bins: 10 as usize,
            i_range: (-10.0, 10.0),
            j_range: (-10.0, 10.0),
        }
    }
}
pub struct DStreamProps {
    c_m: f64,
    c_l: f64,
    lambda: f64,
    beta: f64,
    i_bins: usize,
    j_bins: usize,
    i_range: (f64, f64),
    j_range: (f64, f64),
}

/*

input data: [(x, y, v)]

///some impl
for some time t in 0..:
  _.put t, [(x, y, v)]

//some other impl
fn put (t, [(x, y, v)]):
  [(i, j, sum_vals)] = [x,y,v].map(i,j,v).groupby(i,j).reduce(_+_)
  foreach:
    g = density_grids[i, j]
    g.update(t, sum_vals)
    print g.get()
*/

#[derive(Clone)]
pub struct RawData {
    x: f64,
    y: f64,
    v: f64,
}

#[derive(Clone)]
#[derive(Debug)]
#[derive(Copy)]
struct BucketPoint {
    t: u32,
    v: f64,
}
#[derive(Clone)]
struct GridData {
    i: usize,
    j: usize,
    v: f64,
}
struct TheWorld {
    g_vec: Vec<((usize, usize), DG)>,
}

#[test]
fn test_new_put_works() {
    let raw_data_1 = RawData{x: 1.0, y: -1.0, v: 123.45};
    let raw_data_2 = RawData{x: 5.0, y: -7.0, v: 23.45};
    let raw_data_3 = RawData{x: 5.0, y: -7.0, v: 83.45};

    let rd_vec = vec!(raw_data_1, raw_data_2, raw_data_3);

    let t = 1;

    let default_vec : Vec<BucketPoint> = Vec::new();
    let mut world = TheWorld{g_vec: Vec::new()};
    world.init(default_vec);
    let res1 = world.put(t, rd_vec.clone());
    let res2 = world.put(t + 1, rd_vec.clone());
    let res3 = world.put(t + 2, rd_vec.clone());

}

impl TheWorld {
    fn init(&mut self, def_bucket: Vec<BucketPoint>) {
        println!("init");
        let props: DStreamProps = DStreamProps { ..Default::default() };

        for i in 0..props.i_bins {
            for j in 0..props.j_bins {
                let z_clone = def_bucket.clone();
                let some_default_dg = DG {i: i, j: j, updates_and_vals: z_clone};
                (self.g_vec).push(((i as usize, j as usize), some_default_dg));
            }
        }
    }
    fn do_time_steps() {}
    fn do_one_time_step(t: u32, data: Vec<RawData>) {}

    fn get_by_idx(&mut self, idx: (usize, usize))-> DG {
        let  vec_f: Vec<((usize, usize), DG)> = self.g_vec.clone().into_iter().filter(|i| i.0 == idx).collect();
        vec_f[0].1.clone()
    }
    fn update_by_idx(&mut self, idx: (usize, usize), dg: DG) -> Result<(), String> {
        self.g_vec.retain(|i| i.0 != idx);
        self.g_vec.push((idx, dg));
        Ok(())
    }
    fn put(&mut self, t: u32, dat: Vec<RawData>) -> Result<(), String> {

//        if ((loc2d.0 <= self.props.i_range.1) &&
//        (loc2d.0 >= self.props.i_range.0) &&
//        (loc2d.1 <= self.props.j_range.1) &&
//        (loc2d.1 >= self.props.j_range.0)) {
//
//            println!("valid!");
//            let idxs =
//            grid_helpers::which_grid(loc2d, self.props.i_range, self.props.j_range,
//                                     self.props.i_bins, self.props.j_bins).unwrap();

        let with_idxs: Vec<GridData> = dat
            .iter()
            .map(|rd| self.which_idxs(rd).unwrap())
            .collect();

        let props: DStreamProps = DStreamProps { ..Default::default() };

        for (key, group) in with_idxs.iter().group_by(|gd| (gd.i, gd.j)) {
            println!("--put: key, g size: {}{} : {}", key.0, key.1, group.len());

            let the_vec_of_vals: Vec<f64> = group.iter().map(|t| t.v).collect();

            let mut some_default_dg = DG {i: key.0, j: key.1, updates_and_vals: Vec::<BucketPoint>::new()};

            let teh_dg: &mut DG = &mut self.get_by_idx(key);
            let update_dg_result = teh_dg.update(t, the_vec_of_vals);
            let udpate_world_result = self.update_by_idx(key, teh_dg.clone());
        }
        Ok(())
    }
    fn which_idxs(&self, dat: &RawData) -> Result<GridData, String> {Ok((GridData{i:1,j:1,v:0.1}))}
}

#[derive(Debug)]
#[derive(Clone)]
//#[derive(Copy)] TODO: how to make this work?
struct DG {
    i: usize,
    j: usize,
    updates_and_vals: Vec<BucketPoint>,
}
impl DG {
    fn get_at_time(&self, t: u32) -> f64 {
        let last_update_time_and_value = self.get_last_update_and_value_to(t);
        let coeff = self.coeff(t, last_update_time_and_value.0);
        let d = coeff * last_update_time_and_value.1 + 1.0;

        d
    }
    fn update(&mut self, t: u32, vals: Vec<f64>) -> Result<(), String> {
        let sum = vals.clone().iter().fold(0.0, |sum, x| sum + x);
        self.updates_and_vals.push(BucketPoint {t: t, v: sum});
        println!("vals len from dg: {}", self.updates_and_vals.len());
        Ok(())
    }

    fn get_last_update_and_value_to(&self, t: u32) -> (u32, f64) {
        //TODO
        (1, 123.232)
    }

    fn coeff(&self, t_n: u32, t_l: u32) -> f64 {
        //TODO
        100.0343
    }

 }

#[test]
fn test_initialize_clustering() {

    let result = initialize_clustering(Vec::new());
    assert_eq!(Ok(()), result);
}

pub fn initialize_clustering(grid_list: Vec<RawData>) -> Result<(), String> {
    //update density of all grids in grid_list
    //assign each dense grid to a distinct cluster
    //label all other grids as NO_CLASS; bad grids!
    /*
    do until no change in cluster labels
          foreach cluster c
            foreach outside grid g of c
                foreach neighboring grid h of g
                    if h belongs to cluster c'
                        if |c| > |c'| label all grids in c' as c
                        else label all grids in c as c'
                    else if (h is translational) label h as in c
    end do
    */
    Ok(())
}

pub fn adjust_clustering(grid_list: Vec<RawData>) -> Result<(), String> {
    //update the density of all grids in grid_list
    /*
    foreach grid g whose attribute (dense/sparse/transitional) is changed since last call to adjust_clustering()
        if g is a sparse grid
            delete g from its cluster c, label g as NO_CLASS
            if (c becomes unconnected) split c into two clusters
        else if g is a dense grid
            among all neighboring grids of g, find out the grid h whoe cluster c_h has the largest size
            if h is a dense grid
                if (g is labelled as NO_CLASS) label g as in c_h
                else if (g is in cluster c and |c| > |c_h|)
                    label all grids in c_h as in c
                else if (g is in cluster c and |c| <= |c_h|)
                    label all grids in c as in c_h
            else if h is a transitional grid
                if ((g is NO_CLASS) and (h is an outside grid if g is added to c_h)) label g as in c_h
                else if (g is in cluster c and |c| >= |c_h|)
                    move h from cluster c_h to c
        else if (g is transitional grid)
            among neighboring clusters of g, find the largest one c'
            satisfying that g is an outside grid if added to it and
            label g as in c'
    */

    Ok(())
}<commit_msg>impl which_idxs: RawData -> GridData<commit_after>use na::{Mat2, DMat};
use std::collections::HashMap;
use std::num::*;
use itertools::Itertools;
use std::cell::RefCell;
use std::rc::Rc;

mod test;

#[test]
fn test_which_grid() {
    let loc = (-6., 6.);
    let i_rn = (-10.0, 10.0);
    let j_rn = (-10.0, 10.0);
    let i_bins = 10 as usize;
    let j_bins = 10 as usize;

    let result = grid_helpers::which_grid(loc, i_rn, j_rn, i_bins, j_bins).unwrap();
    assert_eq!((2, 8), result);

}

mod grid_helpers {
    pub fn which_grid(val: (f64, f64), i_range: (f64, f64), j_range: (f64, f64), i_bins: usize, j_bins: usize) -> Result<(usize, usize), String> {
        let i_size = (i_range.1 - i_range.0) / i_bins as f64;
        let i_number_of_sizes = ((val.0 - i_range.0) / i_size) as usize;
        let j_size = (j_range.1 - j_range.0) / j_bins as f64;
        let j_number_of_sizes = ((val.1 - j_range.0) / j_size) as usize;

        assert!(i_number_of_sizes < i_bins);
        assert!(j_number_of_sizes < j_bins);

        Ok((i_number_of_sizes, j_number_of_sizes))
    }

//
//        fn get_value_at_time(&self, time: u32, lambda: f64, dats: Vec<((usize,usize),Dat)>) -> Result<f64, String> {
//
//    //TODO time - 1 is wrong, it should be biggest time smaller than current
//    let coeff = self.compute_decay_coeff_at_time(time, time - 5, lambda);
//
//    let sum_vals = dats.iter().fold(0.0, |sum, x| sum + x.1.val);
//    println!("sum vals: {}", sum_vals);
//    let new_d = coeff * sum_vals + 1.0;
//    println!("new D: {}", new_d);
//
//    Ok(new_d)
//    }

//        fn compute_decay_coeff_at_time(&self, t_n: u32, t_l: u32, lambda: f64) -> f64 {
//    lambda.powf((t_n - t_l) as f64)
//    }
}

impl Default for DStreamProps {
    fn default() -> DStreamProps {
        DStreamProps {
            c_m: 3.0,
            c_l: 0.8,
            lambda: 0.998,
            beta: 0.3,
            i_bins: 10 as usize,
            j_bins: 10 as usize,
            i_range: (-10.0, 10.0),
            j_range: (-10.0, 10.0),
        }
    }
}
pub struct DStreamProps {
    c_m: f64,
    c_l: f64,
    lambda: f64,
    beta: f64,
    i_bins: usize,
    j_bins: usize,
    i_range: (f64, f64),
    j_range: (f64, f64),
}

/*

input data: [(x, y, v)]

///some impl
for some time t in 0..:
  _.put t, [(x, y, v)]

//some other impl
fn put (t, [(x, y, v)]):
  [(i, j, sum_vals)] = [x,y,v].map(i,j,v).groupby(i,j).reduce(_+_)
  foreach:
    g = density_grids[i, j]
    g.update(t, sum_vals)
    print g.get()
*/

#[derive(Clone)]
pub struct RawData {
    x: f64,
    y: f64,
    v: f64,
}

#[derive(Clone)]
#[derive(Debug)]
#[derive(Copy)]
struct BucketPoint {
    t: u32,
    v: f64,
}
#[derive(Clone)]
struct GridData {
    i: usize,
    j: usize,
    v: f64,
}
struct TheWorld {
    g_vec: Vec<((usize, usize), DG)>,
}

#[test]
fn test_new_put_works() {
    let raw_data_1 = RawData{x: 1.0, y: -1.0, v: 123.45};
    let raw_data_2 = RawData{x: 5.0, y: -7.0, v: 23.45};
    let raw_data_3 = RawData{x: 5.0, y: -7.0, v: 83.45};

    let rd_vec = vec!(raw_data_1, raw_data_2, raw_data_3);

    let t = 1;

    let default_vec : Vec<BucketPoint> = Vec::new();
    let mut world = TheWorld{g_vec: Vec::new()};
    world.init(default_vec);
    let res1 = world.put(t, rd_vec.clone());
    let res2 = world.put(t + 1, rd_vec.clone());
    let res3 = world.put(t + 2, rd_vec.clone());

}

impl TheWorld {
    fn init(&mut self, def_bucket: Vec<BucketPoint>) {
        println!("init");
        let props: DStreamProps = DStreamProps { ..Default::default() };

        for i in 0..props.i_bins {
            for j in 0..props.j_bins {
                let z_clone = def_bucket.clone();
                let some_default_dg = DG {i: i, j: j, updates_and_vals: z_clone};
                (self.g_vec).push(((i as usize, j as usize), some_default_dg));
            }
        }
    }
    fn do_time_steps() {}
    fn do_one_time_step(t: u32, data: Vec<RawData>) {}

    fn get_by_idx(&mut self, idx: (usize, usize))-> DG {
        let  vec_f: Vec<((usize, usize), DG)> = self.g_vec.clone().into_iter().filter(|i| i.0 == idx).collect();
        vec_f[0].1.clone()
    }
    fn update_by_idx(&mut self, idx: (usize, usize), dg: DG) -> Result<(), String> {
        self.g_vec.retain(|i| i.0 != idx);
        self.g_vec.push((idx, dg));
        Ok(())
    }
    fn put(&mut self, t: u32, dat: Vec<RawData>) -> Result<(), String> {

//        if ((loc2d.0 <= self.props.i_range.1) &&
//        (loc2d.0 >= self.props.i_range.0) &&
//        (loc2d.1 <= self.props.j_range.1) &&
//        (loc2d.1 >= self.props.j_range.0)) {
//
//            println!("valid!");
//            let idxs =
//            grid_helpers::which_grid(loc2d, self.props.i_range, self.props.j_range,
//                                     self.props.i_bins, self.props.j_bins).unwrap();

        let with_idxs: Vec<GridData> = dat
            .iter()
            .map(|rd| self.which_idxs(rd).unwrap())
            .collect();

        let props: DStreamProps = DStreamProps { ..Default::default() };

        for (key, group) in with_idxs.iter().group_by(|gd| (gd.i, gd.j)) {
            println!("--put: key, g size: ({},{}) : {}", key.0, key.1, group.len());

            let the_vec_of_vals: Vec<f64> = group.iter().map(|t| t.v).collect();

            let mut some_default_dg = DG {i: key.0, j: key.1, updates_and_vals: Vec::<BucketPoint>::new()};

            let teh_dg: &mut DG = &mut self.get_by_idx(key);
            let update_dg_result = teh_dg.update(t, the_vec_of_vals);
            let udpate_world_result = self.update_by_idx(key, teh_dg.clone());
        }
        Ok(())
    }
    fn which_idxs(&self, dat: &RawData) -> Result<GridData, String> {

        let props: DStreamProps = DStreamProps { ..Default::default() };

        let idxs = grid_helpers::which_grid((dat.x, dat.y), props.i_range, props.j_range,props.i_bins, props.j_bins).unwrap();

        Ok((GridData{i:idxs.0,j:idxs.1,v:dat.v}))

    }
}

#[derive(Debug)]
#[derive(Clone)]
//#[derive(Copy)] TODO: how to make this work?
struct DG {
    i: usize,
    j: usize,
    updates_and_vals: Vec<BucketPoint>,
}
impl DG {
    fn get_at_time(&self, t: u32) -> f64 {
        let last_update_time_and_value = self.get_last_update_and_value_to(t);
        let coeff = self.coeff(t, last_update_time_and_value.0);
        let d = coeff * last_update_time_and_value.1 + 1.0;

        d
    }
    fn update(&mut self, t: u32, vals: Vec<f64>) -> Result<(), String> {
        let sum = vals.clone().iter().fold(0.0, |sum, x| sum + x);
        self.updates_and_vals.push(BucketPoint {t: t, v: sum});
        println!("  times updated dg: {}", self.updates_and_vals.len());
        Ok(())
    }

    fn get_last_update_and_value_to(&self, t: u32) -> (u32, f64) {
        //TODO
        (1, 123.232)
    }

    fn coeff(&self, t_n: u32, t_l: u32) -> f64 {
        //TODO
        100.0343
    }

 }

#[test]
fn test_initialize_clustering() {

    let result = initialize_clustering(Vec::new());
    assert_eq!(Ok(()), result);
}

pub fn initialize_clustering(grid_list: Vec<RawData>) -> Result<(), String> {
    //update density of all grids in grid_list
    //assign each dense grid to a distinct cluster
    //label all other grids as NO_CLASS; bad grids!
    /*
    do until no change in cluster labels
          foreach cluster c
            foreach outside grid g of c
                foreach neighboring grid h of g
                    if h belongs to cluster c'
                        if |c| > |c'| label all grids in c' as c
                        else label all grids in c as c'
                    else if (h is translational) label h as in c
    end do
    */
    Ok(())
}

pub fn adjust_clustering(grid_list: Vec<RawData>) -> Result<(), String> {
    //update the density of all grids in grid_list
    /*
    foreach grid g whose attribute (dense/sparse/transitional) is changed since last call to adjust_clustering()
        if g is a sparse grid
            delete g from its cluster c, label g as NO_CLASS
            if (c becomes unconnected) split c into two clusters
        else if g is a dense grid
            among all neighboring grids of g, find out the grid h whoe cluster c_h has the largest size
            if h is a dense grid
                if (g is labelled as NO_CLASS) label g as in c_h
                else if (g is in cluster c and |c| > |c_h|)
                    label all grids in c_h as in c
                else if (g is in cluster c and |c| <= |c_h|)
                    label all grids in c as in c_h
            else if h is a transitional grid
                if ((g is NO_CLASS) and (h is an outside grid if g is added to c_h)) label g as in c_h
                else if (g is in cluster c and |c| >= |c_h|)
                    move h from cluster c_h to c
        else if (g is transitional grid)
            among neighboring clusters of g, find the largest one c'
            satisfying that g is an outside grid if added to it and
            label g as in c'
    */

    Ok(())
}<|endoftext|>


<commit_before>use std::num::zero;

fn horner<T:Num>(cs:&[T], x:T) -> T {
    cs.iter().rev().fold(zero::<T>(), |acc, c| (acc*x) + (*c))
}

fn main() {
    println!("{}", horner([-19i, 7, -4, 6], 3i)); // 128
}

#[cfg(test)]
mod test {
    use super::horner;
    #[test]
    fn test() {
        assert_eq!(horner([-19i, 7, -4, 6], 3i), 128);
        assert_eq!(horner([-1i, 7, -4, 6], 0i), -1);
        assert_eq!(horner([-0i, 3], 100i), 300);
        assert_eq!(horner([-20i, 7, 1], 10i), 150);
        assert_eq!(horner([-19i, 7, -4, 0], 5i), -84);
    }
}
<commit_msg>main not tested (fix warning)<commit_after>use std::num::zero;

fn horner<T:Num>(cs:&[T], x:T) -> T {
    cs.iter().rev().fold(zero::<T>(), |acc, c| (acc*x) + (*c))
}

#[cfg(not(test))]
fn main() {
    println!("{}", horner([-19i, 7, -4, 6], 3i)); // 128
}

#[cfg(test)]
mod test {
    use super::horner;
    #[test]
    fn test() {
        assert_eq!(horner([-19i, 7, -4, 6], 3i), 128);
        assert_eq!(horner([-1i, 7, -4, 6], 0i), -1);
        assert_eq!(horner([-0i, 3], 100i), 300);
        assert_eq!(horner([-20i, 7, 1], 10i), 150);
        assert_eq!(horner([-19i, 7, -4, 0], 5i), -84);
    }
}
<|endoftext|>


<commit_before>#![unstable(feature = "futures_api",
            reason = "futures in libcore are unstable",
            issue = "50547")]

use marker::Unpin;
use ops;
use pin::Pin;
use task::{Poll, Waker};

/// A future represents an asynchronous computation.
///
/// A future is a value that may not have finished computing yet. This kind of
/// "asynchronous value" makes it possible for a thread to continue doing useful
/// work while it waits for the value to become available.
///
/// # The `poll` method
///
/// The core method of future, `poll`, *attempts* to resolve the future into a
/// final value. This method does not block if the value is not ready. Instead,
/// the current task is scheduled to be woken up when it's possible to make
/// further progress by `poll`ing again. The wake up is performed using
/// the `waker` argument of the `poll()` method, which is a handle for waking
/// up the current task.
///
/// When using a future, you generally won't call `poll` directly, but instead
/// `await!` the value.
#[must_use = "futures do nothing unless polled"]
pub trait Future {
    /// The type of value produced on completion.
    type Output;

    /// Attempt to resolve the future to a final value, registering
    /// the current task for wakeup if the value is not yet available.
    ///
    /// # Return value
    ///
    /// This function returns:
    ///
    /// - [`Poll::Pending`] if the future is not ready yet
    /// - [`Poll::Ready(val)`] with the result `val` of this future if it
    ///   finished successfully.
    ///
    /// Once a future has finished, clients should not `poll` it again.
    ///
    /// When a future is not ready yet, `poll` returns `Poll::Pending` and
    /// stores a clone of the [`Waker`] to be woken once the future can
    /// make progress. For example, a future waiting for a socket to become
    /// readable would call `.clone()` on the [`Waker`] and store it.
    /// When a signal arrives elsewhere indicating that the socket is readable,
    /// `[Waker::wake]` is called and the socket future's task is awoken.
    /// Once a task has been woken up, it should attempt to `poll` the future
    /// again, which may or may not produce a final value.
    ///
    /// Note that on multiple calls to `poll`, only the most recent
    /// [`Waker`] passed to `poll` should be scheduled to receive a
    /// wakeup.
    ///
    /// # Runtime characteristics
    ///
    /// Futures alone are *inert*; they must be *actively* `poll`ed to make
    /// progress, meaning that each time the current task is woken up, it should
    /// actively re-`poll` pending futures that it still has an interest in.
    ///
    /// The `poll` function is not called repeatedly in a tight loop -- instead,
    /// it should only be called when the future indicates that it is ready to
    /// make progress (by calling `wake()`). If you're familiar with the
    /// `poll(2)` or `select(2)` syscalls on Unix it's worth noting that futures
    /// typically do *not* suffer the same problems of "all wakeups must poll
    /// all events"; they are more like `epoll(4)`.
    ///
    /// An implementation of `poll` should strive to return quickly, and should
    /// not block. Returning quickly prevents unnecessarily clogging up
    /// threads or event loops. If it is known ahead of time that a call to
    /// `poll` may end up taking awhile, the work should be offloaded to a
    /// thread pool (or something similar) to ensure that `poll` can return
    /// quickly.
    ///
    /// An implementation of `poll` may also never cause memory unsafety.
    ///
    /// # Panics
    ///
    /// Once a future has completed (returned `Ready` from `poll`),
    /// then any future calls to `poll` may panic, block forever, or otherwise
    /// cause any kind of bad behavior except causing memory unsafety.
    /// The `Future` trait itself provides no guarantees about the behavior
    /// of `poll` after a future has completed.
    ///
    /// [`Poll::Pending`]: ../task/enum.Poll.html#variant.Pending
    /// [`Poll::Ready(val)`]: ../task/enum.Poll.html#variant.Ready
    /// [`Waker`]: ../task/struct.Waker.html
    /// [`Waker::wake`]: ../task/struct.Waker.html#method.wake
    fn poll(self: Pin<&mut Self>, waker: &Waker) -> Poll<Self::Output>;
}

impl<F: ?Sized + Future + Unpin> Future for &mut F {
    type Output = F::Output;

    fn poll(mut self: Pin<&mut Self>, waker: &Waker) -> Poll<Self::Output> {
        F::poll(Pin::new(&mut **self), waker)
    }
}

impl
 Future for Pin

where
    P: Unpin + ops::DerefMut,
    P::Target: Future,
{
    type Output = <
::Target as Future>::Output;

    fn poll(self: Pin<&mut Self>, waker: &Waker) -> Poll<Self::Output> {
        Pin::get_mut(self).as_mut().poll(waker)
    }
}
<commit_msg>Rollup merge of #58606 - stjepang:put-future-into-spotlight, r=alexcrichton<commit_after>#![unstable(feature = "futures_api",
            reason = "futures in libcore are unstable",
            issue = "50547")]

use marker::Unpin;
use ops;
use pin::Pin;
use task::{Poll, Waker};

/// A future represents an asynchronous computation.
///
/// A future is a value that may not have finished computing yet. This kind of
/// "asynchronous value" makes it possible for a thread to continue doing useful
/// work while it waits for the value to become available.
///
/// # The `poll` method
///
/// The core method of future, `poll`, *attempts* to resolve the future into a
/// final value. This method does not block if the value is not ready. Instead,
/// the current task is scheduled to be woken up when it's possible to make
/// further progress by `poll`ing again. The wake up is performed using
/// the `waker` argument of the `poll()` method, which is a handle for waking
/// up the current task.
///
/// When using a future, you generally won't call `poll` directly, but instead
/// `await!` the value.
#[doc(spotlight)]
#[must_use = "futures do nothing unless polled"]
pub trait Future {
    /// The type of value produced on completion.
    type Output;

    /// Attempt to resolve the future to a final value, registering
    /// the current task for wakeup if the value is not yet available.
    ///
    /// # Return value
    ///
    /// This function returns:
    ///
    /// - [`Poll::Pending`] if the future is not ready yet
    /// - [`Poll::Ready(val)`] with the result `val` of this future if it
    ///   finished successfully.
    ///
    /// Once a future has finished, clients should not `poll` it again.
    ///
    /// When a future is not ready yet, `poll` returns `Poll::Pending` and
    /// stores a clone of the [`Waker`] to be woken once the future can
    /// make progress. For example, a future waiting for a socket to become
    /// readable would call `.clone()` on the [`Waker`] and store it.
    /// When a signal arrives elsewhere indicating that the socket is readable,
    /// `[Waker::wake]` is called and the socket future's task is awoken.
    /// Once a task has been woken up, it should attempt to `poll` the future
    /// again, which may or may not produce a final value.
    ///
    /// Note that on multiple calls to `poll`, only the most recent
    /// [`Waker`] passed to `poll` should be scheduled to receive a
    /// wakeup.
    ///
    /// # Runtime characteristics
    ///
    /// Futures alone are *inert*; they must be *actively* `poll`ed to make
    /// progress, meaning that each time the current task is woken up, it should
    /// actively re-`poll` pending futures that it still has an interest in.
    ///
    /// The `poll` function is not called repeatedly in a tight loop -- instead,
    /// it should only be called when the future indicates that it is ready to
    /// make progress (by calling `wake()`). If you're familiar with the
    /// `poll(2)` or `select(2)` syscalls on Unix it's worth noting that futures
    /// typically do *not* suffer the same problems of "all wakeups must poll
    /// all events"; they are more like `epoll(4)`.
    ///
    /// An implementation of `poll` should strive to return quickly, and should
    /// not block. Returning quickly prevents unnecessarily clogging up
    /// threads or event loops. If it is known ahead of time that a call to
    /// `poll` may end up taking awhile, the work should be offloaded to a
    /// thread pool (or something similar) to ensure that `poll` can return
    /// quickly.
    ///
    /// An implementation of `poll` may also never cause memory unsafety.
    ///
    /// # Panics
    ///
    /// Once a future has completed (returned `Ready` from `poll`),
    /// then any future calls to `poll` may panic, block forever, or otherwise
    /// cause any kind of bad behavior except causing memory unsafety.
    /// The `Future` trait itself provides no guarantees about the behavior
    /// of `poll` after a future has completed.
    ///
    /// [`Poll::Pending`]: ../task/enum.Poll.html#variant.Pending
    /// [`Poll::Ready(val)`]: ../task/enum.Poll.html#variant.Ready
    /// [`Waker`]: ../task/struct.Waker.html
    /// [`Waker::wake`]: ../task/struct.Waker.html#method.wake
    fn poll(self: Pin<&mut Self>, waker: &Waker) -> Poll<Self::Output>;
}

impl<F: ?Sized + Future + Unpin> Future for &mut F {
    type Output = F::Output;

    fn poll(mut self: Pin<&mut Self>, waker: &Waker) -> Poll<Self::Output> {
        F::poll(Pin::new(&mut **self), waker)
    }
}

impl
 Future for Pin

where
    P: Unpin + ops::DerefMut,
    P::Target: Future,
{
    type Output = <
::Target as Future>::Output;

    fn poll(self: Pin<&mut Self>, waker: &Waker) -> Poll<Self::Output> {
        Pin::get_mut(self).as_mut().poll(waker)
    }
}
<|endoftext|>


<commit_before>import T = inst::T;
import cmp::{eq, ord};
import num::num;

export min_value, max_value;
export min, max;
export add, sub, mul, div, rem;
export lt, le, eq, ne, ge, gt;
export is_positive, is_negative;
export is_nonpositive, is_nonnegative;
export range;
export compl;
export to_str, to_str_bytes;
export from_str, from_str_radix, str, parse_buf;
export ord, eq, num;

const min_value: T = 0 as T;
const max_value: T = 0 as T - 1 as T;

pure fn min(x: T, y: T) -> T { if x < y { x } else { y } }
pure fn max(x: T, y: T) -> T { if x > y { x } else { y } }

pure fn add(x: T, y: T) -> T { x + y }
pure fn sub(x: T, y: T) -> T { x - y }
pure fn mul(x: T, y: T) -> T { x * y }
pure fn div(x: T, y: T) -> T { x / y }
pure fn rem(x: T, y: T) -> T { x % y }

pure fn lt(x: T, y: T) -> bool { x < y }
pure fn le(x: T, y: T) -> bool { x <= y }
pure fn eq(x: T, y: T) -> bool { x == y }
pure fn ne(x: T, y: T) -> bool { x != y }
pure fn ge(x: T, y: T) -> bool { x >= y }
pure fn gt(x: T, y: T) -> bool { x > y }

pure fn is_positive(x: T) -> bool { x > 0 as T }
pure fn is_negative(x: T) -> bool { x < 0 as T }
pure fn is_nonpositive(x: T) -> bool { x <= 0 as T }
pure fn is_nonnegative(x: T) -> bool { x >= 0 as T }

#[doc = "Iterate over the range [`lo`..`hi`)"]
fn range(lo: T, hi: T, it: fn(T) -> bool) {
    let mut i = lo;
    while i < hi {
        if !it(i) { break }
        i += 1 as T;
    }
}

#[doc = "Computes the bitwise complement"]
pure fn compl(i: T) -> T {
    max_value ^ i
}

impl ord of ord for T {
    fn lt(&&other: T) -> bool {
        ret self < other;
    }
}

impl eq of eq for T {
    fn eq(&&other: T) -> bool {
        ret self == other;
    }
}

impl num of num for T {
    fn add(&&other: T)    -> T { ret self + other; }
    fn sub(&&other: T)    -> T { ret self - other; }
    fn mul(&&other: T)    -> T { ret self * other; }
    fn div(&&other: T)    -> T { ret self / other; }
    fn modulo(&&other: T) -> T { ret self % other; }
    fn neg()              -> T { ret -self;        }

    fn to_int()         -> int { ret self as int; }
    fn from_int(n: int) -> T   { ret n as T;      }
}

#[doc = "
Parse a buffer of bytes

# Arguments

* buf - A byte buffer
* radix - The base of the number

# Failure

`buf` must not be empty
"]
fn parse_buf(buf: [u8], radix: uint) -> option<T> {
    if vec::len(buf) == 0u { ret none; }
    let mut i = vec::len(buf) - 1u;
    let mut power = 1u as T;
    let mut n = 0u as T;
    loop {
        alt char::to_digit(buf[i] as char, radix) {
          some(d) { n += d as T * power; }
          none { ret none; }
        }
        power *= radix as T;
        if i == 0u { ret some(n); }
        i -= 1u;
    };
}

#[doc = "Parse a string to an int"]
fn from_str(s: str) -> option<T> { parse_buf(str::bytes(s), 10u) }

#[doc = "Parse a string as an unsigned integer."]
fn from_str_radix(buf: str, radix: u64) -> option<u64> {
    if str::len(buf) == 0u { ret none; }
    let mut i = str::len(buf) - 1u;
    let mut power = 1u64, n = 0u64;
    loop {
        alt char::to_digit(buf[i] as char, radix as uint) {
          some(d) { n += d as u64 * power; }
          none { ret none; }
        }
        power *= radix;
        if i == 0u { ret some(n); }
        i -= 1u;
    };
}

#[doc = "
Convert to a string in a given base

# Failure

Fails if `radix` < 2 or `radix` > 16
"]
fn to_str(num: T, radix: uint) -> str unsafe {
    to_str_bytes(false, num, radix) {|slice|
        vec::unpack_slice(slice) {|p, len|
            str::unsafe::from_buf_len(p, len)
        }
    }
}

#[doc = "Low-level helper routine for string conversion."]
fn to_str_bytes<U>(neg: bool, num: T, radix: uint,
                   f: fn([u8]/&) -> U) -> U unsafe {

    #[inline(always)]
    fn digit(n: T) -> u8 {
        if n <= 9u as T {
            n as u8 + '0' as u8
        } else if n <= 15u as T {
            (n - 10 as T) as u8 + 'a' as u8
        } else {
            fail;
        }
    }

    assert (1u < radix && radix <= 16u);

    // Enough room to hold any number in any radix.
    // Worst case: 64-bit number, binary-radix, with
    // a leading negative sign = 65 bytes.
    let buf : [mut u8]/65 =
        [mut
         0u8,0u8,0u8,0u8,0u8, 0u8,0u8,0u8,0u8,0u8,
         0u8,0u8,0u8,0u8,0u8, 0u8,0u8,0u8,0u8,0u8,

         0u8,0u8,0u8,0u8,0u8, 0u8,0u8,0u8,0u8,0u8,
         0u8,0u8,0u8,0u8,0u8, 0u8,0u8,0u8,0u8,0u8,

         0u8,0u8,0u8,0u8,0u8, 0u8,0u8,0u8,0u8,0u8,
         0u8,0u8,0u8,0u8,0u8, 0u8,0u8,0u8,0u8,0u8,

         0u8,0u8,0u8,0u8,0u8
         ]/65;

    // FIXME: post-snapshot, you can do this without
    // the raw pointers and unsafe bits, and the
    // codegen will prove it's all in-bounds, no
    // extra cost.

    vec::unpack_slice(buf) {|p, len|
        let mp = p as *mut u8;
        let mut i = len;
        let mut n = num;
        let radix = radix as T;
        loop {
            i -= 1u;
            assert 0u < i && i < len;
            *ptr::mut_offset(mp, i) = digit(n % radix);
            n /= radix;
            if n == 0 as T { break; }
        }

        assert 0u < i && i < len;

        if neg {
            i -= 1u;
            *ptr::mut_offset(mp, i) = '-' as u8;
        }

        vec::unsafe::form_slice(ptr::offset(p, i),
                                len - i, f)
    }
}

#[doc = "Convert to a string"]
fn str(i: T) -> str { ret to_str(i, 10u); }

#[test]
fn test_to_str() {
    assert to_str(0 as T, 10u) == "0";
    assert to_str(1 as T, 10u) == "1";
    assert to_str(2 as T, 10u) == "2";
    assert to_str(11 as T, 10u) == "11";
    assert to_str(11 as T, 16u) == "b";
    assert to_str(255 as T, 16u) == "ff";
    assert to_str(0xff as T, 10u) == "255";
}

#[test]
#[ignore]
fn test_from_str() {
    assert from_str("0") == some(0u as T);
    assert from_str("3") == some(3u as T);
    assert from_str("10") == some(10u as T);
    assert from_str("123456789") == some(123456789u as T);
    assert from_str("00100") == some(100u as T);

    assert from_str("") == none;
    assert from_str(" ") == none;
    assert from_str("x") == none;
}

#[test]
#[ignore]
fn test_parse_buf() {
    import str::bytes;
    assert parse_buf(bytes("123"), 10u) == some(123u as T);
    assert parse_buf(bytes("1001"), 2u) == some(9u as T);
    assert parse_buf(bytes("123"), 8u) == some(83u as T);
    assert parse_buf(bytes("123"), 16u) == some(291u as T);
    assert parse_buf(bytes("ffff"), 16u) == some(65535u as T);
    assert parse_buf(bytes("z"), 36u) == some(35u as T);

    assert parse_buf(str::bytes("Z"), 10u) == none;
    assert parse_buf(str::bytes("_"), 2u) == none;
}

#[test]
#[should_fail]
#[ignore(cfg(windows))]
fn to_str_radix1() {
    uint::to_str(100u, 1u);
}

#[test]
#[should_fail]
#[ignore(cfg(windows))]
fn to_str_radix17() {
    uint::to_str(100u, 17u);
}
<commit_msg>core: Inline unsigned range function<commit_after>import T = inst::T;
import cmp::{eq, ord};
import num::num;

export min_value, max_value;
export min, max;
export add, sub, mul, div, rem;
export lt, le, eq, ne, ge, gt;
export is_positive, is_negative;
export is_nonpositive, is_nonnegative;
export range;
export compl;
export to_str, to_str_bytes;
export from_str, from_str_radix, str, parse_buf;
export ord, eq, num;

const min_value: T = 0 as T;
const max_value: T = 0 as T - 1 as T;

pure fn min(x: T, y: T) -> T { if x < y { x } else { y } }
pure fn max(x: T, y: T) -> T { if x > y { x } else { y } }

pure fn add(x: T, y: T) -> T { x + y }
pure fn sub(x: T, y: T) -> T { x - y }
pure fn mul(x: T, y: T) -> T { x * y }
pure fn div(x: T, y: T) -> T { x / y }
pure fn rem(x: T, y: T) -> T { x % y }

pure fn lt(x: T, y: T) -> bool { x < y }
pure fn le(x: T, y: T) -> bool { x <= y }
pure fn eq(x: T, y: T) -> bool { x == y }
pure fn ne(x: T, y: T) -> bool { x != y }
pure fn ge(x: T, y: T) -> bool { x >= y }
pure fn gt(x: T, y: T) -> bool { x > y }

pure fn is_positive(x: T) -> bool { x > 0 as T }
pure fn is_negative(x: T) -> bool { x < 0 as T }
pure fn is_nonpositive(x: T) -> bool { x <= 0 as T }
pure fn is_nonnegative(x: T) -> bool { x >= 0 as T }

#[inline(always)]
#[doc = "Iterate over the range [`lo`..`hi`)"]
fn range(lo: T, hi: T, it: fn(T) -> bool) {
    let mut i = lo;
    while i < hi {
        if !it(i) { break }
        i += 1 as T;
    }
}

#[doc = "Computes the bitwise complement"]
pure fn compl(i: T) -> T {
    max_value ^ i
}

impl ord of ord for T {
    fn lt(&&other: T) -> bool {
        ret self < other;
    }
}

impl eq of eq for T {
    fn eq(&&other: T) -> bool {
        ret self == other;
    }
}

impl num of num for T {
    fn add(&&other: T)    -> T { ret self + other; }
    fn sub(&&other: T)    -> T { ret self - other; }
    fn mul(&&other: T)    -> T { ret self * other; }
    fn div(&&other: T)    -> T { ret self / other; }
    fn modulo(&&other: T) -> T { ret self % other; }
    fn neg()              -> T { ret -self;        }

    fn to_int()         -> int { ret self as int; }
    fn from_int(n: int) -> T   { ret n as T;      }
}

#[doc = "
Parse a buffer of bytes

# Arguments

* buf - A byte buffer
* radix - The base of the number

# Failure

`buf` must not be empty
"]
fn parse_buf(buf: [u8], radix: uint) -> option<T> {
    if vec::len(buf) == 0u { ret none; }
    let mut i = vec::len(buf) - 1u;
    let mut power = 1u as T;
    let mut n = 0u as T;
    loop {
        alt char::to_digit(buf[i] as char, radix) {
          some(d) { n += d as T * power; }
          none { ret none; }
        }
        power *= radix as T;
        if i == 0u { ret some(n); }
        i -= 1u;
    };
}

#[doc = "Parse a string to an int"]
fn from_str(s: str) -> option<T> { parse_buf(str::bytes(s), 10u) }

#[doc = "Parse a string as an unsigned integer."]
fn from_str_radix(buf: str, radix: u64) -> option<u64> {
    if str::len(buf) == 0u { ret none; }
    let mut i = str::len(buf) - 1u;
    let mut power = 1u64, n = 0u64;
    loop {
        alt char::to_digit(buf[i] as char, radix as uint) {
          some(d) { n += d as u64 * power; }
          none { ret none; }
        }
        power *= radix;
        if i == 0u { ret some(n); }
        i -= 1u;
    };
}

#[doc = "
Convert to a string in a given base

# Failure

Fails if `radix` < 2 or `radix` > 16
"]
fn to_str(num: T, radix: uint) -> str unsafe {
    to_str_bytes(false, num, radix) {|slice|
        vec::unpack_slice(slice) {|p, len|
            str::unsafe::from_buf_len(p, len)
        }
    }
}

#[doc = "Low-level helper routine for string conversion."]
fn to_str_bytes<U>(neg: bool, num: T, radix: uint,
                   f: fn([u8]/&) -> U) -> U unsafe {

    #[inline(always)]
    fn digit(n: T) -> u8 {
        if n <= 9u as T {
            n as u8 + '0' as u8
        } else if n <= 15u as T {
            (n - 10 as T) as u8 + 'a' as u8
        } else {
            fail;
        }
    }

    assert (1u < radix && radix <= 16u);

    // Enough room to hold any number in any radix.
    // Worst case: 64-bit number, binary-radix, with
    // a leading negative sign = 65 bytes.
    let buf : [mut u8]/65 =
        [mut
         0u8,0u8,0u8,0u8,0u8, 0u8,0u8,0u8,0u8,0u8,
         0u8,0u8,0u8,0u8,0u8, 0u8,0u8,0u8,0u8,0u8,

         0u8,0u8,0u8,0u8,0u8, 0u8,0u8,0u8,0u8,0u8,
         0u8,0u8,0u8,0u8,0u8, 0u8,0u8,0u8,0u8,0u8,

         0u8,0u8,0u8,0u8,0u8, 0u8,0u8,0u8,0u8,0u8,
         0u8,0u8,0u8,0u8,0u8, 0u8,0u8,0u8,0u8,0u8,

         0u8,0u8,0u8,0u8,0u8
         ]/65;

    // FIXME: post-snapshot, you can do this without
    // the raw pointers and unsafe bits, and the
    // codegen will prove it's all in-bounds, no
    // extra cost.

    vec::unpack_slice(buf) {|p, len|
        let mp = p as *mut u8;
        let mut i = len;
        let mut n = num;
        let radix = radix as T;
        loop {
            i -= 1u;
            assert 0u < i && i < len;
            *ptr::mut_offset(mp, i) = digit(n % radix);
            n /= radix;
            if n == 0 as T { break; }
        }

        assert 0u < i && i < len;

        if neg {
            i -= 1u;
            *ptr::mut_offset(mp, i) = '-' as u8;
        }

        vec::unsafe::form_slice(ptr::offset(p, i),
                                len - i, f)
    }
}

#[doc = "Convert to a string"]
fn str(i: T) -> str { ret to_str(i, 10u); }

#[test]
fn test_to_str() {
    assert to_str(0 as T, 10u) == "0";
    assert to_str(1 as T, 10u) == "1";
    assert to_str(2 as T, 10u) == "2";
    assert to_str(11 as T, 10u) == "11";
    assert to_str(11 as T, 16u) == "b";
    assert to_str(255 as T, 16u) == "ff";
    assert to_str(0xff as T, 10u) == "255";
}

#[test]
#[ignore]
fn test_from_str() {
    assert from_str("0") == some(0u as T);
    assert from_str("3") == some(3u as T);
    assert from_str("10") == some(10u as T);
    assert from_str("123456789") == some(123456789u as T);
    assert from_str("00100") == some(100u as T);

    assert from_str("") == none;
    assert from_str(" ") == none;
    assert from_str("x") == none;
}

#[test]
#[ignore]
fn test_parse_buf() {
    import str::bytes;
    assert parse_buf(bytes("123"), 10u) == some(123u as T);
    assert parse_buf(bytes("1001"), 2u) == some(9u as T);
    assert parse_buf(bytes("123"), 8u) == some(83u as T);
    assert parse_buf(bytes("123"), 16u) == some(291u as T);
    assert parse_buf(bytes("ffff"), 16u) == some(65535u as T);
    assert parse_buf(bytes("z"), 36u) == some(35u as T);

    assert parse_buf(str::bytes("Z"), 10u) == none;
    assert parse_buf(str::bytes("_"), 2u) == none;
}

#[test]
#[should_fail]
#[ignore(cfg(windows))]
fn to_str_radix1() {
    uint::to_str(100u, 1u);
}

#[test]
#[should_fail]
#[ignore(cfg(windows))]
fn to_str_radix17() {
    uint::to_str(100u, 17u);
}
<|endoftext|>


<commit_before>pub mod aes;
pub mod gcm;
pub mod hash256;
pub mod hash384;
pub mod hash512;
pub mod rand;
pub mod sha3;
pub mod nhs;

macro_rules! rom_mod {
    ($path: expr) => {
        #[path = $path]
        mod rom;
    };
}

macro_rules! arch {
    () => {
        #[cfg(target_pointer_width = "32")]
        #[path = "arch/arch32.rs"]
        mod arch;
        #[cfg(target_pointer_width = "64")]
        #[path = "arch/arch64.rs"]
        mod arch;
    };
}

macro_rules! curve {
    () => {};
}

macro_rules! rsa {
    ($name: tt, $feature: expr, $path32: expr, $path64: expr) => {
        #[cfg(feature = $feature)]
        #[path = "./"]
        pub mod $name {
            arch!();
            #[cfg(target_pointer_width = "32")]
            rom_mod!($path32);
            #[cfg(target_pointer_width = "64")]
            rom_mod!($path64);
            pub mod big;
            pub mod dbig;
            pub mod ff;
            pub mod rsa;
        }
    };
}

rsa!(rsa2048, "rsa2048", "roms/rom_rsa2048_32.rs", "roms/rom_rsa2048_64.rs");
rsa!(rsa3072, "rsa3072", "roms/rom_rsa3072_32.rs", "roms/rom_rsa3072_64.rs");
rsa!(rsa2048, "rsa3072", "roms/rom_rsa4096_32.rs", "roms/rom_rsa4096_64.rs");<commit_msg>Example without macroses<commit_after>pub mod aes;
pub mod gcm;
pub mod hash256;
pub mod hash384;
pub mod hash512;
pub mod rand;
pub mod sha3;
pub mod nhs;

#[cfg(feature = "rsa2048")]
#[path = "./"]
pub mod rsa2048 {
    #[cfg(target_pointer_width = "32")]
    #[path = "arch/arch32.rs"]
    mod arch;
    #[cfg(target_pointer_width = "64")]
    #[path = "arch/arch64.rs"]
    mod arch;

    #[cfg(target_pointer_width = "32")]
    #[path = "roms/rom_rsa2048_32.rs"]
    mod rom;
    #[cfg(target_pointer_width = "64")]
    #[path = "roms/rom_rsa2048_64.rs"]
    mod rom;
    pub mod big;
    pub mod dbig;
    pub mod ff;
    pub mod rsa;
}

#[cfg(feature = "rsa3072")]
#[path = "./"]
pub mod rsa3072 {
    #[cfg(target_pointer_width = "32")]
    #[path = "arch/arch32.rs"]
    mod arch;
    #[cfg(target_pointer_width = "64")]
    #[path = "arch/arch64.rs"]
    mod arch;

    #[cfg(target_pointer_width = "32")]
    #[path = "roms/rom_rsa3072_32.rs"]
    mod rom;
    #[cfg(target_pointer_width = "64")]
    #[path = "roms/rom_rsa3072_64.rs"]
    mod rom;
    pub mod big;
    pub mod dbig;
    pub mod ff;
    pub mod rsa;
}

#[cfg(feature = "rsa4096")]
#[path = "./"]
pub mod rsa4096 {
    #[cfg(target_pointer_width = "32")]
    #[path = "arch/arch32.rs"]
    mod arch;
    #[cfg(target_pointer_width = "64")]
    #[path = "arch/arch64.rs"]
    mod arch;

    #[cfg(target_pointer_width = "32")]
    #[path = "roms/rom_rsa4096_32.rs"]
    mod rom;
    #[cfg(target_pointer_width = "64")]
    #[path = "roms/rom_rsa4096_64.rs"]
    mod rom;
    pub mod big;
    pub mod dbig;
    pub mod ff;
    pub mod rsa;
}<|endoftext|>


<commit_before><commit_msg>Use `str::starts_with` method to check bech32 address prefixes.<commit_after><|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

use std::rand;
use std::rand::Rng;
use cgmath::vector::{Vector3, Vector, EuclideanVector};
use visualizer::geom;
use core::types::{MapPos, UnitId};
use core::game_state::GameState;
use core::core;
use visualizer::mesh::{MeshId};
use visualizer::scene::{Scene, SceneNode, NodeId};
use visualizer::types::{MFloat, WorldPos, Time};

fn unit_id_to_node_id(unit_id: UnitId) -> NodeId {
    NodeId{id: unit_id.id}
}

fn marker_id(unit_id: UnitId) -> NodeId {
    NodeId{id: unit_id.id + 1000}
}

pub trait EventVisualizer {
    fn is_finished(&self) -> bool;
    fn draw(&mut self, scene: &mut Scene, dtime: Time);
    fn end(&mut self, scene: &mut Scene, state: &GameState);
}

pub struct EventMoveVisualizer {
    unit_id: UnitId,
    path: Vec<WorldPos>,
    move: MoveHelper,
    speed: MFloat,
}

impl EventVisualizer for EventMoveVisualizer {
    fn is_finished(&self) -> bool {
        self.path.len() == 1
    }

    fn draw(&mut self, scene: &mut Scene, dtime: Time) {
        let pos = self.move.step(dtime);
        {
            let marker_node = scene.nodes.get_mut(&marker_id(self.unit_id));
            marker_node.pos.v = pos.v.add_v(&vec3_z(geom::HEX_EX_RADIUS / 2.0));
        }
        let node_id = unit_id_to_node_id(self.unit_id);
        let node = scene.nodes.get_mut(&node_id);
        node.pos = pos;
        if self.move.is_finished() {
            self.path.shift();
            if self.path.len() > 1 {
                self.update_waypoint(node);
            }
            node.pos = self.current_waypoint();
        }
    }

    fn end(&mut self, scene: &mut Scene, _: &GameState) {
        assert!(self.path.len() == 1);
        let node_id = unit_id_to_node_id(self.unit_id);
        let node = scene.nodes.get_mut(&node_id);
        node.pos = self.current_waypoint();
    }
}

impl EventMoveVisualizer {
    pub fn new(
        scene: &mut Scene,
        _: &GameState,
        unit_id: UnitId,
        path: Vec<MapPos>
    ) -> Box<EventVisualizer> {
        let mut world_path = Vec::new();
        for map_pos in path.iter() {
            let world_pos = geom::map_pos_to_world_pos(*map_pos);
            world_path.push(world_pos);
        }
        let speed = 3.8; // TODO: Get from UnitType
        let node_id = unit_id_to_node_id(unit_id);
        let node = scene.nodes.get_mut(&node_id);
        node.rot = geom::get_rot_angle(
            *world_path.get(0), *world_path.get(1));
        let move = MoveHelper::new(
            *world_path.get(0), *world_path.get(1), speed);
        let mut vis = box EventMoveVisualizer {
            unit_id: unit_id,
            path: world_path,
            move: move,
            speed: speed,
        };
        vis.update_waypoint(node);
        vis as Box<EventVisualizer>
    }

    fn update_waypoint(&mut self, node: &mut SceneNode) {
        self.move = MoveHelper::new(
            self.current_waypoint(),
            self.next_waypoint(),
            self.speed,
        );
        node.rot = geom::get_rot_angle(
            self.current_waypoint(),
            self.next_waypoint()
        );
    }

    fn current_waypoint(&self) -> WorldPos {
        assert!(self.path.len() >= 1);
        *self.path.get(0)
    }

    fn next_waypoint(&self) -> WorldPos {
        assert!(self.path.len() >= 2);
        *self.path.get(1)
    }
}

pub struct EventEndTurnVisualizer;

impl EventEndTurnVisualizer {
    pub fn new() -> Box<EventVisualizer> {
        box EventEndTurnVisualizer as Box<EventVisualizer>
    }
}

impl EventVisualizer for EventEndTurnVisualizer {
    fn is_finished(&self) -> bool {
        true
    }

    fn draw(&mut self, _: &mut Scene, _: Time) {}

    fn end(&mut self, _: &mut Scene, _: &GameState) {}
}

pub struct EventCreateUnitVisualizer {
    id: UnitId,
    move: MoveHelper,
}

fn get_unit_scene_nodes(
    type_id: core::UnitTypeId,
    mesh_id: MeshId,
) -> Vec<SceneNode> {
    match type_id {
        core::Tank => vec![
            SceneNode {
                pos: WorldPos{v: Vector3{x: 0.0, y: 0.0, z: 0.0}},
                rot: 0.0,
                mesh_id: Some(mesh_id),
                children: vec![],
            },
        ],
        core::Soldier => vec![
            SceneNode {
                pos: WorldPos{v: Vector3{x: 0.2, y: 0.2, z: 0.0}},
                rot: 0.0,
                mesh_id: Some(mesh_id),
                children: vec![],
            },
            SceneNode {
                pos: WorldPos{v: Vector3{x: 0.2, y: -0.2, z: 0.0}},
                rot: 0.0,
                mesh_id: Some(mesh_id),
                children: vec![],
            },
            SceneNode {
                pos: WorldPos{v: Vector3{x: -0.2, y: 0.2, z: 0.0}},
                rot: 0.0,
                mesh_id: Some(mesh_id),
                children: vec![],
            },
            SceneNode {
                pos: WorldPos{v: Vector3{x: -0.2, y: -0.2, z: 0.0}},
                rot: 0.0,
                mesh_id: Some(mesh_id),
                children: vec![],
            },
        ],
    }
}

impl EventCreateUnitVisualizer {
    pub fn new(
        scene: &mut Scene,
        _: &GameState,
        id: UnitId,
        type_id: core::UnitTypeId,
        pos: MapPos,
        mesh_id: MeshId,
        marker_mesh_id: MeshId
    ) -> Box<EventVisualizer> {
        let node_id = unit_id_to_node_id(id);
        let world_pos = geom::map_pos_to_world_pos(pos);
        let to = world_pos;
        let from = WorldPos{v: to.v.sub_v(&vec3_z(geom::HEX_EX_RADIUS / 2.0))};
        let rot = rand::task_rng().gen_range::<MFloat>(0.0, 360.0);
        scene.nodes.insert(node_id, SceneNode {
            pos: from,
            rot: rot,
            mesh_id: None,
            children: get_unit_scene_nodes(type_id, mesh_id),
        });
        scene.nodes.insert(marker_id(id), SceneNode {
            pos: WorldPos{v: to.v.add_v(&vec3_z(geom::HEX_EX_RADIUS / 2.0))},
            rot: 0.0,
            mesh_id: Some(marker_mesh_id),
            children: Vec::new(),
        });
        let move = MoveHelper::new(from, to, 1.0);
        box EventCreateUnitVisualizer {
            id: id,
            move: move,
        } as Box<EventVisualizer>
    }
}

impl EventVisualizer for EventCreateUnitVisualizer {
    fn is_finished(&self) -> bool {
        self.move.is_finished()
    }

    fn draw(&mut self, scene: &mut Scene, dtime: Time) {
        let node_id = unit_id_to_node_id(self.id);
        let node = scene.nodes.get_mut(&node_id);
        node.pos = self.move.step(dtime);
    }

    fn end(&mut self, _: &mut Scene, _: &GameState) {}
}

pub struct MoveHelper {
    to: WorldPos,
    current: WorldPos,
    dist: MFloat,
    current_dist: MFloat,
    dir: Vector3<MFloat>,
}

impl MoveHelper {
    pub fn new(
        from: WorldPos,
        to: WorldPos,
        speed: MFloat
    ) -> MoveHelper {
        let dir = to.v.sub_v(&from.v).normalize();
        let dist = geom::dist(from, to);
        MoveHelper {
            to: to,
            current: from,
            dist: dist,
            current_dist: 0.0,
            dir: dir.mul_s(speed),
        }
    }

    pub fn is_finished(&self) -> bool {
        self.current_dist >= self.dist
    }

    pub fn step(&mut self, dtime: Time) -> WorldPos {
        let dt = dtime.n as MFloat / 1000000000.0;
        let step = self.dir.mul_s(dt);
        self.current_dist += step.length();
        self.current.v.add_self_v(&step);
        if self.is_finished() {
            self.current = self.to;
        }
        self.current
    }
}

fn vec3_z(z: MFloat) -> Vector3<MFloat> {
    Vector3{x: 0.0, y: 0.0, z: z}
}

pub struct EventAttackUnitVisualizer {
    defender_id: UnitId,
    killed: bool,
    move: MoveHelper,
    shell_move: MoveHelper,
    shell_node_id: NodeId,
}

impl EventAttackUnitVisualizer {
    pub fn new(
        scene: &mut Scene,
        _: &GameState,
        attacker_id: UnitId,
        defender_id: UnitId,
        killed: bool,
        shell_mesh_id: MeshId
    ) -> Box<EventVisualizer> {
        let node_id = unit_id_to_node_id(defender_id);
        let from = scene.nodes.get(&node_id).pos;
        let to = WorldPos{v: from.v.sub_v(&vec3_z(geom::HEX_EX_RADIUS / 2.0))};
        let move = MoveHelper::new(from, to, 1.0);
        let shell_node_id = NodeId{id: 1666}; // TODO
        let shell_move = {
            let from = scene.nodes.get(&unit_id_to_node_id(attacker_id)).pos;
            let to = scene.nodes.get(&unit_id_to_node_id(defender_id)).pos;
            scene.nodes.insert(shell_node_id, SceneNode {
                pos: from,
                rot: 0.0,
                mesh_id: Some(shell_mesh_id),
                children: Vec::new(),
            });
            MoveHelper::new(from, to, 10.0)
        };
        box EventAttackUnitVisualizer {
            defender_id: defender_id,
            killed: killed,
            move: move,
            shell_move: shell_move,
            shell_node_id: shell_node_id,
        } as Box<EventVisualizer>
    }
}

impl EventVisualizer for EventAttackUnitVisualizer {
    fn is_finished(&self) -> bool {
        // TODO: Simplify
        if self.killed {
            self.move.is_finished() && self.shell_move.is_finished()
        } else {
            self.shell_move.is_finished()
        }
    }

    fn draw(&mut self, scene: &mut Scene, dtime: Time) {
        scene.nodes.get_mut(&self.shell_node_id).pos = self.shell_move.step(dtime);
        if self.killed {
            if self.shell_move.is_finished() {
                let node_id = unit_id_to_node_id(self.defender_id);
                scene.nodes.get_mut(&node_id).pos = self.move.step(dtime);
            }
        }
    }

    fn end(&mut self, scene: &mut Scene, _: &GameState) {
        if self.killed {
            let node_id = unit_id_to_node_id(self.defender_id);
            scene.nodes.remove(&node_id);
            scene.nodes.remove(&marker_id(self.defender_id));
        }
        scene.nodes.remove(&self.shell_node_id);
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>EventVisualizer: Simplified is_finished()<commit_after>// See LICENSE file for copyright and license details.

use std::rand;
use std::rand::Rng;
use cgmath::vector::{Vector3, Vector, EuclideanVector};
use visualizer::geom;
use core::types::{MapPos, UnitId};
use core::game_state::GameState;
use core::core;
use visualizer::mesh::{MeshId};
use visualizer::scene::{Scene, SceneNode, NodeId};
use visualizer::types::{MFloat, WorldPos, Time};

fn unit_id_to_node_id(unit_id: UnitId) -> NodeId {
    NodeId{id: unit_id.id}
}

fn marker_id(unit_id: UnitId) -> NodeId {
    NodeId{id: unit_id.id + 1000}
}

pub trait EventVisualizer {
    fn is_finished(&self) -> bool;
    fn draw(&mut self, scene: &mut Scene, dtime: Time);
    fn end(&mut self, scene: &mut Scene, state: &GameState);
}

pub struct EventMoveVisualizer {
    unit_id: UnitId,
    path: Vec<WorldPos>,
    move: MoveHelper,
    speed: MFloat,
}

impl EventVisualizer for EventMoveVisualizer {
    fn is_finished(&self) -> bool {
        self.path.len() == 1
    }

    fn draw(&mut self, scene: &mut Scene, dtime: Time) {
        let pos = self.move.step(dtime);
        {
            let marker_node = scene.nodes.get_mut(&marker_id(self.unit_id));
            marker_node.pos.v = pos.v.add_v(&vec3_z(geom::HEX_EX_RADIUS / 2.0));
        }
        let node_id = unit_id_to_node_id(self.unit_id);
        let node = scene.nodes.get_mut(&node_id);
        node.pos = pos;
        if self.move.is_finished() {
            self.path.shift();
            if self.path.len() > 1 {
                self.update_waypoint(node);
            }
            node.pos = self.current_waypoint();
        }
    }

    fn end(&mut self, scene: &mut Scene, _: &GameState) {
        assert!(self.path.len() == 1);
        let node_id = unit_id_to_node_id(self.unit_id);
        let node = scene.nodes.get_mut(&node_id);
        node.pos = self.current_waypoint();
    }
}

impl EventMoveVisualizer {
    pub fn new(
        scene: &mut Scene,
        _: &GameState,
        unit_id: UnitId,
        path: Vec<MapPos>
    ) -> Box<EventVisualizer> {
        let mut world_path = Vec::new();
        for map_pos in path.iter() {
            let world_pos = geom::map_pos_to_world_pos(*map_pos);
            world_path.push(world_pos);
        }
        let speed = 3.8; // TODO: Get from UnitType
        let node_id = unit_id_to_node_id(unit_id);
        let node = scene.nodes.get_mut(&node_id);
        node.rot = geom::get_rot_angle(
            *world_path.get(0), *world_path.get(1));
        let move = MoveHelper::new(
            *world_path.get(0), *world_path.get(1), speed);
        let mut vis = box EventMoveVisualizer {
            unit_id: unit_id,
            path: world_path,
            move: move,
            speed: speed,
        };
        vis.update_waypoint(node);
        vis as Box<EventVisualizer>
    }

    fn update_waypoint(&mut self, node: &mut SceneNode) {
        self.move = MoveHelper::new(
            self.current_waypoint(),
            self.next_waypoint(),
            self.speed,
        );
        node.rot = geom::get_rot_angle(
            self.current_waypoint(),
            self.next_waypoint()
        );
    }

    fn current_waypoint(&self) -> WorldPos {
        assert!(self.path.len() >= 1);
        *self.path.get(0)
    }

    fn next_waypoint(&self) -> WorldPos {
        assert!(self.path.len() >= 2);
        *self.path.get(1)
    }
}

pub struct EventEndTurnVisualizer;

impl EventEndTurnVisualizer {
    pub fn new() -> Box<EventVisualizer> {
        box EventEndTurnVisualizer as Box<EventVisualizer>
    }
}

impl EventVisualizer for EventEndTurnVisualizer {
    fn is_finished(&self) -> bool {
        true
    }

    fn draw(&mut self, _: &mut Scene, _: Time) {}

    fn end(&mut self, _: &mut Scene, _: &GameState) {}
}

pub struct EventCreateUnitVisualizer {
    id: UnitId,
    move: MoveHelper,
}

fn get_unit_scene_nodes(
    type_id: core::UnitTypeId,
    mesh_id: MeshId,
) -> Vec<SceneNode> {
    match type_id {
        core::Tank => vec![
            SceneNode {
                pos: WorldPos{v: Vector3{x: 0.0, y: 0.0, z: 0.0}},
                rot: 0.0,
                mesh_id: Some(mesh_id),
                children: vec![],
            },
        ],
        core::Soldier => vec![
            SceneNode {
                pos: WorldPos{v: Vector3{x: 0.2, y: 0.2, z: 0.0}},
                rot: 0.0,
                mesh_id: Some(mesh_id),
                children: vec![],
            },
            SceneNode {
                pos: WorldPos{v: Vector3{x: 0.2, y: -0.2, z: 0.0}},
                rot: 0.0,
                mesh_id: Some(mesh_id),
                children: vec![],
            },
            SceneNode {
                pos: WorldPos{v: Vector3{x: -0.2, y: 0.2, z: 0.0}},
                rot: 0.0,
                mesh_id: Some(mesh_id),
                children: vec![],
            },
            SceneNode {
                pos: WorldPos{v: Vector3{x: -0.2, y: -0.2, z: 0.0}},
                rot: 0.0,
                mesh_id: Some(mesh_id),
                children: vec![],
            },
        ],
    }
}

impl EventCreateUnitVisualizer {
    pub fn new(
        scene: &mut Scene,
        _: &GameState,
        id: UnitId,
        type_id: core::UnitTypeId,
        pos: MapPos,
        mesh_id: MeshId,
        marker_mesh_id: MeshId
    ) -> Box<EventVisualizer> {
        let node_id = unit_id_to_node_id(id);
        let world_pos = geom::map_pos_to_world_pos(pos);
        let to = world_pos;
        let from = WorldPos{v: to.v.sub_v(&vec3_z(geom::HEX_EX_RADIUS / 2.0))};
        let rot = rand::task_rng().gen_range::<MFloat>(0.0, 360.0);
        scene.nodes.insert(node_id, SceneNode {
            pos: from,
            rot: rot,
            mesh_id: None,
            children: get_unit_scene_nodes(type_id, mesh_id),
        });
        scene.nodes.insert(marker_id(id), SceneNode {
            pos: WorldPos{v: to.v.add_v(&vec3_z(geom::HEX_EX_RADIUS / 2.0))},
            rot: 0.0,
            mesh_id: Some(marker_mesh_id),
            children: Vec::new(),
        });
        let move = MoveHelper::new(from, to, 1.0);
        box EventCreateUnitVisualizer {
            id: id,
            move: move,
        } as Box<EventVisualizer>
    }
}

impl EventVisualizer for EventCreateUnitVisualizer {
    fn is_finished(&self) -> bool {
        self.move.is_finished()
    }

    fn draw(&mut self, scene: &mut Scene, dtime: Time) {
        let node_id = unit_id_to_node_id(self.id);
        let node = scene.nodes.get_mut(&node_id);
        node.pos = self.move.step(dtime);
    }

    fn end(&mut self, _: &mut Scene, _: &GameState) {}
}

pub struct MoveHelper {
    to: WorldPos,
    current: WorldPos,
    dist: MFloat,
    current_dist: MFloat,
    dir: Vector3<MFloat>,
}

impl MoveHelper {
    pub fn new(
        from: WorldPos,
        to: WorldPos,
        speed: MFloat
    ) -> MoveHelper {
        let dir = to.v.sub_v(&from.v).normalize();
        let dist = geom::dist(from, to);
        MoveHelper {
            to: to,
            current: from,
            dist: dist,
            current_dist: 0.0,
            dir: dir.mul_s(speed),
        }
    }

    pub fn is_finished(&self) -> bool {
        self.current_dist >= self.dist
    }

    pub fn step(&mut self, dtime: Time) -> WorldPos {
        let dt = dtime.n as MFloat / 1000000000.0;
        let step = self.dir.mul_s(dt);
        self.current_dist += step.length();
        self.current.v.add_self_v(&step);
        if self.is_finished() {
            self.current = self.to;
        }
        self.current
    }
}

fn vec3_z(z: MFloat) -> Vector3<MFloat> {
    Vector3{x: 0.0, y: 0.0, z: z}
}

pub struct EventAttackUnitVisualizer {
    defender_id: UnitId,
    killed: bool,
    move: MoveHelper,
    shell_move: MoveHelper,
    shell_node_id: NodeId,
}

impl EventAttackUnitVisualizer {
    pub fn new(
        scene: &mut Scene,
        _: &GameState,
        attacker_id: UnitId,
        defender_id: UnitId,
        killed: bool,
        shell_mesh_id: MeshId
    ) -> Box<EventVisualizer> {
        let node_id = unit_id_to_node_id(defender_id);
        let from = scene.nodes.get(&node_id).pos;
        let to = WorldPos{v: from.v.sub_v(&vec3_z(geom::HEX_EX_RADIUS / 2.0))};
        let move = MoveHelper::new(from, to, 1.0);
        let shell_node_id = NodeId{id: 1666}; // TODO
        let shell_move = {
            let from = scene.nodes.get(&unit_id_to_node_id(attacker_id)).pos;
            let to = scene.nodes.get(&unit_id_to_node_id(defender_id)).pos;
            scene.nodes.insert(shell_node_id, SceneNode {
                pos: from,
                rot: 0.0,
                mesh_id: Some(shell_mesh_id),
                children: Vec::new(),
            });
            MoveHelper::new(from, to, 10.0)
        };
        box EventAttackUnitVisualizer {
            defender_id: defender_id,
            killed: killed,
            move: move,
            shell_move: shell_move,
            shell_node_id: shell_node_id,
        } as Box<EventVisualizer>
    }
}

impl EventVisualizer for EventAttackUnitVisualizer {
    fn is_finished(&self) -> bool {
        if self.killed {
            self.move.is_finished()
        } else {
            self.shell_move.is_finished()
        }
    }

    fn draw(&mut self, scene: &mut Scene, dtime: Time) {
        scene.nodes.get_mut(&self.shell_node_id).pos = self.shell_move.step(dtime);
        if self.killed {
            if self.shell_move.is_finished() {
                let node_id = unit_id_to_node_id(self.defender_id);
                scene.nodes.get_mut(&node_id).pos = self.move.step(dtime);
            }
        }
    }

    fn end(&mut self, scene: &mut Scene, _: &GameState) {
        if self.killed {
            let node_id = unit_id_to_node_id(self.defender_id);
            scene.nodes.remove(&node_id);
            scene.nodes.remove(&marker_id(self.defender_id));
        }
        scene.nodes.remove(&self.shell_node_id);
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>


<commit_before>use consts::CRYPTO_CONTROL_BYTES;
use util::slice_u16;

/// Buffer of bytes that represent a crypto control packet.
pub type Buf = [u8; CRYPTO_CONTROL_BYTES];

pub struct CryptoControlFields(Buf);

impl CryptoControlFields {
    pub fn new(buf: Buf) -> Self { CryptoControlFields(buf) }

    pub fn crypto_init(&self) -> &[u8] { &self.0[..9] }

    pub fn crypto_alg(&self) -> CryptoAlgorithm {
        CryptoAlgorithm::from_bits(self.0[9])
    }

    pub fn crypto_key(&self) -> u16 { slice_u16(&self.0[10..]) }
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum CryptoAlgorithm {
    Accordion,
    BatonEven,
    Firefly,
    Mayfly,
    Saville,
    BatonOdd,
    Unencrypted,
    DES,
    TripleDES,
    AES,
    Other(u8),
}

impl CryptoAlgorithm {
    pub fn from_bits(bits: u8) -> CryptoAlgorithm {
        use self::CryptoAlgorithm::*;

        match bits {
            0x00 => Accordion,
            0x01 => BatonEven,
            0x02 => Firefly,
            0x03 => Mayfly,
            0x04 => Saville,
            0x41 => BatonOdd,
            0x80 => Unencrypted,
            0x81 => DES,
            0x83 => TripleDES,
            0x84 => AES,
            b => Other(b),
        }
    }
}

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

    #[test]
    fn test_cypto() {
        let c = CryptoControlFields::new([
            0, 0, 0, 1, 0, 0, 0, 2, 0,
            0b10000100,
            0xDE, 0xAD,
        ]);

        assert_eq!(c.crypto_init(), &[0,0,0,1,0,0,0,2,0]);
        assert_eq!(c.crypto_alg(), AES);
        assert_eq!(c.crypto_key(), 0xDEAD);
    }
}
<commit_msg>Remove crypto_ prefix<commit_after>use consts::CRYPTO_CONTROL_BYTES;
use util::slice_u16;

/// Buffer of bytes that represent a crypto control packet.
pub type Buf = [u8; CRYPTO_CONTROL_BYTES];

pub struct CryptoControlFields(Buf);

impl CryptoControlFields {
    pub fn new(buf: Buf) -> Self { CryptoControlFields(buf) }

    pub fn init(&self) -> &[u8] { &self.0[..9] }

    pub fn alg(&self) -> CryptoAlgorithm { CryptoAlgorithm::from_bits(self.0[9]) }

    pub fn key(&self) -> u16 { slice_u16(&self.0[10..]) }
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum CryptoAlgorithm {
    Accordion,
    BatonEven,
    Firefly,
    Mayfly,
    Saville,
    BatonOdd,
    Unencrypted,
    DES,
    TripleDES,
    AES,
    Other(u8),
}

impl CryptoAlgorithm {
    pub fn from_bits(bits: u8) -> CryptoAlgorithm {
        use self::CryptoAlgorithm::*;

        match bits {
            0x00 => Accordion,
            0x01 => BatonEven,
            0x02 => Firefly,
            0x03 => Mayfly,
            0x04 => Saville,
            0x41 => BatonOdd,
            0x80 => Unencrypted,
            0x81 => DES,
            0x83 => TripleDES,
            0x84 => AES,
            b => Other(b),
        }
    }
}

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

    #[test]
    fn test_cypto() {
        let c = CryptoControlFields::new([
            0, 0, 0, 1, 0, 0, 0, 2, 0,
            0b10000100,
            0xDE, 0xAD,
        ]);

        assert_eq!(c.init(), &[0,0,0,1,0,0,0,2,0]);
        assert_eq!(c.alg(), AES);
        assert_eq!(c.key(), 0xDEAD);
    }
}
<|endoftext|>


<commit_before>/// L4Re specifics
/// This module contains definitions required by various L4Re libc backends.
/// Some of them are formally not part of the libc, but are a dependency of the
/// libc and hence we should provide them here.

pub type l4_umword_t = ::c_ulong; // Unsigned machine word.
pub type pthread_t = *mut ::c_void;

s! {
    /// CPU sets.
    pub struct l4_sched_cpu_set_t {
        // from the L4Re docs
        /// Combination of granularity and offset.
        ///
        /// The granularity defines how many CPUs each bit in map describes.
        /// The offset is the numer of the first CPU described by the first
        /// bit in the bitmap.
        /// offset must be a multiple of 2^graularity.
        ///
        /// | MSB              |                 LSB |
        /// | ---------------- | ------------------- |
        /// | 8bit granularity | 24bit offset ..     |
        gran_offset: l4_umword_t ,
        /// Bitmap of CPUs.
        map: l4_umword_t ,
    }
}

#[cfg(target_os = "l4re")]
#[allow(missing_debug_implementations)]
pub struct pthread_attr_t {
    pub __detachstate: ::c_int,
    pub __schedpolicy: ::c_int,
    pub __schedparam: super::__sched_param,
    pub __inheritsched: ::c_int,
    pub __scope: ::c_int,
    pub __guardsize: ::size_t,
    pub __stackaddr_set: ::c_int,
    pub __stackaddr: *mut ::c_void, // better don't use it
    pub __stacksize: ::size_t,
    // L4Re specifics
    pub affinity: l4_sched_cpu_set_t,
    pub create_flags: ::c_uint,
}

// L4Re requires a min stack size of 64k; that isn't defined in uClibc, but
// somewhere in the core libraries. uClibc wants 16k, but that's not enough.
pub const PTHREAD_STACK_MIN: usize = 65536;
<commit_msg>l4re: fix build by adding required constants<commit_after>/// L4Re specifics
/// This module contains definitions required by various L4Re libc backends.
/// Some of them are formally not part of the libc, but are a dependency of the
/// libc and hence we should provide them here.

pub type l4_umword_t = ::c_ulong; // Unsigned machine word.
pub type pthread_t = *mut ::c_void;

s! {
    /// CPU sets.
    pub struct l4_sched_cpu_set_t {
        // from the L4Re docs
        /// Combination of granularity and offset.
        ///
        /// The granularity defines how many CPUs each bit in map describes.
        /// The offset is the numer of the first CPU described by the first
        /// bit in the bitmap.
        /// offset must be a multiple of 2^graularity.
        ///
        /// | MSB              |                 LSB |
        /// | ---------------- | ------------------- |
        /// | 8bit granularity | 24bit offset ..     |
        gran_offset: l4_umword_t ,
        /// Bitmap of CPUs.
        map: l4_umword_t ,
    }
}

#[cfg(target_os = "l4re")]
#[allow(missing_debug_implementations)]
pub struct pthread_attr_t {
    pub __detachstate: ::c_int,
    pub __schedpolicy: ::c_int,
    pub __schedparam: super::__sched_param,
    pub __inheritsched: ::c_int,
    pub __scope: ::c_int,
    pub __guardsize: ::size_t,
    pub __stackaddr_set: ::c_int,
    pub __stackaddr: *mut ::c_void, // better don't use it
    pub __stacksize: ::size_t,
    // L4Re specifics
    pub affinity: l4_sched_cpu_set_t,
    pub create_flags: ::c_uint,
}

// L4Re requires a min stack size of 64k; that isn't defined in uClibc, but
// somewhere in the core libraries. uClibc wants 16k, but that's not enough.
pub const PTHREAD_STACK_MIN: usize = 65536;

// Misc other constants required for building.
pub const SIGIO: ::c_int = 29;
pub const B19200: ::speed_t = 0o000016;
pub const B38400: ::speed_t = 0o000017;
<|endoftext|>


<commit_before>extern crate sdl2;

use sdl2::render::{Renderer, Texture};
use sdl2_image::LoadTexture;
use std::path::Path;
use std::collections::HashMap;

struct ResourceManager<'a> {
    texture_cache: HashMap<&'a str, Texture>,
    renderer: Renderer<'a>,
}

impl<'a> ResourceManager<'a> {
    // pub fn new() -> Self {}
    pub fn getTexture(&mut self, path: &'a str) -> Result<&Texture, String> {
        if !self.texture_cache.contains_key(path) {
            let image_path = Path::new(path);
            let texture = try!(self.renderer.load_texture(image_path));
            self.texture_cache.insert(path, texture);
        }
        self.texture_cache.get(path).ok_or("Texture Cache Error: No such path".into())
    }
}
<commit_msg>added tests for resource manager<commit_after>extern crate sdl2;

use sdl2::render::{Renderer, Texture};
use sdl2_image::LoadTexture;
use std::path::Path;
use std::collections::HashMap;

trait ImageLoader {
    type Image;
    fn load_from_path(&self, path: &Path) -> Result<Self::Image, String>;
}

impl<'a> ImageLoader for Renderer<'a> {
    type Image = Texture;
    fn load_from_path(&self, path: &Path) -> Result<Texture, String> {
        self.load_texture(path)
    }
}

struct ResourceManager<'a, I: ImageLoader> {
    texture_cache: HashMap<&'a str, I::Image>,
    image_loader: I,
}

impl<'a, I: ImageLoader> ResourceManager<'a, I> {
    pub fn new(image_loader: I) -> Self {
        ResourceManager {
            texture_cache: HashMap::new(),
            image_loader: image_loader,
        }
    }
    pub fn getTexture(&mut self, path: &'a str) -> Result<&I::Image, String> {
        if !self.texture_cache.contains_key(path) {
            let image_path = Path::new(path);
            let texture = try!(self.image_loader.load_from_path(image_path));
            self.texture_cache.insert(path, texture);
        }
        self.texture_cache.get(path).ok_or("Texture Cache Error: No such path".into())
    }
}

#[cfg(test)]
mod test {
    use std::path::Path;
    use sdl2::render::Texture;
    use std::cell::{RefCell, Ref};
    use super::ImageLoader;
    use super::ResourceManager;

    struct MockImage {
        pub path: String,
        pub id: u16,
    }

    struct MockImageLoader {
        pub load_count: RefCell<u16>,
        pub error: Option<String>,
    }

    impl ImageLoader for MockImageLoader {
        type Image = MockImage;

        fn load_from_path(&self, path: &Path) -> Result<MockImage, String> {
            *self.load_count.borrow_mut() += 1;
            match self.error {
                None => {
                    Ok(MockImage {
                        path: path.to_str().unwrap_or("").into(),
                        id: *self.load_count.borrow(),
                    })
                }
                Some(ref e) => Err(e.clone()),
            }
        }
    }

    #[test]
    fn loads_image() {
        let imageLoader = MockImageLoader {
            load_count: RefCell::new(0),
            error: None,
        };
        let mut subject = ResourceManager::new(imageLoader);
        let image = subject.getTexture("mypath/").unwrap();
        assert_eq!(image.path, String::from("mypath/"));
        assert_eq!(image.id, 1);
    }

    #[test]
    fn returns_error() {
        let imageLoader = MockImageLoader {
            load_count: RefCell::new(0),
            error: Some("FAIL".into()),
        };
        let mut subject = ResourceManager::new(imageLoader);
        let image = subject.getTexture("mypath/");
        assert_eq!(image.err(), Some("FAIL".into()));
    }

    #[test]
    fn caches_images() {
        let imageLoader = MockImageLoader {
            load_count: RefCell::new(0),
            error: None,
        };

        let mut subject = ResourceManager::new(imageLoader);

        {
            let image = subject.getTexture("mypath/1").unwrap();
            assert_eq!(image.path, String::from("mypath/1"));
            assert_eq!(image.id, 1);
        }

        // no error because image is already cached
        {
            let image = subject.getTexture("mypath/1").unwrap();
            assert_eq!(image.path, String::from("mypath/1"));
            assert_eq!(image.id, 1);
        }

        // no error because image is already cached
        let image = subject.getTexture("mypath/2").unwrap();
        assert_eq!(image.path, String::from("mypath/2"));
        assert_eq!(image.id, 2);
    }
}
<|endoftext|>