<commit_before>use std::collections::HashMap;
use std::rc::Rc;

use rustc_serialize::{Decodable, Decoder};

use animation::AnimationClip;
use transform::Transform;
use blend_tree::{BlendTreeNode, BlendTreeNodeDef, ClipId};
use math::*;
use skeleton::Skeleton;

const MAX_JOINTS: usize = 64;

/// A state that an AnimationController can be in, consisting
/// of a blend tree and a collection of transitions to other states
pub struct AnimationState<T: Transform> {

    /// The blend tree used to determine the final blended pose
    /// for this state
    pub blend_tree: BlendTreeNode<T>,

    /// Transitions from this state to other AnimationStates
    pub transitions: Vec<AnimationTransition>,
}

/// Representation of a state transition to a target state, with a condition and a duration
#[derive(Debug, Clone, RustcDecodable)]
pub struct AnimationTransition {
    /// The name of the target state to transition to
    pub target_state: String,

    /// The condition that will be checked in order to determine
    /// if the controller should transition to the target state
    pub condition: TransitionCondition,

    /// The duration of the transition, during which a linear blend
    /// transition between the current and target states should occur
    pub duration: f32,
}

/// Representation of a condition to check for an AnimationTransition
#[derive(Debug, Clone, RustcDecodable)]
pub struct TransitionCondition {

    /// The name of the controller parameter to compare with
    pub parameter: String,

    /// The comparision operator to use
    pub operator: Operator,

    /// The constant value to compare with the controller parameter value
    pub value: f32,
}

impl TransitionCondition {
    /// Returns true if the condition is satisfied
    pub fn is_true(&self, parameters: &HashMap<String, f32>) -> bool {
        match self.operator {
            Operator::LessThan => parameters[&self.parameter[..]] < self.value,
            Operator::GreaterThan => parameters[&self.parameter[..]] > self.value,
            Operator::LessThanEqual => parameters[&self.parameter[..]] <= self.value,
            Operator::GreaterThanEqual => parameters[&self.parameter[..]] >= self.value,
            Operator::Equal => parameters[&self.parameter[..]] == self.value,
            Operator::NotEqual => parameters[&self.parameter[..]] != self.value,
        }
    }
}

#[derive(Debug, Clone)]
pub enum Operator {
    LessThan,
    LessThanEqual,
    GreaterThan,
    GreaterThanEqual,
    Equal,
    NotEqual,
}

impl Decodable for Operator {
    fn decode<D: Decoder>(decoder: &mut D) -> Result<Operator, D::Error> {
        match &try!(decoder.read_str())[..] {
            "<" => Ok(Operator::LessThan),
            ">" => Ok(Operator::GreaterThan),
            "<=" => Ok(Operator::LessThanEqual),
            ">=" => Ok(Operator::GreaterThanEqual),
            "=" => Ok(Operator::Equal),
            "!=" => Ok(Operator::NotEqual),
            _ => Ok(Operator::Equal), // FIXME -- figure out how to throw a D::Error...
        }
    }
}

/// Definition struct for an AnimationController, which can be deserialized from JSON
/// and converted to an AnimationController instance at runtime
#[derive(Clone, Debug, RustcDecodable)]
pub struct AnimationControllerDef {

    /// Identifying name for the controller definition
    pub name: String,

    /// Declaration list of all parameters that are used by the AnimationController,
    /// including state transition conditions and blend tree parameters
    pub parameters: Vec<String>,

    /// List of animation state definitions
    pub states: Vec<AnimationStateDef>,

    /// The name of the state that the AnimationController should start in
    pub initial_state: String,
}

/// Definition struct for an AnimationState, which can be deserialized from JSON
/// and converted to an AnimationState instance at runtime
#[derive(Clone, Debug)]
pub struct AnimationStateDef {

    /// The identifying name for the state
    pub name: String,

    /// The blend tree definition for this state
    pub blend_tree: BlendTreeNodeDef,

    /// The transitions to other states that can occur from this state
    pub transitions: Vec<AnimationTransition>,
}

impl Decodable for AnimationStateDef {
    fn decode<D: Decoder>(decoder: &mut D) -> Result<AnimationStateDef, D::Error> {
        decoder.read_struct("root", 0, |decoder| {

            let name = try!(decoder.read_struct_field("name", 0, |decoder| {
                Ok(try!(decoder.read_str()))
            }));

            let blend_tree = try!(decoder.read_struct_field("blend_tree", 0, Decodable::decode));

            let transitions = try!(decoder.read_struct_field("transitions", 0, |decoder| {
                decoder.read_seq(|decoder, len| {
                    let mut transitions = Vec::new();
                    for i in (0 .. len) {
                        transitions.push(try!(decoder.read_seq_elt(i, Decodable::decode)));
                    }
                    Ok(transitions)
                })
            }));

            Ok(AnimationStateDef {
                name: name,
                blend_tree: blend_tree,
                transitions: transitions,
            })
        })
    }
}

/// A runtime representation of an Animation State Machine, consisting of one or more
/// AnimationStates connected by AnimationTransitions, where the output animation
/// pose depends on the current state or any active transitions between states.
pub struct AnimationController<T: Transform> {

    /// Parameters that will be referenced by blend tree nodes and animation states
    parameters: HashMap<String, f32>,

    /// Shared reference to the skeleton this controller is using
    skeleton: Rc<Skeleton>,

    /// Tracks seconds since controller started running
    local_clock: f64,

    /// Playback speed multiplier.
    playback_speed: f64,

    /// Mapping of all animation state names to their instances
    states: HashMap<String, AnimationState<T>>,

    /// The name of the current active AnimationState
    current_state: String,

    /// The current active AnimationTransition and its start time, if any
    transition: Option<(f64, AnimationTransition)>,
}

impl<T: Transform> AnimationController<T> {

    /// Create an AnimationController instance from its definition, the desired skeleton, and a
    /// collection of currently loaded animation clips.
    pub fn new(controller_def: AnimationControllerDef, skeleton: Rc<Skeleton>, animations: &HashMap<ClipId, Rc<AnimationClip<T>>>) -> AnimationController<T> {

        let mut parameters = HashMap::new();

        for parameter in controller_def.parameters.iter() {
            parameters.insert(parameter.clone(), 0.0);
        };

        let mut states = HashMap::new();
        for state_def in controller_def.states.iter() {
            states.insert(state_def.name.clone(), AnimationState {
                blend_tree: BlendTreeNode::from_def(state_def.blend_tree.clone(), animations),
                transitions: state_def.transitions.clone()
            });
        }

        AnimationController {
            parameters: parameters,
            skeleton: skeleton.clone(),
            local_clock: 0.0,
            playback_speed: 1.0,
            states: states,
            current_state: controller_def.initial_state,
            transition: None,
        }
    }

    /// Update the controller's local clock with the given time delta
    pub fn update(&mut self, delta_time: f64) {
        self.local_clock += delta_time * self.playback_speed;
    }

    /// Checks if controller should transition to a different state, or if currently
    /// in a transition, checks if the transition is complete
    fn update_state(&mut self, ext_dt: f64) {
        match self.transition.clone() {
            Some((ref start_time, ref transition)) => {
                // If transition is finished, switch state to new transition
                if self.local_clock + ext_dt >= start_time + transition.duration as f64{
                    self.current_state = transition.target_state.clone();
                    self.transition = None;
                }
            },
            None => {

                // Check for any transitions with passing conditions
                let current_state = &self.states[&self.current_state[..]];
                for transition in current_state.transitions.iter() {

                    if transition.condition.is_true(&self.parameters) {
                        self.transition = Some((self.local_clock + ext_dt, transition.clone()));
                        break;
                    }
                }
            }
        }
    }

    /// Set the playback speed for the controller
    pub fn set_playback_speed(&mut self, speed: f64) {
        self.playback_speed = speed;
    }

    /// Set the value for the given controller parameter
    pub fn set_param_value(&mut self, name: &str, value: f32) {
        self.parameters.insert(name.to_string(), value); // :(
    }

    /// Return the value for the given controller parameter
    pub fn get_param_value(&self, name: &str) -> f32 {
        self.parameters[name]
    }

    /// Return a read-only reference to the controller parameter map
    pub fn get_parameters(&self) -> &HashMap<String, f32> {
        &self.parameters
    }

    /// Calculate global skeletal joint poses for the given time since last update
    pub fn get_output_pose(&mut self, ext_dt: f64, output_poses: &mut [Matrix4<f32>]) {

        self.update_state(ext_dt);

        let elapsed_time = self.local_clock + ext_dt * self.playback_speed;

        let mut local_poses = [ T::identity(); MAX_JOINTS ];

        {
            let current_state = self.states.get_mut(&self.current_state[..]).unwrap();
            current_state.blend_tree.get_output_pose(elapsed_time as f32, &self.parameters, &mut local_poses[..]);
        }

        // TODO - would be kinda cool if you could just use a lerp node that pointed to the two
        // blend trees, but then we'd need RC pointers?

        if let Some((transition_start_time, ref transition)) = self.transition {

            // Blend with the target state ...

            let mut target_poses = [ T::identity(); MAX_JOINTS ];

            let target_state = self.states.get_mut(&transition.target_state[..]).unwrap();

            target_state.blend_tree.get_output_pose(elapsed_time as f32, &self.parameters, &mut target_poses[..]);

            let blend_parameter = ((self.local_clock + ext_dt - transition_start_time) / transition.duration as f64) as f32;

            for i in (0 .. output_poses.len()) {
                let pose_1 = &mut local_poses[i];
                let pose_2 = target_poses[i];
                *pose_1 = pose_1.lerp(pose_2, blend_parameter);
            }

        }

        self.calculate_global_poses(&local_poses[..], output_poses);
    }

    /// Calculate global poses from the controller's skeleton and the given local poses
    fn calculate_global_poses(
        &self,
        local_poses: &[T],
        global_poses: &mut [Matrix4<f32>],
    ) {

        for (joint_index, joint) in self.skeleton.joints.iter().enumerate() {

            let parent_pose = if !joint.is_root() {
                global_poses[joint.parent_index as usize]
            } else {
                mat4_id()
            };

            let local_pose = &local_poses[joint_index];
            global_poses[joint_index] = row_mat4_mul(parent_pose, local_pose.to_matrix());
        }
    }
}
<commit_msg>Fixed issue where animations can start out of sync<commit_after>use std::collections::HashMap;
use std::rc::Rc;

use rustc_serialize::{Decodable, Decoder};

use animation::AnimationClip;
use transform::Transform;
use blend_tree::{BlendTreeNode, BlendTreeNodeDef, ClipId};
use math::*;
use skeleton::Skeleton;

const MAX_JOINTS: usize = 64;

/// A state that an AnimationController can be in, consisting
/// of a blend tree and a collection of transitions to other states
pub struct AnimationState<T: Transform> {

    /// The blend tree used to determine the final blended pose
    /// for this state
    pub blend_tree: BlendTreeNode<T>,

    /// Transitions from this state to other AnimationStates
    pub transitions: Vec<AnimationTransition>,
}

/// Representation of a state transition to a target state, with a condition and a duration
#[derive(Debug, Clone, RustcDecodable)]
pub struct AnimationTransition {
    /// The name of the target state to transition to
    pub target_state: String,

    /// The condition that will be checked in order to determine
    /// if the controller should transition to the target state
    pub condition: TransitionCondition,

    /// The duration of the transition, during which a linear blend
    /// transition between the current and target states should occur
    pub duration: f32,
}

/// Representation of a condition to check for an AnimationTransition
#[derive(Debug, Clone, RustcDecodable)]
pub struct TransitionCondition {

    /// The name of the controller parameter to compare with
    pub parameter: String,

    /// The comparision operator to use
    pub operator: Operator,

    /// The constant value to compare with the controller parameter value
    pub value: f32,
}

impl TransitionCondition {
    /// Returns true if the condition is satisfied
    pub fn is_true(&self, parameters: &HashMap<String, f32>) -> bool {
        match self.operator {
            Operator::LessThan => parameters[&self.parameter[..]] < self.value,
            Operator::GreaterThan => parameters[&self.parameter[..]] > self.value,
            Operator::LessThanEqual => parameters[&self.parameter[..]] <= self.value,
            Operator::GreaterThanEqual => parameters[&self.parameter[..]] >= self.value,
            Operator::Equal => parameters[&self.parameter[..]] == self.value,
            Operator::NotEqual => parameters[&self.parameter[..]] != self.value,
        }
    }
}

#[derive(Debug, Clone)]
pub enum Operator {
    LessThan,
    LessThanEqual,
    GreaterThan,
    GreaterThanEqual,
    Equal,
    NotEqual,
}

impl Decodable for Operator {
    fn decode<D: Decoder>(decoder: &mut D) -> Result<Operator, D::Error> {
        match &try!(decoder.read_str())[..] {
            "<" => Ok(Operator::LessThan),
            ">" => Ok(Operator::GreaterThan),
            "<=" => Ok(Operator::LessThanEqual),
            ">=" => Ok(Operator::GreaterThanEqual),
            "=" => Ok(Operator::Equal),
            "!=" => Ok(Operator::NotEqual),
            _ => Ok(Operator::Equal), // FIXME -- figure out how to throw a D::Error...
        }
    }
}

/// Definition struct for an AnimationController, which can be deserialized from JSON
/// and converted to an AnimationController instance at runtime
#[derive(Clone, Debug, RustcDecodable)]
pub struct AnimationControllerDef {

    /// Identifying name for the controller definition
    pub name: String,

    /// Declaration list of all parameters that are used by the AnimationController,
    /// including state transition conditions and blend tree parameters
    pub parameters: Vec<String>,

    /// List of animation state definitions
    pub states: Vec<AnimationStateDef>,

    /// The name of the state that the AnimationController should start in
    pub initial_state: String,
}

/// Definition struct for an AnimationState, which can be deserialized from JSON
/// and converted to an AnimationState instance at runtime
#[derive(Clone, Debug)]
pub struct AnimationStateDef {

    /// The identifying name for the state
    pub name: String,

    /// The blend tree definition for this state
    pub blend_tree: BlendTreeNodeDef,

    /// The transitions to other states that can occur from this state
    pub transitions: Vec<AnimationTransition>,
}

impl Decodable for AnimationStateDef {
    fn decode<D: Decoder>(decoder: &mut D) -> Result<AnimationStateDef, D::Error> {
        decoder.read_struct("root", 0, |decoder| {

            let name = try!(decoder.read_struct_field("name", 0, |decoder| {
                Ok(try!(decoder.read_str()))
            }));

            let blend_tree = try!(decoder.read_struct_field("blend_tree", 0, Decodable::decode));

            let transitions = try!(decoder.read_struct_field("transitions", 0, |decoder| {
                decoder.read_seq(|decoder, len| {
                    let mut transitions = Vec::new();
                    for i in (0 .. len) {
                        transitions.push(try!(decoder.read_seq_elt(i, Decodable::decode)));
                    }
                    Ok(transitions)
                })
            }));

            Ok(AnimationStateDef {
                name: name,
                blend_tree: blend_tree,
                transitions: transitions,
            })
        })
    }
}

/// A runtime representation of an Animation State Machine, consisting of one or more
/// AnimationStates connected by AnimationTransitions, where the output animation
/// pose depends on the current state or any active transitions between states.
pub struct AnimationController<T: Transform> {

    /// Parameters that will be referenced by blend tree nodes and animation states
    parameters: HashMap<String, f32>,

    /// Shared reference to the skeleton this controller is using
    skeleton: Rc<Skeleton>,

    /// Tracks seconds since controller started running
    local_clock: f64,

    /// Playback speed multiplier.
    playback_speed: f64,

    /// Mapping of all animation state names to their instances
    states: HashMap<String, AnimationState<T>>,

    /// The name of the current active AnimationState
    current_state: String,

    /// The current active AnimationTransition and its start time, if any
    transition: Option<(f64, AnimationTransition)>,
}

impl<T: Transform> AnimationController<T> {

    /// Create an AnimationController instance from its definition, the desired skeleton, and a
    /// collection of currently loaded animation clips.
    pub fn new(controller_def: AnimationControllerDef, skeleton: Rc<Skeleton>, animations: &HashMap<ClipId, Rc<AnimationClip<T>>>) -> AnimationController<T> {

        let mut parameters = HashMap::new();

        for parameter in controller_def.parameters.iter() {
            parameters.insert(parameter.clone(), 0.0);
        };

        let mut states = HashMap::new();
        for state_def in controller_def.states.iter() {

            let mut blend_tree = BlendTreeNode::from_def(state_def.blend_tree.clone(), animations);
            blend_tree.synchronize_subtree(0.0, &parameters);

            states.insert(state_def.name.clone(), AnimationState {
                blend_tree: blend_tree,
                transitions: state_def.transitions.clone()
            });

        }

        AnimationController {
            parameters: parameters,
            skeleton: skeleton.clone(),
            local_clock: 0.0,
            playback_speed: 1.0,
            states: states,
            current_state: controller_def.initial_state,
            transition: None,
        }
    }

    /// Update the controller's local clock with the given time delta
    pub fn update(&mut self, delta_time: f64) {
        self.local_clock += delta_time * self.playback_speed;
    }

    /// Checks if controller should transition to a different state, or if currently
    /// in a transition, checks if the transition is complete
    fn update_state(&mut self, ext_dt: f64) {
        match self.transition.clone() {
            Some((ref start_time, ref transition)) => {
                // If transition is finished, switch state to new transition
                if self.local_clock + ext_dt >= start_time + transition.duration as f64{
                    self.current_state = transition.target_state.clone();
                    self.transition = None;
                }
            },
            None => {

                // Check for any transitions with passing conditions
                let current_state = &self.states[&self.current_state[..]];
                for transition in current_state.transitions.iter() {

                    if transition.condition.is_true(&self.parameters) {
                        self.transition = Some((self.local_clock + ext_dt, transition.clone()));
                        break;
                    }
                }
            }
        }
    }

    /// Set the playback speed for the controller
    pub fn set_playback_speed(&mut self, speed: f64) {
        self.playback_speed = speed;
    }

    /// Set the value for the given controller parameter
    pub fn set_param_value(&mut self, name: &str, value: f32) {
        self.parameters.insert(name.to_string(), value); // :(
    }

    /// Return the value for the given controller parameter
    pub fn get_param_value(&self, name: &str) -> f32 {
        self.parameters[name]
    }

    /// Return a read-only reference to the controller parameter map
    pub fn get_parameters(&self) -> &HashMap<String, f32> {
        &self.parameters
    }

    /// Calculate global skeletal joint poses for the given time since last update
    pub fn get_output_pose(&mut self, ext_dt: f64, output_poses: &mut [Matrix4<f32>]) {

        self.update_state(ext_dt);

        let elapsed_time = self.local_clock + ext_dt * self.playback_speed;

        let mut local_poses = [ T::identity(); MAX_JOINTS ];

        {
            let current_state = self.states.get_mut(&self.current_state[..]).unwrap();
            current_state.blend_tree.get_output_pose(elapsed_time as f32, &self.parameters, &mut local_poses[..]);
        }

        // TODO - would be kinda cool if you could just use a lerp node that pointed to the two
        // blend trees, but then we'd need RC pointers?

        if let Some((transition_start_time, ref transition)) = self.transition {

            // Blend with the target state ...

            let mut target_poses = [ T::identity(); MAX_JOINTS ];

            let target_state = self.states.get_mut(&transition.target_state[..]).unwrap();

            target_state.blend_tree.get_output_pose(elapsed_time as f32, &self.parameters, &mut target_poses[..]);

            let blend_parameter = ((self.local_clock + ext_dt - transition_start_time) / transition.duration as f64) as f32;

            for i in (0 .. output_poses.len()) {
                let pose_1 = &mut local_poses[i];
                let pose_2 = target_poses[i];
                *pose_1 = pose_1.lerp(pose_2, blend_parameter);
            }

        }

        self.calculate_global_poses(&local_poses[..], output_poses);
    }

    /// Calculate global poses from the controller's skeleton and the given local poses
    fn calculate_global_poses(
        &self,
        local_poses: &[T],
        global_poses: &mut [Matrix4<f32>],
    ) {

        for (joint_index, joint) in self.skeleton.joints.iter().enumerate() {

            let parent_pose = if !joint.is_root() {
                global_poses[joint.parent_index as usize]
            } else {
                mat4_id()
            };

            let local_pose = &local_poses[joint_index];
            global_poses[joint_index] = row_mat4_mul(parent_pose, local_pose.to_matrix());
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! A type-checked scaling factor between units.

use num::One;

use num_traits::NumCast;
#[cfg(feature = "serde")]
use serde;
use core::fmt;
use core::ops::{Add, Div, Mul, Neg, Sub};
use core::marker::PhantomData;
use {Point2D, Rect, Size2D, Vector2D};

/// A scaling factor between two different units of measurement.
///
/// This is effectively a type-safe float, intended to be used in combination with other types like
/// `length::Length` to enforce conversion between systems of measurement at compile time.
///
/// `Src` and `Dst` represent the units before and after multiplying a value by a `Scale`. They
/// may be types without values, such as empty enums.  For example:
///
/// ```rust
/// use euclid::Scale;
/// use euclid::Length;
/// enum Mm {};
/// enum Inch {};
///
/// let mm_per_inch: Scale<f32, Inch, Mm> = Scale::new(25.4);
///
/// let one_foot: Length<f32, Inch> = Length::new(12.0);
/// let one_foot_in_mm: Length<f32, Mm> = one_foot * mm_per_inch;
/// ```
#[repr(C)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(bound(serialize = "T: serde::Serialize", deserialize = "T: serde::Deserialize<'de>")))]
pub struct Scale<T, Src, Dst>(pub T, #[doc(hidden)] pub PhantomData<(Src, Dst)>);

impl<T, Src, Dst> Scale<T, Src, Dst> {
    pub const fn new(x: T) -> Self {
        Scale(x, PhantomData)
    }
}

impl<T: Clone, Src, Dst> Scale<T, Src, Dst> {
    pub fn get(&self) -> T {
        self.0.clone()
    }
}

impl<Src, Dst> Scale<f32, Src, Dst> {
    /// Identity scaling, could be used to safely transit from one space to another.
    pub const ONE: Self = Scale(1.0, PhantomData);
}

impl<T: Clone + One + Div<T, Output = T>, Src, Dst> Scale<T, Src, Dst> {
    /// The inverse Scale (1.0 / self).
    pub fn inv(&self) -> Scale<T, Dst, Src> {
        let one: T = One::one();
        Scale::new(one / self.get())
    }
}

// scale0 * scale1
impl<T: Clone + Mul<T, Output = T>, A, B, C> Mul<Scale<T, B, C>> for Scale<T, A, B> {
    type Output = Scale<T, A, C>;
    #[inline]
    fn mul(self, other: Scale<T, B, C>) -> Scale<T, A, C> {
        Scale::new(self.get() * other.get())
    }
}

// scale0 + scale1
impl<T: Clone + Add<T, Output = T>, Src, Dst> Add for Scale<T, Src, Dst> {
    type Output = Scale<T, Src, Dst>;
    #[inline]
    fn add(self, other: Scale<T, Src, Dst>) -> Scale<T, Src, Dst> {
        Scale::new(self.get() + other.get())
    }
}

// scale0 - scale1
impl<T: Clone + Sub<T, Output = T>, Src, Dst> Sub for Scale<T, Src, Dst> {
    type Output = Scale<T, Src, Dst>;
    #[inline]
    fn sub(self, other: Scale<T, Src, Dst>) -> Scale<T, Src, Dst> {
        Scale::new(self.get() - other.get())
    }
}

impl<T: NumCast + Clone, Src, Dst0> Scale<T, Src, Dst0> {
    /// Cast from one numeric representation to another, preserving the units.
    pub fn cast<T1: NumCast + Clone>(&self) -> Scale<T1, Src, Dst0> {
        self.try_cast().unwrap()
    }

    /// Fallible cast from one numeric representation to another, preserving the units.
    pub fn try_cast<T1: NumCast + Clone>(&self) -> Option<Scale<T1, Src, Dst0>> {
        NumCast::from(self.get()).map(Scale::new)
    }
}

impl<T, Src, Dst> Scale<T, Src, Dst>
where
    T: Copy + Clone + Mul<T, Output = T> + Neg<Output = T> + PartialEq + One,
{
    /// Returns the given point transformed by this scale.
    #[inline]
    pub fn transform_point(&self, point: Point2D<T, Src>) -> Point2D<T, Dst> {
        Point2D::new(point.x * self.get(), point.y * self.get())
    }

    /// Returns the given vector transformed by this scale.
    #[inline]
    pub fn transform_vector(&self, vec: Vector2D<T, Src>) -> Vector2D<T, Dst> {
        Vector2D::new(vec.x * self.get(), vec.y * self.get())
    }

    /// Returns the given vector transformed by this scale.
    #[inline]
    pub fn transform_size(&self, size: Size2D<T, Src>) -> Size2D<T, Dst> {
        Size2D::new(size.width * self.get(), size.height * self.get())
    }

    /// Returns the given rect transformed by this scale.
    #[inline]
    pub fn transform_rect(&self, rect: &Rect<T, Src>) -> Rect<T, Dst> {
        Rect::new(
            self.transform_point(rect.origin),
            self.transform_size(rect.size),
        )
    }

    /// Returns the inverse of this scale.
    #[inline]
    pub fn inverse(&self) -> Scale<T, Dst, Src> {
        Scale::new(-self.get())
    }

    /// Returns true if this scale has no effect.
    #[inline]
    pub fn is_identity(&self) -> bool {
        self.get() == T::one()
    }
}

// FIXME: Switch to `derive(PartialEq, Clone)` after this Rust issue is fixed:
// https://github.com/mozilla/rust/issues/7671

impl<T: PartialEq, Src, Dst> PartialEq for Scale<T, Src, Dst> {
    fn eq(&self, other: &Scale<T, Src, Dst>) -> bool {
        self.0 == other.0
    }
}

impl<T: Clone, Src, Dst> Clone for Scale<T, Src, Dst> {
    fn clone(&self) -> Scale<T, Src, Dst> {
        Scale::new(self.get())
    }
}

impl<T: Copy, Src, Dst> Copy for Scale<T, Src, Dst> {}

impl<T: fmt::Debug, Src, Dst> fmt::Debug for Scale<T, Src, Dst> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl<T: fmt::Display, Src, Dst> fmt::Display for Scale<T, Src, Dst> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

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

    enum Inch {}
    enum Cm {}
    enum Mm {}

    #[test]
    fn test_scale() {
        let mm_per_inch: Scale<f32, Inch, Mm> = Scale::new(25.4);
        let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);

        let mm_per_cm: Scale<f32, Cm, Mm> = cm_per_mm.inv();
        assert_eq!(mm_per_cm.get(), 10.0);

        let cm_per_inch: Scale<f32, Inch, Cm> = mm_per_inch * cm_per_mm;
        assert_eq!(cm_per_inch, Scale::new(2.54));

        let a: Scale<isize, Inch, Inch> = Scale::new(2);
        let b: Scale<isize, Inch, Inch> = Scale::new(3);
        assert!(a != b);
        assert_eq!(a, a.clone());
        assert_eq!(a.clone() + b.clone(), Scale::new(5));
        assert_eq!(a - b, Scale::new(-1));
    }
}
<commit_msg>Switch to using correct fixme link<commit_after>// Copyright 2014 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! A type-checked scaling factor between units.

use num::One;

use num_traits::NumCast;
#[cfg(feature = "serde")]
use serde;
use core::fmt;
use core::ops::{Add, Div, Mul, Neg, Sub};
use core::marker::PhantomData;
use {Point2D, Rect, Size2D, Vector2D};

/// A scaling factor between two different units of measurement.
///
/// This is effectively a type-safe float, intended to be used in combination with other types like
/// `length::Length` to enforce conversion between systems of measurement at compile time.
///
/// `Src` and `Dst` represent the units before and after multiplying a value by a `Scale`. They
/// may be types without values, such as empty enums.  For example:
///
/// ```rust
/// use euclid::Scale;
/// use euclid::Length;
/// enum Mm {};
/// enum Inch {};
///
/// let mm_per_inch: Scale<f32, Inch, Mm> = Scale::new(25.4);
///
/// let one_foot: Length<f32, Inch> = Length::new(12.0);
/// let one_foot_in_mm: Length<f32, Mm> = one_foot * mm_per_inch;
/// ```
#[repr(C)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(bound(serialize = "T: serde::Serialize", deserialize = "T: serde::Deserialize<'de>")))]
pub struct Scale<T, Src, Dst>(pub T, #[doc(hidden)] pub PhantomData<(Src, Dst)>);

impl<T, Src, Dst> Scale<T, Src, Dst> {
    pub const fn new(x: T) -> Self {
        Scale(x, PhantomData)
    }
}

impl<T: Clone, Src, Dst> Scale<T, Src, Dst> {
    pub fn get(&self) -> T {
        self.0.clone()
    }
}

impl<Src, Dst> Scale<f32, Src, Dst> {
    /// Identity scaling, could be used to safely transit from one space to another.
    pub const ONE: Self = Scale(1.0, PhantomData);
}

impl<T: Clone + One + Div<T, Output = T>, Src, Dst> Scale<T, Src, Dst> {
    /// The inverse Scale (1.0 / self).
    pub fn inv(&self) -> Scale<T, Dst, Src> {
        let one: T = One::one();
        Scale::new(one / self.get())
    }
}

// scale0 * scale1
impl<T: Clone + Mul<T, Output = T>, A, B, C> Mul<Scale<T, B, C>> for Scale<T, A, B> {
    type Output = Scale<T, A, C>;
    #[inline]
    fn mul(self, other: Scale<T, B, C>) -> Scale<T, A, C> {
        Scale::new(self.get() * other.get())
    }
}

// scale0 + scale1
impl<T: Clone + Add<T, Output = T>, Src, Dst> Add for Scale<T, Src, Dst> {
    type Output = Scale<T, Src, Dst>;
    #[inline]
    fn add(self, other: Scale<T, Src, Dst>) -> Scale<T, Src, Dst> {
        Scale::new(self.get() + other.get())
    }
}

// scale0 - scale1
impl<T: Clone + Sub<T, Output = T>, Src, Dst> Sub for Scale<T, Src, Dst> {
    type Output = Scale<T, Src, Dst>;
    #[inline]
    fn sub(self, other: Scale<T, Src, Dst>) -> Scale<T, Src, Dst> {
        Scale::new(self.get() - other.get())
    }
}

impl<T: NumCast + Clone, Src, Dst0> Scale<T, Src, Dst0> {
    /// Cast from one numeric representation to another, preserving the units.
    pub fn cast<T1: NumCast + Clone>(&self) -> Scale<T1, Src, Dst0> {
        self.try_cast().unwrap()
    }

    /// Fallible cast from one numeric representation to another, preserving the units.
    pub fn try_cast<T1: NumCast + Clone>(&self) -> Option<Scale<T1, Src, Dst0>> {
        NumCast::from(self.get()).map(Scale::new)
    }
}

impl<T, Src, Dst> Scale<T, Src, Dst>
where
    T: Copy + Clone + Mul<T, Output = T> + Neg<Output = T> + PartialEq + One,
{
    /// Returns the given point transformed by this scale.
    #[inline]
    pub fn transform_point(&self, point: Point2D<T, Src>) -> Point2D<T, Dst> {
        Point2D::new(point.x * self.get(), point.y * self.get())
    }

    /// Returns the given vector transformed by this scale.
    #[inline]
    pub fn transform_vector(&self, vec: Vector2D<T, Src>) -> Vector2D<T, Dst> {
        Vector2D::new(vec.x * self.get(), vec.y * self.get())
    }

    /// Returns the given vector transformed by this scale.
    #[inline]
    pub fn transform_size(&self, size: Size2D<T, Src>) -> Size2D<T, Dst> {
        Size2D::new(size.width * self.get(), size.height * self.get())
    }

    /// Returns the given rect transformed by this scale.
    #[inline]
    pub fn transform_rect(&self, rect: &Rect<T, Src>) -> Rect<T, Dst> {
        Rect::new(
            self.transform_point(rect.origin),
            self.transform_size(rect.size),
        )
    }

    /// Returns the inverse of this scale.
    #[inline]
    pub fn inverse(&self) -> Scale<T, Dst, Src> {
        Scale::new(-self.get())
    }

    /// Returns true if this scale has no effect.
    #[inline]
    pub fn is_identity(&self) -> bool {
        self.get() == T::one()
    }
}

// FIXME: Switch to `derive(PartialEq, Clone)` after this Rust issue is fixed:
// https://github.com/rust-lang/rust/issues/26925

impl<T: PartialEq, Src, Dst> PartialEq for Scale<T, Src, Dst> {
    fn eq(&self, other: &Scale<T, Src, Dst>) -> bool {
        self.0 == other.0
    }
}

impl<T: Clone, Src, Dst> Clone for Scale<T, Src, Dst> {
    fn clone(&self) -> Scale<T, Src, Dst> {
        Scale::new(self.get())
    }
}

impl<T: Copy, Src, Dst> Copy for Scale<T, Src, Dst> {}

impl<T: fmt::Debug, Src, Dst> fmt::Debug for Scale<T, Src, Dst> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl<T: fmt::Display, Src, Dst> fmt::Display for Scale<T, Src, Dst> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

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

    enum Inch {}
    enum Cm {}
    enum Mm {}

    #[test]
    fn test_scale() {
        let mm_per_inch: Scale<f32, Inch, Mm> = Scale::new(25.4);
        let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);

        let mm_per_cm: Scale<f32, Cm, Mm> = cm_per_mm.inv();
        assert_eq!(mm_per_cm.get(), 10.0);

        let cm_per_inch: Scale<f32, Inch, Cm> = mm_per_inch * cm_per_mm;
        assert_eq!(cm_per_inch, Scale::new(2.54));

        let a: Scale<isize, Inch, Inch> = Scale::new(2);
        let b: Scale<isize, Inch, Inch> = Scale::new(3);
        assert!(a != b);
        assert_eq!(a, a.clone());
        assert_eq!(a.clone() + b.clone(), Scale::new(5));
        assert_eq!(a - b, Scale::new(-1));
    }
}
<|endoftext|>


<commit_before>use cgmath::Point2;
use pathfinding::{directed::astar::astar, utils::absdiff};

use crate::game::constants::{TILES_PCS_H, TILES_PCS_W, TERRAIN_OBJECTS};
use crate::game::get_rand_from_range;
use crate::graphics::coords_to_tile;
use crate::shaders::Position;

fn neighbours<'c>(curr_pos: Point2<i32>, impassable_tiles: &[[i32; 2]], neighbour_tiles: &'c mut Vec<Point2<i32>>) -> Vec<&'c Point2<i32>> {
  neighbour_tiles.push(Point2::new(curr_pos.x - 1, curr_pos.y));
  neighbour_tiles.push(Point2::new(curr_pos.x - 1, curr_pos.y - 1));
  neighbour_tiles.push(Point2::new(curr_pos.x, curr_pos.y - 1));
  neighbour_tiles.push(Point2::new(curr_pos.x + 1, curr_pos.y));
  neighbour_tiles.push(Point2::new(curr_pos.x + 1, curr_pos.y + 1));
  neighbour_tiles.push(Point2::new(curr_pos.x, curr_pos.y + 1));
  neighbour_tiles.push(Point2::new(curr_pos.x - 1, curr_pos.y + 1));
  neighbour_tiles.push(Point2::new(curr_pos.x + 1, curr_pos.y - 1));

  neighbour_tiles
    .iter()
    .filter(|ref e| e.x >= 0 && e.x < TILES_PCS_W as i32 && e.y >= 0 && e.y < TILES_PCS_H as i32)
    .filter(|ref e| !impassable_tiles.contains(&[e.x, e.y]))
    .collect()
}

fn tiles(p: Point2<i32>, impassable_tiles: &[[i32; 2]]) -> Vec<(Point2<i32>, i32)> {
  neighbours(p, &impassable_tiles, &mut vec![])
    .iter()
    .map(|p| (**p, 1))
    .collect()
}

fn find_next_best_endpoint<'c>(end_point: &'c Point2<i32>, impassable_tiles: &[[i32; 2]], neighbour_tiles: &'c mut Vec<Point2<i32>>) -> &'c Point2<i32> {
  if impassable_tiles.iter().any(|e| e[0] == end_point.x && e[1] == end_point.y) {
    neighbours(*end_point, &impassable_tiles, neighbour_tiles)[0]
  } else {
    &end_point
  }
}

pub fn calc_route(start_point: Position, end_point: Position, impassable_tiles: &[[i32; 2]]) -> Option<(Vec<Point2<i32>>, i32)> {
  let mut neighbour_tiles = vec![];
  let end_point_with_offset = coords_to_tile(end_point);

  let start = coords_to_tile(start_point);
  let end = find_next_best_endpoint(&end_point_with_offset, &impassable_tiles, &mut neighbour_tiles);

  astar(&start,
        |p: &Point2<i32>| tiles(*p, &impassable_tiles),
        |p: &Point2<i32>| absdiff(p.x, end.x) + absdiff(p.y, end.y),
        |p: &Point2<i32>| p.x == end.x && p.y == end.y)
}

pub fn calc_next_movement(start_point: Position, end_point: Position) -> i32 {
  let next_step: Point2<i32> = calc_route(start_point, end_point, &TERRAIN_OBJECTS.to_vec())
    .map_or_else(|| Point2::new(0, 0),
                 |(route, ..)| {
                   if route.len() > 1 {
                     route[1]
                   } else {
                     route[0]
                   }
                 });

  let start = coords_to_tile(start_point);
  let diff: (i32, i32) = (next_step.x - start.x, next_step.y - start.y);

  match diff {
    (1, 0) => 315,
    (1, 1) => 270,
    (0, 1) => 225,
    (-1, 1) => 180,
    (-1, 0) => 135,
    (-1, -1) => 90,
    (0, -1) => 45,
    (1, -1) => 0,
    _ => get_rand_from_range(0, 359),
  }
}
<commit_msg>Rename variables<commit_after>use cgmath::Point2;
use pathfinding::{directed::astar::astar, utils::absdiff};

use crate::game::constants::{TILES_PCS_H, TILES_PCS_W, TERRAIN_OBJECTS};
use crate::game::get_rand_from_range;
use crate::graphics::coords_to_tile;
use crate::shaders::Position;

fn neighbours<'c>(curr_pos: Point2<i32>, impassable_tiles: &[[i32; 2]], neighbour_tiles: &'c mut Vec<Point2<i32>>) -> Vec<&'c Point2<i32>> {
  neighbour_tiles.push(Point2::new(curr_pos.x - 1, curr_pos.y));
  neighbour_tiles.push(Point2::new(curr_pos.x - 1, curr_pos.y - 1));
  neighbour_tiles.push(Point2::new(curr_pos.x, curr_pos.y - 1));
  neighbour_tiles.push(Point2::new(curr_pos.x + 1, curr_pos.y));
  neighbour_tiles.push(Point2::new(curr_pos.x + 1, curr_pos.y + 1));
  neighbour_tiles.push(Point2::new(curr_pos.x, curr_pos.y + 1));
  neighbour_tiles.push(Point2::new(curr_pos.x - 1, curr_pos.y + 1));
  neighbour_tiles.push(Point2::new(curr_pos.x + 1, curr_pos.y - 1));

  neighbour_tiles
    .iter()
    .filter(|ref e| e.x >= 0 && e.x < TILES_PCS_W as i32 && e.y >= 0 && e.y < TILES_PCS_H as i32)
    .filter(|ref e| !impassable_tiles.contains(&[e.x, e.y]))
    .collect()
}

fn tiles(p: Point2<i32>, impassable_tiles: &[[i32; 2]]) -> Vec<(Point2<i32>, i32)> {
  neighbours(p, &impassable_tiles, &mut vec![])
    .iter()
    .map(|p| (**p, 1))
    .collect()
}

fn find_next_best_endpoint<'c>(end_point: &'c Point2<i32>, impassable_tiles: &[[i32; 2]], neighbour_tiles: &'c mut Vec<Point2<i32>>) -> &'c Point2<i32> {
  if impassable_tiles.iter().any(|e| e[0] == end_point.x && e[1] == end_point.y) {
    neighbours(*end_point, &impassable_tiles, neighbour_tiles)[0]
  } else {
    &end_point
  }
}

pub fn calc_route(start_point: Position, end_point: Position, impassable_tiles: &[[i32; 2]]) -> Option<(Vec<Point2<i32>>, i32)> {
  let mut neighbour_tiles = vec![];
  let end_tile = coords_to_tile(end_point);
  let start_tile = coords_to_tile(start_point);

  let end = find_next_best_endpoint(&end_tile, &impassable_tiles, &mut neighbour_tiles);

  astar(&start_tile,
        |p: &Point2<i32>| tiles(*p, &impassable_tiles),
        |p: &Point2<i32>| absdiff(p.x, end.x) + absdiff(p.y, end.y),
        |p: &Point2<i32>| p.x == end.x && p.y == end.y)
}

pub fn calc_next_movement(start_point: Position, end_point: Position) -> i32 {
  let next_step: Point2<i32> = calc_route(start_point, end_point, &TERRAIN_OBJECTS.to_vec())
    .map_or_else(|| Point2::new(0, 0),
                 |(route, ..)| {
                   if route.len() > 1 {
                     route[1]
                   } else {
                     route[0]
                   }
                 });

  let start = coords_to_tile(start_point);
  let diff: (i32, i32) = (next_step.x - start.x, next_step.y - start.y);

  match diff {
    (1, 0) => 315,
    (1, 1) => 270,
    (0, 1) => 225,
    (-1, 1) => 180,
    (-1, 0) => 135,
    (-1, -1) => 90,
    (0, -1) => 45,
    (1, -1) => 0,
    _ => get_rand_from_range(0, 359),
  }
}
<|endoftext|>


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

use std::env;
use std::process::Command;
use std::path::{Path, PathBuf};
use std::fs::File;
use std::io::Write;

struct Test {
    repo: &'static str,
    name: &'static str,
    sha: &'static str,
    lock: Option<&'static str>,
}

const TEST_REPOS: &'static [Test] = &[
    Test {
        name: "cargo",
        repo: "https://github.com/rust-lang/cargo",
        sha: "b7be4f2ef2cf743492edc6dfb55d087ed88f2d76",
        lock: None,
    },
    Test {
        name: "iron",
        repo: "https://github.com/iron/iron",
        sha: "16c858ec2901e2992fe5e529780f59fa8ed12903",
        lock: Some(include_str!("lockfiles/iron-Cargo.lock")),
    },
    Test {
        name: "ripgrep",
        repo: "https://github.com/BurntSushi/ripgrep",
        sha: "b65bb37b14655e1a89c7cd19c8b011ef3e312791",
        lock: None,
    },
    Test {
        name: "tokei",
        repo: "https://github.com/Aaronepower/tokei",
        sha: "5e11c4852fe4aa086b0e4fe5885822fbe57ba928",
        lock: None,
    },
    Test {
        name: "treeify",
        repo: "https://github.com/dzamlo/treeify",
        sha: "999001b223152441198f117a68fb81f57bc086dd",
        lock: None,
    },
];

fn main() {
    // One of the projects being tested here is Cargo, and when being tested
    // Cargo will at some point call `nmake.exe` on Windows MSVC. Unfortunately
    // `nmake` will read these two environment variables below and try to
    // intepret them. We're likely being run, however, from MSYS `make` which
    // uses the same variables.
    //
    // As a result, to prevent confusion and errors, we remove these variables
    // from our environment to prevent passing MSYS make flags to nmake, causing
    // it to blow up.
    if cfg!(target_env = "msvc") {
        env::remove_var("MAKE");
        env::remove_var("MAKEFLAGS");
    }

    let args = env::args().collect::<Vec<_>>();
    let ref cargo = args[1];
    let out_dir = Path::new(&args[2]);
    let ref cargo = Path::new(cargo);

    for test in TEST_REPOS.iter().rev() {
        test_repo(cargo, out_dir, test);
    }
}

fn test_repo(cargo: &Path, out_dir: &Path, test: &Test) {
    println!("testing {}", test.repo);
    let dir = clone_repo(test, out_dir);
    if let Some(lockfile) = test.lock {
        File::create(&dir.join("Cargo.lock"))
            .expect("")
            .write_all(lockfile.as_bytes())
            .expect("");
    }
    if !run_cargo_test(cargo, &dir) {
        panic!("tests failed for {}", test.repo);
    }
}

fn clone_repo(test: &Test, out_dir: &Path) -> PathBuf {
    let out_dir = out_dir.join(test.name);

    if !out_dir.join(".git").is_dir() {
        let status = Command::new("git")
                         .arg("init")
                         .arg(&out_dir)
                         .status()
                         .expect("");
        assert!(status.success());
    }

    // Try progressively deeper fetch depths to find the commit
    let mut found = false;
    for depth in &[0, 1, 10, 100, 1000, 100000] {
        if *depth > 0 {
            let status = Command::new("git")
                             .arg("fetch")
                             .arg(test.repo)
                             .arg("master")
                             .arg(&format!("--depth={}", depth))
                             .current_dir(&out_dir)
                             .status()
                             .expect("");
            assert!(status.success());
        }

        let status = Command::new("git")
                         .arg("reset")
                         .arg(test.sha)
                         .arg("--hard")
                         .current_dir(&out_dir)
                         .status()
                         .expect("");

        if status.success() {
            found = true;
            break;
        }
    }

    if !found {
        panic!("unable to find commit {}", test.sha)
    }
    let status = Command::new("git")
                     .arg("clean")
                     .arg("-fdx")
                     .current_dir(&out_dir)
                     .status()
                     .unwrap();
    assert!(status.success());

    out_dir
}

fn run_cargo_test(cargo_path: &Path, crate_path: &Path) -> bool {
    let status = Command::new(cargo_path)
        .arg("test")
        // Disable rust-lang/cargo's cross-compile tests
        .env("CFG_DISABLE_CROSS_TESTS", "1")
        .current_dir(crate_path)
        .status()
        .expect("");

    status.success()
}
<commit_msg>Auto merge of #38709 - alexcrichton:check-xsv, r=nikomatsakis<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::env;
use std::process::Command;
use std::path::{Path, PathBuf};
use std::fs::File;
use std::io::Write;

struct Test {
    repo: &'static str,
    name: &'static str,
    sha: &'static str,
    lock: Option<&'static str>,
}

const TEST_REPOS: &'static [Test] = &[
    Test {
        name: "cargo",
        repo: "https://github.com/rust-lang/cargo",
        sha: "b7be4f2ef2cf743492edc6dfb55d087ed88f2d76",
        lock: None,
    },
    Test {
        name: "iron",
        repo: "https://github.com/iron/iron",
        sha: "16c858ec2901e2992fe5e529780f59fa8ed12903",
        lock: Some(include_str!("lockfiles/iron-Cargo.lock")),
    },
    Test {
        name: "ripgrep",
        repo: "https://github.com/BurntSushi/ripgrep",
        sha: "b65bb37b14655e1a89c7cd19c8b011ef3e312791",
        lock: None,
    },
    Test {
        name: "tokei",
        repo: "https://github.com/Aaronepower/tokei",
        sha: "5e11c4852fe4aa086b0e4fe5885822fbe57ba928",
        lock: None,
    },
    Test {
        name: "treeify",
        repo: "https://github.com/dzamlo/treeify",
        sha: "999001b223152441198f117a68fb81f57bc086dd",
        lock: None,
    },
    Test {
        name: "xsv",
        repo: "https://github.com/BurntSushi/xsv",
        sha: "a9a7163f2a2953cea426fee1216bec914fe2f56a",
        lock: None,
    },
];

fn main() {
    // One of the projects being tested here is Cargo, and when being tested
    // Cargo will at some point call `nmake.exe` on Windows MSVC. Unfortunately
    // `nmake` will read these two environment variables below and try to
    // intepret them. We're likely being run, however, from MSYS `make` which
    // uses the same variables.
    //
    // As a result, to prevent confusion and errors, we remove these variables
    // from our environment to prevent passing MSYS make flags to nmake, causing
    // it to blow up.
    if cfg!(target_env = "msvc") {
        env::remove_var("MAKE");
        env::remove_var("MAKEFLAGS");
    }

    let args = env::args().collect::<Vec<_>>();
    let ref cargo = args[1];
    let out_dir = Path::new(&args[2]);
    let ref cargo = Path::new(cargo);

    for test in TEST_REPOS.iter().rev() {
        test_repo(cargo, out_dir, test);
    }
}

fn test_repo(cargo: &Path, out_dir: &Path, test: &Test) {
    println!("testing {}", test.repo);
    let dir = clone_repo(test, out_dir);
    if let Some(lockfile) = test.lock {
        File::create(&dir.join("Cargo.lock"))
            .expect("")
            .write_all(lockfile.as_bytes())
            .expect("");
    }
    if !run_cargo_test(cargo, &dir) {
        panic!("tests failed for {}", test.repo);
    }
}

fn clone_repo(test: &Test, out_dir: &Path) -> PathBuf {
    let out_dir = out_dir.join(test.name);

    if !out_dir.join(".git").is_dir() {
        let status = Command::new("git")
                         .arg("init")
                         .arg(&out_dir)
                         .status()
                         .expect("");
        assert!(status.success());
    }

    // Try progressively deeper fetch depths to find the commit
    let mut found = false;
    for depth in &[0, 1, 10, 100, 1000, 100000] {
        if *depth > 0 {
            let status = Command::new("git")
                             .arg("fetch")
                             .arg(test.repo)
                             .arg("master")
                             .arg(&format!("--depth={}", depth))
                             .current_dir(&out_dir)
                             .status()
                             .expect("");
            assert!(status.success());
        }

        let status = Command::new("git")
                         .arg("reset")
                         .arg(test.sha)
                         .arg("--hard")
                         .current_dir(&out_dir)
                         .status()
                         .expect("");

        if status.success() {
            found = true;
            break;
        }
    }

    if !found {
        panic!("unable to find commit {}", test.sha)
    }
    let status = Command::new("git")
                     .arg("clean")
                     .arg("-fdx")
                     .current_dir(&out_dir)
                     .status()
                     .unwrap();
    assert!(status.success());

    out_dir
}

fn run_cargo_test(cargo_path: &Path, crate_path: &Path) -> bool {
    let status = Command::new(cargo_path)
        .arg("test")
        // Disable rust-lang/cargo's cross-compile tests
        .env("CFG_DISABLE_CROSS_TESTS", "1")
        .current_dir(crate_path)
        .status()
        .expect("");

    status.success()
}
<|endoftext|>


<commit_before>use serde::de;
use Value;
use super::{Decoder, DecodeError, DecodeErrorKind};
use std::collections::BTreeMap;

struct MapVisitor<'a, I> {
    iter: I,
    toml: &'a mut Option<Value>,
    key: Option<String>,
    value: Option<Value>,
}

fn se2toml(err: de::value::Error, ty: &'static str) -> DecodeError {
    match err {
        de::value::Error::SyntaxError => de::Error::syntax_error(),
        de::value::Error::EndOfStreamError => de::Error::end_of_stream_error(),
        de::value::Error::MissingFieldError(s) => {
            DecodeError {
                field: Some(s.to_string()),
                kind: DecodeErrorKind::ExpectedField(Some(ty)),
            }
        },
        de::value::Error::UnknownFieldError(s) => {
            DecodeError {
                field: Some(s.to_string()),
                kind: DecodeErrorKind::UnknownField,
            }
        },
    }
}

impl de::Deserializer for Decoder {
    type Error = DecodeError;

    fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, DecodeError>
        where V: de::Visitor
    {
        match self.toml.take() {
            Some(Value::String(s)) => {
                visitor.visit_string(s).map_err(|e| se2toml(e, "string"))
            }
            Some(Value::Integer(i)) => {
                visitor.visit_i64(i).map_err(|e| se2toml(e, "integer"))
            }
            Some(Value::Float(f)) => {
                visitor.visit_f64(f).map_err(|e| se2toml(e, "float"))
            }
            Some(Value::Boolean(b)) => {
                visitor.visit_bool(b).map_err(|e| se2toml(e, "bool"))
            }
            Some(Value::Datetime(s)) => {
                visitor.visit_string(s).map_err(|e| se2toml(e, "date"))
            }
            Some(Value::Array(a)) => {
                let len = a.len();
                let iter = a.into_iter();
                visitor.visit_seq(SeqDeserializer::new(iter, len, &mut self.toml))
            }
            Some(Value::Table(t)) => {
                visitor.visit_map(MapVisitor {
                    iter: t.into_iter(),
                    toml: &mut self.toml,
                    key: None,
                    value: None,
                })
            }
            None => Err(de::Error::end_of_stream_error()),
        }
    }

    fn visit_option<V>(&mut self, mut visitor: V) -> Result<V::Value, DecodeError>
        where V: de::Visitor
    {
        if self.toml.is_none() {
            visitor.visit_none()
        } else {
            visitor.visit_some(self)
        }
    }

    fn visit_seq<V>(&mut self, mut visitor: V) -> Result<V::Value, DecodeError>
        where V: de::Visitor,
    {
        if self.toml.is_none() {
            let iter = None::<i32>.into_iter();
            let e = visitor.visit_seq(de::value::SeqDeserializer::new(iter, 0));
            e.map_err(|e| se2toml(e, "array"))
        } else {
            self.visit(visitor)
        }
    }
}

struct SeqDeserializer<'a, I> {
    iter: I,
    len: usize,
    toml: &'a mut Option<Value>,
}

impl<'a, I> SeqDeserializer<'a, I> where I: Iterator<Item=Value> {
    fn new(iter: I, len: usize, toml: &'a mut Option<Value>) -> Self {
        SeqDeserializer {
            iter: iter,
            len: len,
            toml: toml,
        }
    }

    fn put_value_back(&mut self, v: Value) {
        *self.toml = self.toml.take().or(Some(Value::Array(Vec::new())));
        match self.toml.as_mut().unwrap() {
            &mut Value::Array(ref mut a) => {
                a.push(v);
            },
            _ => unreachable!(),
        }
    }
}

impl<'a, I> de::Deserializer for SeqDeserializer<'a, I>
    where I: Iterator<Item=Value>,
{
    type Error = DecodeError;

    fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, DecodeError>
        where V: de::Visitor,
    {
        visitor.visit_seq(self)
    }
}

impl<'a, I> de::SeqVisitor for SeqDeserializer<'a, I>
    where I: Iterator<Item=Value>
{
    type Error = DecodeError;

    fn visit<V>(&mut self) -> Result<Option<V>, DecodeError>
        where V: de::Deserialize
    {
        match self.iter.next() {
            Some(value) => {
                self.len -= 1;
                let mut de = Decoder::new(value);
                let v = try!(de::Deserialize::deserialize(&mut de));
                if let Some(t) = de.toml {
                    self.put_value_back(t);
                }
                Ok(Some(v))
            }
            None => Ok(None),
        }
    }

    fn end(&mut self) -> Result<(), DecodeError> {
        if self.len == 0 {
            Ok(())
        } else {
            Err(de::Error::end_of_stream_error())
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.len, Some(self.len))
    }
}

impl de::Error for DecodeError {
    fn syntax_error() -> DecodeError {
        DecodeError { field: None, kind: DecodeErrorKind::SyntaxError }
    }
    fn end_of_stream_error() -> DecodeError {
        DecodeError { field: None, kind: DecodeErrorKind::EndOfStream }
    }
    fn missing_field_error(name: &'static str) -> DecodeError {
        DecodeError {
            field: Some(name.to_string()),
            kind: DecodeErrorKind::ExpectedField(None),
        }
    }
    fn unknown_field_error(name: &str) -> DecodeError {
        DecodeError {
            field: Some(name.to_string()),
            kind: DecodeErrorKind::UnknownField,
        }
    }
}

impl<'a, I> MapVisitor<'a, I> {
    fn put_value_back(&mut self, v: Value) {
        *self.toml = self.toml.take().or_else(|| {
            Some(Value::Table(BTreeMap::new()))
        });
        match self.toml.as_mut().unwrap() {
            &mut Value::Table(ref mut t) => {
                t.insert(self.key.take().unwrap(), v);
            },
            _ => unreachable!(),
        }
    }
}

impl<'a, I> de::MapVisitor for MapVisitor<'a, I>
    where I: Iterator<Item=(String, Value)>
{
    type Error = DecodeError;

    fn visit_key<K>(&mut self) -> Result<Option<K>, DecodeError>
        where K: de::Deserialize
    {
        while let Some((k, v)) = self.iter.next() {
            self.key = Some(k.clone());
            let mut dec = Decoder::new(Value::String(k));
            match de::Deserialize::deserialize(&mut dec) {
                Ok(val) => {
                    self.value = Some(v);
                    return Ok(Some(val))
                }

                // If this was an unknown field, then we put the toml value
                // back into the map and keep going.
                Err(DecodeError {kind: DecodeErrorKind::UnknownField, ..}) => {
                    self.put_value_back(v);
                }
                Err(e) => return Err(e),
            }
        }
        Ok(None)
    }

    fn visit_value<V>(&mut self) -> Result<V, DecodeError>
        where V: de::Deserialize
    {
        match self.value.take() {
            Some(t) => {
                let mut dec = Decoder::new(t);
                let v = try!(de::Deserialize::deserialize(&mut dec));
                if let Some(t) = dec.toml {
                    self.put_value_back(t);
                }
                Ok(v)
            },
            None => Err(de::Error::end_of_stream_error())
        }
    }

    fn end(&mut self) -> Result<(), DecodeError> {
        Ok(())
    }

    fn missing_field<V>(&mut self, field_name: &'static str)
                        -> Result<V, DecodeError> where V: de::Deserialize {
        // See if the type can deserialize from a unit.
        match de::Deserialize::deserialize(&mut UnitDeserializer) {
            Err(DecodeError {
                kind: DecodeErrorKind::SyntaxError,
                field,
            }) => Err(DecodeError {
                field: field.or(Some(field_name.to_string())),
                kind: DecodeErrorKind::ExpectedField(None),
            }),
            v => v,
        }
    }
}

struct UnitDeserializer;

impl de::Deserializer for UnitDeserializer {
    type Error = DecodeError;

    fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, DecodeError>
        where V: de::Visitor,
    {
        visitor.visit_unit()
    }

    fn visit_option<V>(&mut self, mut visitor: V) -> Result<V::Value, DecodeError>
        where V: de::Visitor,
    {
        visitor.visit_none()
    }
}

// Based on https://github.com/serde-rs/serde/blob/199ed417bd6afc2071d17759b8c7e0ab8d0ba4cc/serde_json/src/value.rs#L265
impl de::Deserialize for Value {
    fn deserialize<D>(deserializer: &mut D) -> Result<Value, D::Error> {
        struct ValueVisitor;

        impl de::Visitor for ValueVisitor {
            type Value = Value;

            fn visit_bool<E>(&mut self, value: bool) -> Result<Value, E> {
                Ok(Value::Boolean(value))
            }

            fn visit_i64<E>(&mut self, value: i64) -> Result<Value, E> {
                Ok(Value::Integer(value))
            }

            fn visit_f64<E>(&mut self, value: f64) -> Result<Value, E> {
                Ok(Value::Float(value))
            }

            fn visit_str<E>(&mut self, value: &str) -> Result<Value, E> {
                Ok(Value::String(value.into()))
            }

            fn visit_string<E>(&mut self, value: String) -> Result<Value, E> {
                Ok(Value::String(value))
            }

            fn visit_seq<V>(&mut self, visitor: V) -> Result<Value, V::Error> where V: de::SeqVisitor {
                let values = try!(de::impls::VecVisitor::new().visit_seq(visitor));
                Ok(Value::Array(values))
            }

            fn visit_map<V>(&mut self, visitor: V) -> Result<Value, V::Error> where V: de::MapVisitor {
                let values = try!(de::impls::BTreeMapVisitor::new().visit_map(visitor));
                Ok(Value::Table(values))
            }
        }
    }
}
<commit_msg>it helps to actually build with serde enabled<commit_after>use serde::de;
use Value;
use super::{Decoder, DecodeError, DecodeErrorKind};
use std::collections::BTreeMap;

struct MapVisitor<'a, I> {
    iter: I,
    toml: &'a mut Option<Value>,
    key: Option<String>,
    value: Option<Value>,
}

fn se2toml(err: de::value::Error, ty: &'static str) -> DecodeError {
    match err {
        de::value::Error::SyntaxError => de::Error::syntax_error(),
        de::value::Error::EndOfStreamError => de::Error::end_of_stream_error(),
        de::value::Error::MissingFieldError(s) => {
            DecodeError {
                field: Some(s.to_string()),
                kind: DecodeErrorKind::ExpectedField(Some(ty)),
            }
        },
        de::value::Error::UnknownFieldError(s) => {
            DecodeError {
                field: Some(s.to_string()),
                kind: DecodeErrorKind::UnknownField,
            }
        },
    }
}

impl de::Deserializer for Decoder {
    type Error = DecodeError;

    fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, DecodeError>
        where V: de::Visitor
    {
        match self.toml.take() {
            Some(Value::String(s)) => {
                visitor.visit_string(s).map_err(|e| se2toml(e, "string"))
            }
            Some(Value::Integer(i)) => {
                visitor.visit_i64(i).map_err(|e| se2toml(e, "integer"))
            }
            Some(Value::Float(f)) => {
                visitor.visit_f64(f).map_err(|e| se2toml(e, "float"))
            }
            Some(Value::Boolean(b)) => {
                visitor.visit_bool(b).map_err(|e| se2toml(e, "bool"))
            }
            Some(Value::Datetime(s)) => {
                visitor.visit_string(s).map_err(|e| se2toml(e, "date"))
            }
            Some(Value::Array(a)) => {
                let len = a.len();
                let iter = a.into_iter();
                visitor.visit_seq(SeqDeserializer::new(iter, len, &mut self.toml))
            }
            Some(Value::Table(t)) => {
                visitor.visit_map(MapVisitor {
                    iter: t.into_iter(),
                    toml: &mut self.toml,
                    key: None,
                    value: None,
                })
            }
            None => Err(de::Error::end_of_stream_error()),
        }
    }

    fn visit_option<V>(&mut self, mut visitor: V) -> Result<V::Value, DecodeError>
        where V: de::Visitor
    {
        if self.toml.is_none() {
            visitor.visit_none()
        } else {
            visitor.visit_some(self)
        }
    }

    fn visit_seq<V>(&mut self, mut visitor: V) -> Result<V::Value, DecodeError>
        where V: de::Visitor,
    {
        if self.toml.is_none() {
            let iter = None::<i32>.into_iter();
            let e = visitor.visit_seq(de::value::SeqDeserializer::new(iter, 0));
            e.map_err(|e| se2toml(e, "array"))
        } else {
            self.visit(visitor)
        }
    }
}

struct SeqDeserializer<'a, I> {
    iter: I,
    len: usize,
    toml: &'a mut Option<Value>,
}

impl<'a, I> SeqDeserializer<'a, I> where I: Iterator<Item=Value> {
    fn new(iter: I, len: usize, toml: &'a mut Option<Value>) -> Self {
        SeqDeserializer {
            iter: iter,
            len: len,
            toml: toml,
        }
    }

    fn put_value_back(&mut self, v: Value) {
        *self.toml = self.toml.take().or(Some(Value::Array(Vec::new())));
        match self.toml.as_mut().unwrap() {
            &mut Value::Array(ref mut a) => {
                a.push(v);
            },
            _ => unreachable!(),
        }
    }
}

impl<'a, I> de::Deserializer for SeqDeserializer<'a, I>
    where I: Iterator<Item=Value>,
{
    type Error = DecodeError;

    fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, DecodeError>
        where V: de::Visitor,
    {
        visitor.visit_seq(self)
    }
}

impl<'a, I> de::SeqVisitor for SeqDeserializer<'a, I>
    where I: Iterator<Item=Value>
{
    type Error = DecodeError;

    fn visit<V>(&mut self) -> Result<Option<V>, DecodeError>
        where V: de::Deserialize
    {
        match self.iter.next() {
            Some(value) => {
                self.len -= 1;
                let mut de = Decoder::new(value);
                let v = try!(de::Deserialize::deserialize(&mut de));
                if let Some(t) = de.toml {
                    self.put_value_back(t);
                }
                Ok(Some(v))
            }
            None => Ok(None),
        }
    }

    fn end(&mut self) -> Result<(), DecodeError> {
        if self.len == 0 {
            Ok(())
        } else {
            Err(de::Error::end_of_stream_error())
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.len, Some(self.len))
    }
}

impl de::Error for DecodeError {
    fn syntax_error() -> DecodeError {
        DecodeError { field: None, kind: DecodeErrorKind::SyntaxError }
    }
    fn end_of_stream_error() -> DecodeError {
        DecodeError { field: None, kind: DecodeErrorKind::EndOfStream }
    }
    fn missing_field_error(name: &'static str) -> DecodeError {
        DecodeError {
            field: Some(name.to_string()),
            kind: DecodeErrorKind::ExpectedField(None),
        }
    }
    fn unknown_field_error(name: &str) -> DecodeError {
        DecodeError {
            field: Some(name.to_string()),
            kind: DecodeErrorKind::UnknownField,
        }
    }
}

impl<'a, I> MapVisitor<'a, I> {
    fn put_value_back(&mut self, v: Value) {
        *self.toml = self.toml.take().or_else(|| {
            Some(Value::Table(BTreeMap::new()))
        });
        match self.toml.as_mut().unwrap() {
            &mut Value::Table(ref mut t) => {
                t.insert(self.key.take().unwrap(), v);
            },
            _ => unreachable!(),
        }
    }
}

impl<'a, I> de::MapVisitor for MapVisitor<'a, I>
    where I: Iterator<Item=(String, Value)>
{
    type Error = DecodeError;

    fn visit_key<K>(&mut self) -> Result<Option<K>, DecodeError>
        where K: de::Deserialize
    {
        while let Some((k, v)) = self.iter.next() {
            self.key = Some(k.clone());
            let mut dec = Decoder::new(Value::String(k));
            match de::Deserialize::deserialize(&mut dec) {
                Ok(val) => {
                    self.value = Some(v);
                    return Ok(Some(val))
                }

                // If this was an unknown field, then we put the toml value
                // back into the map and keep going.
                Err(DecodeError {kind: DecodeErrorKind::UnknownField, ..}) => {
                    self.put_value_back(v);
                }
                Err(e) => return Err(e),
            }
        }
        Ok(None)
    }

    fn visit_value<V>(&mut self) -> Result<V, DecodeError>
        where V: de::Deserialize
    {
        match self.value.take() {
            Some(t) => {
                let mut dec = Decoder::new(t);
                let v = try!(de::Deserialize::deserialize(&mut dec));
                if let Some(t) = dec.toml {
                    self.put_value_back(t);
                }
                Ok(v)
            },
            None => Err(de::Error::end_of_stream_error())
        }
    }

    fn end(&mut self) -> Result<(), DecodeError> {
        Ok(())
    }

    fn missing_field<V>(&mut self, field_name: &'static str)
                        -> Result<V, DecodeError> where V: de::Deserialize {
        // See if the type can deserialize from a unit.
        match de::Deserialize::deserialize(&mut UnitDeserializer) {
            Err(DecodeError {
                kind: DecodeErrorKind::SyntaxError,
                field,
            }) => Err(DecodeError {
                field: field.or(Some(field_name.to_string())),
                kind: DecodeErrorKind::ExpectedField(None),
            }),
            v => v,
        }
    }
}

struct UnitDeserializer;

impl de::Deserializer for UnitDeserializer {
    type Error = DecodeError;

    fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, DecodeError>
        where V: de::Visitor,
    {
        visitor.visit_unit()
    }

    fn visit_option<V>(&mut self, mut visitor: V) -> Result<V::Value, DecodeError>
        where V: de::Visitor,
    {
        visitor.visit_none()
    }
}

// Based on https://github.com/serde-rs/serde/blob/199ed417bd6afc2071d17759b8c7e0ab8d0ba4cc/serde_json/src/value.rs#L265
impl de::Deserialize for Value {
    fn deserialize<D>(deserializer: &mut D) -> Result<Value, D::Error> where D: de::Deserializer {
        struct ValueVisitor;

        impl de::Visitor for ValueVisitor {
            type Value = Value;

            fn visit_bool<E>(&mut self, value: bool) -> Result<Value, E> {
                Ok(Value::Boolean(value))
            }

            fn visit_i64<E>(&mut self, value: i64) -> Result<Value, E> {
                Ok(Value::Integer(value))
            }

            fn visit_f64<E>(&mut self, value: f64) -> Result<Value, E> {
                Ok(Value::Float(value))
            }

            fn visit_str<E>(&mut self, value: &str) -> Result<Value, E> {
                Ok(Value::String(value.into()))
            }

            fn visit_string<E>(&mut self, value: String) -> Result<Value, E> {
                Ok(Value::String(value))
            }

            fn visit_seq<V>(&mut self, visitor: V) -> Result<Value, V::Error> where V: de::SeqVisitor {
                let values = try!(de::impls::VecVisitor::new().visit_seq(visitor));
                Ok(Value::Array(values))
            }

            fn visit_map<V>(&mut self, visitor: V) -> Result<Value, V::Error> where V: de::MapVisitor {
                let values = try!(de::impls::BTreeMapVisitor::new().visit_map(visitor));
                Ok(Value::Table(values))
            }
        }

        deserializer.visit(ValueVisitor)
    }
}
<|endoftext|>


<commit_before>pub trait Stack {
  fn top(&mut self) -> *mut u8;
  fn limit(&self) -> *const u8;
}

pub trait StackSource {
  type Output: Stack;
  fn get_stack(size: usize) -> Self::Output;
}
<commit_msg>document Stack and StackSource<commit_after>//! Traits for stacks.

/// A trait for objects that hold ownership of a stack.
pub trait Stack {
  /// Returns the top of the stack.
  /// On all modern architectures, the stack grows downwards,
  /// so this is the highest address.
  fn top(&mut self) -> *mut u8;
  /// Returns the bottom of the stack.
  /// On all modern architectures, the stack grows downwards,
  /// so this is the lowest address.
  fn limit(&self) -> *const u8;
}

/// A trait for objects that provide stacks of arbitrary size.
pub trait StackSource {
  type Output: Stack;
  fn get_stack(size: usize) -> Self::Output;
}
<|endoftext|>


<commit_before>extern crate rand;

const ROWS: i8 = 9;
const COLS: i8 = 12;
const TILES: i8 = 108;
const PLAYERS: i8 = 4;

#[derive(RustcDecodable, RustcEncodable)]
pub struct Game {
    players: Vec<Player>,
    board: Board,
    turn: PlayerId,
    merge_decision: Option<PlayerId>
}

#[derive(RustcDecodable, RustcEncodable)]
struct Player {
    id: PlayerId,
    money: i32,
    shares: PlayerShares,
    tiles: Vec<Tile>
}

type PlayerId = i8;

#[derive(RustcDecodable, RustcEncodable)]
struct PlayerShares {
    luxor: i8,
    tower: i8,
    american: i8,
    festival: i8,
    worldwide: i8,
    continental: i8,
    imperial: i8
}

#[derive(RustcDecodable, RustcEncodable, Clone, Debug)]
struct Tile { row: i8, col: i8 }

#[derive(RustcDecodable, RustcEncodable)]
struct Board {
    slots: Vec<Vec<Slot>>
}

#[derive(RustcDecodable, RustcEncodable)]
struct Slot {
    hotel: Option<Hotel>
}

enum Action {
    PlaceTile,
    HandleMergeStocks,
    BuyStocks,
    DrawTile,
    EndGame
}

pub struct PlaceTile {
    player: PlayerId,
    tile: Tile
}

pub struct HandleMergeStocks {
    hold: i8,
    sell: i8,
    trade: i8
}

type BuyStocks = PlayerShares;

#[derive(RustcDecodable, RustcEncodable)]
enum Hotel { Luxor, Tower, American, Festival, Worldwide, Continental, Imperial }

fn empty_shares() -> PlayerShares {
    PlayerShares { luxor: 0, tower: 0, american: 0, festival: 0, worldwide: 0, continental: 0, imperial: 0 }
}

fn new_player(id: PlayerId, tiles: Vec<Tile>) -> Player {
    Player { id: id, money: 6000, shares: empty_shares(), tiles: tiles }
}

fn choose_tiles(tiles: Vec<Tile>, count: usize) -> Vec<Tile> {
    let mut remaining_tiles = tiles;
    let mut random_tiles = Vec::new();
    for _ in 0..count {
        let random_index = (rand::random::<i8>() as usize) % remaining_tiles.len();
        random_tiles.push(remaining_tiles.remove(random_index));
    }
    random_tiles
}

pub fn initial_state() -> Game {
    let slots = (0..COLS)
        .map(|_| (0..ROWS).map(|_| Slot { hotel: None } ).collect() )
        .collect();
    let tiles = (0..TILES).map(|i| Tile { row: i / COLS, col: i % ROWS }).collect();
    let mut chosen_tiles = choose_tiles(tiles, 6*PLAYERS as usize);
    let tiles1 = chosen_tiles.split_off(18);
    let tiles2 = chosen_tiles.split_off(12);
    let tiles3 = chosen_tiles.split_off(6);
    let tiles4 = chosen_tiles;
    let players = vec![
        new_player(1, tiles1),
        new_player(2, tiles2),
        new_player(3, tiles3),
        new_player(4, tiles4)];
    Game {
        board: Board { slots: slots },
        players: players,
        turn: 1,
        merge_decision: None
    }
}

#[test]
fn players_start_with_six_tiles() {
    let state = initial_state();
    for player in state.players {
        assert_eq!(player.tiles.len(), 6);
    }
}

#[test]
fn players_start_with_6000_in_cash() {
    let state = initial_state();
    for player in state.players {
        assert_eq!(player.money, 6000);
    }
}

#[test]
fn players_start_with_zero_shares() {
    let state = initial_state();
    for player in state.players {
        assert_eq!(player.shares.luxor, 0);
        assert_eq!(player.shares.tower, 0);
        assert_eq!(player.shares.american, 0);
        assert_eq!(player.shares.festival, 0);
        assert_eq!(player.shares.worldwide, 0);
        assert_eq!(player.shares.continental, 0);
        assert_eq!(player.shares.imperial, 0);
    }
}
<commit_msg>Place four tiles on board initially - failing test<commit_after>extern crate rand;

const ROWS: i8 = 9;
const COLS: i8 = 12;
const TILES: i8 = 108;
const PLAYERS: i8 = 4;

#[derive(RustcDecodable, RustcEncodable)]
pub struct Game {
    players: Vec<Player>,
    board: Board,
    turn: PlayerId,
    merge_decision: Option<PlayerId>
}

#[derive(RustcDecodable, RustcEncodable)]
struct Player {
    id: PlayerId,
    money: i32,
    shares: PlayerShares,
    tiles: Vec<Tile>
}

type PlayerId = i8;

#[derive(RustcDecodable, RustcEncodable)]
struct PlayerShares {
    luxor: i8,
    tower: i8,
    american: i8,
    festival: i8,
    worldwide: i8,
    continental: i8,
    imperial: i8
}

#[derive(RustcDecodable, RustcEncodable, Clone, Debug)]
struct Tile { row: i8, col: i8 }

#[derive(RustcDecodable, RustcEncodable)]
struct Board {
    slots: Vec<Slot>
}

#[derive(RustcDecodable, RustcEncodable)]
struct Slot {
    row: i8,
    col: i8,
    has_tile: bool,
    hotel: Option<Hotel>
}

enum Action {
    PlaceTile,
    HandleMergeStocks,
    BuyStocks,
    DrawTile,
    EndGame
}

pub struct PlaceTile {
    player: PlayerId,
    tile: Tile
}

pub struct HandleMergeStocks {
    hold: i8,
    sell: i8,
    trade: i8
}

type BuyStocks = PlayerShares;

#[derive(RustcDecodable, RustcEncodable)]
enum Hotel { Luxor, Tower, American, Festival, Worldwide, Continental, Imperial }

fn empty_shares() -> PlayerShares {
    PlayerShares { luxor: 0, tower: 0, american: 0, festival: 0, worldwide: 0, continental: 0, imperial: 0 }
}

fn new_player(id: PlayerId, tiles: Vec<Tile>) -> Player {
    Player { id: id, money: 6000, shares: empty_shares(), tiles: tiles }
}

fn choose_tiles(tiles: Vec<Tile>, count: usize) -> Vec<Tile> {
    let mut remaining_tiles = tiles;
    let mut random_tiles = Vec::new();
    for _ in 0..count {
        let random_index = (rand::random::<i8>() as usize) % remaining_tiles.len();
        random_tiles.push(remaining_tiles.remove(random_index));
    }
    random_tiles
}

pub fn initial_state() -> Game {
    let slots: Vec<Slot> = (0..COLS)
        .flat_map(|col| {
            let rows = 0..ROWS;
            let res: Vec<Slot> = rows.map(|row| Slot { row: row, col: col, hotel: None, has_tile: false } ).collect();
            res
        }).collect();
    let tiles = (0..TILES).map(|i| Tile { row: i / COLS, col: i % ROWS }).collect();
    let mut chosen_tiles = choose_tiles(tiles, 6*PLAYERS as usize);
    let tiles1 = chosen_tiles.split_off(18);
    let tiles2 = chosen_tiles.split_off(12);
    let tiles3 = chosen_tiles.split_off(6);
    let tiles4 = chosen_tiles;
    let players = vec![
        new_player(1, tiles1),
        new_player(2, tiles2),
        new_player(3, tiles3),
        new_player(4, tiles4)];
    Game {
        board: Board { slots: slots },
        players: players,
        turn: 1,
        merge_decision: None
    }
}

#[test]
fn players_start_with_six_tiles() {
    let state = initial_state();
    for player in state.players {
        assert_eq!(player.tiles.len(), 6);
    }
}

#[test]
fn players_start_with_6000_in_cash() {
    let state = initial_state();
    for player in state.players {
        assert_eq!(player.money, 6000);
    }
}

#[test]
fn players_start_with_zero_shares() {
    let state = initial_state();
    for player in state.players {
        assert_eq!(player.shares.luxor, 0);
        assert_eq!(player.shares.tower, 0);
        assert_eq!(player.shares.american, 0);
        assert_eq!(player.shares.festival, 0);
        assert_eq!(player.shares.worldwide, 0);
        assert_eq!(player.shares.continental, 0);
        assert_eq!(player.shares.imperial, 0);
    }
}

#[test]
fn game_starts_with_four_placed_tiles() {
    let state = initial_state();
    let board_tiles = state.board.slots.iter().filter(|s| s.has_tile).count();
    assert_eq!(board_tiles, 4)
}
<|endoftext|>


<commit_before>extern crate walkdir;
extern crate chrono;

use std::path;
use self::walkdir::{WalkDir, DirEntry, Error as WalkDirError};
use std::fs::File;
use std::io::BufReader;
use std::io::BufRead;
use self::chrono::{DateTime, UTC};
use std::collections::HashMap;
use std::error::Error;

struct ELBLogEntry {
    time_stamp: DateTime<UTC>,
    elb_name: String,
    client_address: String,
    backend_address: String,
    request_processing_time: f32,
    backend_processing_time: String,
    response_processing_time: String,
    elb_status_code: String,
    backend_status_code: String,
    received_bytes: String,
    sent_bytes: String,
    request_method: String,
    request_url: String,
    request_http_version: String
}

pub fn file_list(dir: &path::Path, filenames: &mut Vec<DirEntry>) -> Result<usize, WalkDirError> {
    for entry in WalkDir::new(dir).min_depth(1) {
        match entry {
            Err(err) => return Err(err),
            Ok(entry) => filenames.push(entry),
        }
    }
    Ok(filenames.len())
}

pub fn process_files(runtime_context: &::RuntimeContext, filenames: Vec<walkdir::DirEntry>) -> usize {
    let debug = runtime_context.debug;
    let mut record_count = 0;
    for filename in filenames {
        debug!(debug, "Processing file {}.", filename.path().display());
        match File::open(filename.path()) {
            Ok(file) => {
                let buffered_file = BufReader::new(&file);
                let recs: Vec<_> = buffered_file.lines()
                    .map(|x| {
                        parse_line(&(x.unwrap()))
                    })
                    .collect();
                record_count += recs.len();
                debug!(debug, "Found {} records in file {}.", recs.len(), filename.path().display());
            },
            Err(e) => {
                println!("ERROR: {}", e);
            }
        }
    }

    record_count
}

#[derive(Debug)]
struct ParsingErrors;

fn parse_line(line: &String) -> Result<Box<ELBLogEntry>, HashMap<String, String>> {
    let split_line: Vec<_> = line.split(" ").collect();
    let mut errors = HashMap::new();

    let ts = match split_line[0].parse() {
        Ok(parsed_ts) => Some(parsed_ts),

        Err(e) => {
            errors.insert("timestamp".to_string(), "timestamp_error".to_string());
            None
        }
    };

    if errors.is_empty() {
        let elb_log_entry = ELBLogEntry {
            time_stamp: ts.unwrap(),
            elb_name: split_line[1].to_string(),
            client_address: split_line[2].to_string(),
            backend_address: split_line[3].to_string(),
            request_processing_time: split_line[4].parse::<f32>().unwrap(),  //TODO This needs to be error checked once I figure out how to handle errors.
            backend_processing_time: split_line[5].to_string(),
            response_processing_time: split_line[6].to_string(),
            elb_status_code: split_line[7].to_string(),
            backend_status_code: split_line[8].to_string(),
            received_bytes: split_line[9].to_string(),
            sent_bytes: split_line[10].to_string(),
            request_method: split_line[11].trim_matches('"').to_string(),
            request_url: split_line[12].to_string(),
            request_http_version: split_line[13].trim_matches('"').to_string()
        };

        Ok(Box::new(elb_log_entry))
    } else {
        Err(errors)
    }
}

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

    const TEST_LINE: &'static str = "2015-08-15T23:43:05.302180Z elb-name 172.16.1.6:54814 \
    172.16.1.5:9000 0.000039 0.145507 0.00003 200 200 0 7582 \
    \"GET http://some.domain.com:80/path0/path1?param0=p0&param1=p1 HTTP/1.1\" \
    ";

    #[test]
	fn parse_line_returns_a_log_entry_with_the_request_http_version() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.request_http_version, "HTTP/1.1")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_request_url() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.request_url, "http://some.domain.com:80/path0/path1?param0=p0&param1=p1")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_request_method() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.request_method, "GET")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_sent_bytes() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.sent_bytes, "7582")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_received_bytes() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.received_bytes, "0")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_backend_status_code() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.backend_status_code, "200")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_elb_status_code() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.elb_status_code, "200")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_response_processing_time() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.response_processing_time, "0.00003")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_backend_processing_time() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.backend_processing_time, "0.145507")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_request_processing_time() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.request_processing_time, 0.000039)
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_backend_address() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.backend_address, "172.16.1.5:9000")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_client_address() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.client_address, "172.16.1.6:54814")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_time_stamp() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(format!("{:?}", elb_log_entry.time_stamp), "2015-08-15T23:43:05.302180Z")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_elb_name() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.elb_name, "elb-name")
	}
}
<commit_msg>Made the timestamp property name a const string.<commit_after>extern crate walkdir;
extern crate chrono;

use std::path;
use self::walkdir::{WalkDir, DirEntry, Error as WalkDirError};
use std::fs::File;
use std::io::BufReader;
use std::io::BufRead;
use self::chrono::{DateTime, UTC};
use std::collections::HashMap;
use std::error::Error;

struct ELBLogEntry {
    timestamp: DateTime<UTC>,
    elb_name: String,
    client_address: String,
    backend_address: String,
    request_processing_time: f32,
    backend_processing_time: String,
    response_processing_time: String,
    elb_status_code: String,
    backend_status_code: String,
    received_bytes: String,
    sent_bytes: String,
    request_method: String,
    request_url: String,
    request_http_version: String
}

pub fn file_list(dir: &path::Path, filenames: &mut Vec<DirEntry>) -> Result<usize, WalkDirError> {
    for entry in WalkDir::new(dir).min_depth(1) {
        match entry {
            Err(err) => return Err(err),
            Ok(entry) => filenames.push(entry),
        }
    }
    Ok(filenames.len())
}

pub fn process_files(runtime_context: &::RuntimeContext, filenames: Vec<walkdir::DirEntry>) -> usize {
    let debug = runtime_context.debug;
    let mut record_count = 0;
    for filename in filenames {
        debug!(debug, "Processing file {}.", filename.path().display());
        match File::open(filename.path()) {
            Ok(file) => {
                let buffered_file = BufReader::new(&file);
                let recs: Vec<_> = buffered_file.lines()
                    .map(|x| {
                        parse_line(&(x.unwrap()))
                    })
                    .collect();
                record_count += recs.len();
                debug!(debug, "Found {} records in file {}.", recs.len(), filename.path().display());
            },
            Err(e) => {
                println!("ERROR: {}", e);
            }
        }
    }

    record_count
}

#[derive(Debug)]
struct ParsingError{
    property: &'static str,
}

const TIMESTAMP: &'static str = "timestamp";

fn parse_line(line: &String) -> Result<Box<ELBLogEntry>, Vec<ParsingError>> {
    let split_line: Vec<_> = line.split(" ").collect();
    let mut errors = Vec::new();

    let ts = match split_line[0].parse() {
        Ok(parsed_ts) => Some(parsed_ts),

        Err(e) => {
            errors.push(
                ParsingError {
                    property: TIMESTAMP
                }
            );
            None
        }
    };

    if errors.is_empty() {
        let elb_log_entry = ELBLogEntry {
            timestamp: ts.unwrap(),
            elb_name: split_line[1].to_string(),
            client_address: split_line[2].to_string(),
            backend_address: split_line[3].to_string(),
            request_processing_time: split_line[4].parse::<f32>().unwrap(),  //TODO This needs to be error checked once I figure out how to handle errors.
            backend_processing_time: split_line[5].to_string(),
            response_processing_time: split_line[6].to_string(),
            elb_status_code: split_line[7].to_string(),
            backend_status_code: split_line[8].to_string(),
            received_bytes: split_line[9].to_string(),
            sent_bytes: split_line[10].to_string(),
            request_method: split_line[11].trim_matches('"').to_string(),
            request_url: split_line[12].to_string(),
            request_http_version: split_line[13].trim_matches('"').to_string()
        };

        Ok(Box::new(elb_log_entry))
    } else {
        Err(errors)
    }
}

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

    const TEST_LINE: &'static str = "2015-08-15T23:43:05.302180Z elb-name 172.16.1.6:54814 \
    172.16.1.5:9000 0.000039 0.145507 0.00003 200 200 0 7582 \
    \"GET http://some.domain.com:80/path0/path1?param0=p0&param1=p1 HTTP/1.1\" \
    ";

    #[test]
	fn parse_line_returns_a_log_entry_with_the_request_http_version() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.request_http_version, "HTTP/1.1")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_request_url() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.request_url, "http://some.domain.com:80/path0/path1?param0=p0&param1=p1")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_request_method() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.request_method, "GET")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_sent_bytes() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.sent_bytes, "7582")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_received_bytes() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.received_bytes, "0")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_backend_status_code() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.backend_status_code, "200")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_elb_status_code() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.elb_status_code, "200")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_response_processing_time() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.response_processing_time, "0.00003")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_backend_processing_time() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.backend_processing_time, "0.145507")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_request_processing_time() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.request_processing_time, 0.000039)
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_backend_address() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.backend_address, "172.16.1.5:9000")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_client_address() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.client_address, "172.16.1.6:54814")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_timestamp() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(format!("{:?}", elb_log_entry.timestamp), "2015-08-15T23:43:05.302180Z")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_elb_name() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.elb_name, "elb-name")
	}
}
<|endoftext|>