<commit_before>#[cfg(feature = "arbitrary")]
use quickcheck::{Arbitrary, Gen};
#[cfg(feature = "arbitrary")]
use core::storage::Owned;

use std::ops::Neg;
use num::Zero;
use rand::{Rand, Rng};
use alga::general::Real;

use core::{MatrixN, Unit, Vector, Vector1, Vector3, VectorN};
use core::dimension::{U1, U2, U3};
use core::storage::Storage;

use geometry::{Rotation2, Rotation3, UnitComplex};

/*
 *
 * 2D Rotation matrix.
 *
 */
impl<N: Real> Rotation2<N> {
    /// Builds a 2 dimensional rotation matrix from an angle in radian.
    pub fn new(angle: N) -> Self {
        let (sia, coa) = angle.sin_cos();
        Self::from_matrix_unchecked(MatrixN::<N, U2>::new(coa, -sia, sia, coa))
    }

    /// Builds a 2 dimensional rotation matrix from an angle in radian wrapped in a 1-dimensional vector.
    ///
    /// Equivalent to `Self::new(axisangle[0])`.
    #[inline]
    pub fn from_scaled_axis<SB: Storage<N, U1>>(axisangle: Vector<N, U1, SB>) -> Self {
        Self::new(axisangle[0])
    }

    /// The rotation matrix required to align `a` and `b` but with its angl.
    ///
    /// This is the rotation `R` such that `(R * a).angle(b) == 0 && (R * a).dot(b).is_positive()`.
    #[inline]
    pub fn rotation_between<SB, SC>(a: &Vector<N, U2, SB>, b: &Vector<N, U2, SC>) -> Self
    where
        SB: Storage<N, U2>,
        SC: Storage<N, U2>,
    {
        ::convert(UnitComplex::rotation_between(a, b).to_rotation_matrix())
    }

    /// The smallest rotation needed to make `a` and `b` collinear and point toward the same
    /// direction, raised to the power `s`.
    #[inline]
    pub fn scaled_rotation_between<SB, SC>(
        a: &Vector<N, U2, SB>,
        b: &Vector<N, U2, SC>,
        s: N,
    ) -> Self
    where
        SB: Storage<N, U2>,
        SC: Storage<N, U2>,
    {
        ::convert(UnitComplex::scaled_rotation_between(a, b, s).to_rotation_matrix())
    }
}

impl<N: Real> Rotation2<N> {
    /// The rotation angle.
    #[inline]
    pub fn angle(&self) -> N {
        self.matrix()[(1, 0)].atan2(self.matrix()[(0, 0)])
    }

    /// The rotation angle needed to make `self` and `other` coincide.
    #[inline]
    pub fn angle_to(&self, other: &Rotation2<N>) -> N {
        self.rotation_to(other).angle()
    }

    /// The rotation matrix needed to make `self` and `other` coincide.
    ///
    /// The result is such that: `self.rotation_to(other) * self == other`.
    #[inline]
    pub fn rotation_to(&self, other: &Rotation2<N>) -> Rotation2<N> {
        other * self.inverse()
    }

    /// Raise the quaternion to a given floating power, i.e., returns the rotation with the angle
    /// of `self` multiplied by `n`.
    #[inline]
    pub fn powf(&self, n: N) -> Rotation2<N> {
        Self::new(self.angle() * n)
    }

    /// The rotation angle returned as a 1-dimensional vector.
    #[inline]
    pub fn scaled_axis(&self) -> VectorN<N, U1> {
        Vector1::new(self.angle())
    }
}

impl<N: Real + Rand> Rand for Rotation2<N> {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> Self {
        Self::new(rng.gen())
    }
}

#[cfg(feature = "arbitrary")]
impl<N: Real + Arbitrary> Arbitrary for Rotation2<N>
where
    Owned<N, U2, U2>: Send,
{
    #[inline]
    fn arbitrary<G: Gen>(g: &mut G) -> Self {
        Self::new(N::arbitrary(g))
    }
}

/*
 *
 * 3D Rotation matrix.
 *
 */
impl<N: Real> Rotation3<N> {
    /// Builds a 3 dimensional rotation matrix from an axis and an angle.
    ///
    /// # Arguments
    ///   * `axisangle` - A vector representing the rotation. Its magnitude is the amount of rotation
    ///   in radian. Its direction is the axis of rotation.
    pub fn new<SB: Storage<N, U3>>(axisangle: Vector<N, U3, SB>) -> Self {
        let axisangle = axisangle.into_owned();
        let (axis, angle) = Unit::new_and_get(axisangle);
        Self::from_axis_angle(&axis, angle)
    }

    /// Builds a 3D rotation matrix from an axis scaled by the rotation angle.
    pub fn from_scaled_axis<SB: Storage<N, U3>>(axisangle: Vector<N, U3, SB>) -> Self {
        Self::new(axisangle)
    }

    /// Builds a 3D rotation matrix from an axis and a rotation angle.
    pub fn from_axis_angle<SB>(axis: &Unit<Vector<N, U3, SB>>, angle: N) -> Self
    where
        SB: Storage<N, U3>,
    {
        if angle.is_zero() {
            Self::identity()
        } else {
            let ux = axis.as_ref()[0];
            let uy = axis.as_ref()[1];
            let uz = axis.as_ref()[2];
            let sqx = ux * ux;
            let sqy = uy * uy;
            let sqz = uz * uz;
            let (sin, cos) = angle.sin_cos();
            let one_m_cos = N::one() - cos;

            Self::from_matrix_unchecked(MatrixN::<N, U3>::new(
                (sqx + (N::one() - sqx) * cos),
                (ux * uy * one_m_cos - uz * sin),
                (ux * uz * one_m_cos + uy * sin),
                (ux * uy * one_m_cos + uz * sin),
                (sqy + (N::one() - sqy) * cos),
                (uy * uz * one_m_cos - ux * sin),
                (ux * uz * one_m_cos - uy * sin),
                (uy * uz * one_m_cos + ux * sin),
                (sqz + (N::one() - sqz) * cos),
            ))
        }
    }

    /// Creates a new rotation from Euler angles.
    ///
    /// The primitive rotations are applied in order: 1 roll − 2 pitch − 3 yaw.
    pub fn from_euler_angles(roll: N, pitch: N, yaw: N) -> Self {
        let (sr, cr) = roll.sin_cos();
        let (sp, cp) = pitch.sin_cos();
        let (sy, cy) = yaw.sin_cos();

        Self::from_matrix_unchecked(MatrixN::<N, U3>::new(
            cy * cp,
            cy * sp * sr - sy * cr,
            cy * sp * cr + sy * sr,
            sy * cp,
            sy * sp * sr + cy * cr,
            sy * sp * cr - cy * sr,
            -sp,
            cp * sr,
            cp * cr,
        ))
    }

    /// Creates Euler angles from a rotation.
    ///
    /// The angles are produced in the form (roll, yaw, pitch).
    pub fn to_euler_angles(&self) -> (N, N, N) {
        // Implementation informed by "Computing Euler angles from a rotation matrix", by Gregory G. Slabaugh
        //  http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.371.6578
        if self[(2,0)].abs() != N::one() {
            let yaw   = -self[(2,0)].asin();
            let roll  = (self[(2,1)] / yaw.cos()).atan2(self[(2,2)] / yaw.cos());
            let pitch = (self[(1,0)] / yaw.cos()).atan2(self[(0,0)] / yaw.cos());
            (roll, yaw, pitch)
        } else if self[(2,0)] == -N::one() {
            (self[(0,1)].atan2(self[(0,2)]), N::frac_pi_2(), N::zero())
        } else {
            (-self[(0,1)].atan2(-self[(0,2)]), -N::frac_pi_2(), N::zero())
        }
    }

    /// Creates a rotation that corresponds to the local frame of an observer standing at the
    /// origin and looking toward `dir`.
    ///
    /// It maps the view direction `dir` to the positive `z` axis.
    ///
    /// # Arguments
    ///   * dir - The look direction, that is, direction the matrix `z` axis will be aligned with.
    ///   * up - The vertical direction. The only requirement of this parameter is to not be
    ///   collinear
    ///   to `dir`. Non-collinearity is not checked.
    #[inline]
    pub fn new_observer_frame<SB, SC>(dir: &Vector<N, U3, SB>, up: &Vector<N, U3, SC>) -> Self
    where
        SB: Storage<N, U3>,
        SC: Storage<N, U3>,
    {
        let zaxis = dir.normalize();
        let xaxis = up.cross(&zaxis).normalize();
        let yaxis = zaxis.cross(&xaxis).normalize();

        Self::from_matrix_unchecked(MatrixN::<N, U3>::new(
            xaxis.x,
            yaxis.x,
            zaxis.x,
            xaxis.y,
            yaxis.y,
            zaxis.y,
            xaxis.z,
            yaxis.z,
            zaxis.z,
        ))
    }

    /// Builds a right-handed look-at view matrix without translation.
    ///
    /// This conforms to the common notion of right handed look-at matrix from the computer
    /// graphics community.
    ///
    /// # Arguments
    ///   * eye - The eye position.
    ///   * target - The target position.
    ///   * up - A vector approximately aligned with required the vertical axis. The only
    ///   requirement of this parameter is to not be collinear to `target - eye`.
    #[inline]
    pub fn look_at_rh<SB, SC>(dir: &Vector<N, U3, SB>, up: &Vector<N, U3, SC>) -> Self
    where
        SB: Storage<N, U3>,
        SC: Storage<N, U3>,
    {
        Self::new_observer_frame(&dir.neg(), up).inverse()
    }

    /// Builds a left-handed look-at view matrix without translation.
    ///
    /// This conforms to the common notion of left handed look-at matrix from the computer
    /// graphics community.
    ///
    /// # Arguments
    ///   * eye - The eye position.
    ///   * target - The target position.
    ///   * up - A vector approximately aligned with required the vertical axis. The only
    ///   requirement of this parameter is to not be collinear to `target - eye`.
    #[inline]
    pub fn look_at_lh<SB, SC>(dir: &Vector<N, U3, SB>, up: &Vector<N, U3, SC>) -> Self
    where
        SB: Storage<N, U3>,
        SC: Storage<N, U3>,
    {
        Self::new_observer_frame(dir, up).inverse()
    }

    /// The rotation matrix required to align `a` and `b` but with its angl.
    ///
    /// This is the rotation `R` such that `(R * a).angle(b) == 0 && (R * a).dot(b).is_positive()`.
    #[inline]
    pub fn rotation_between<SB, SC>(a: &Vector<N, U3, SB>, b: &Vector<N, U3, SC>) -> Option<Self>
    where
        SB: Storage<N, U3>,
        SC: Storage<N, U3>,
    {
        Self::scaled_rotation_between(a, b, N::one())
    }

    /// The smallest rotation needed to make `a` and `b` collinear and point toward the same
    /// direction, raised to the power `s`.
    #[inline]
    pub fn scaled_rotation_between<SB, SC>(
        a: &Vector<N, U3, SB>,
        b: &Vector<N, U3, SC>,
        n: N,
    ) -> Option<Self>
    where
        SB: Storage<N, U3>,
        SC: Storage<N, U3>,
    {
        // FIXME: code duplication with Rotation.
        if let (Some(na), Some(nb)) = (a.try_normalize(N::zero()), b.try_normalize(N::zero())) {
            let c = na.cross(&nb);

            if let Some(axis) = Unit::try_new(c, N::default_epsilon()) {
                return Some(Self::from_axis_angle(&axis, na.dot(&nb).acos() * n));
            }

            // Zero or PI.
            if na.dot(&nb) < N::zero() {
                // PI
                //
                // The rotation axis is undefined but the angle not zero. This is not a
                // simple rotation.
                return None;
            }
        }

        Some(Self::identity())
    }

    /// The rotation angle.
    #[inline]
    pub fn angle(&self) -> N {
        ((self.matrix()[(0, 0)] + self.matrix()[(1, 1)] + self.matrix()[(2, 2)] - N::one())
            / ::convert(2.0))
            .acos()
    }

    /// The rotation axis. Returns `None` if the rotation angle is zero or PI.
    #[inline]
    pub fn axis(&self) -> Option<Unit<Vector3<N>>> {
        let axis = VectorN::<N, U3>::new(
            self.matrix()[(2, 1)] - self.matrix()[(1, 2)],
            self.matrix()[(0, 2)] - self.matrix()[(2, 0)],
            self.matrix()[(1, 0)] - self.matrix()[(0, 1)],
        );

        Unit::try_new(axis, N::default_epsilon())
    }

    /// The rotation axis multiplied by the rotation angle.
    #[inline]
    pub fn scaled_axis(&self) -> Vector3<N> {
        if let Some(axis) = self.axis() {
            axis.unwrap() * self.angle()
        } else {
            Vector::zero()
        }
    }

    /// The rotation angle needed to make `self` and `other` coincide.
    #[inline]
    pub fn angle_to(&self, other: &Rotation3<N>) -> N {
        self.rotation_to(other).angle()
    }

    /// The rotation matrix needed to make `self` and `other` coincide.
    ///
    /// The result is such that: `self.rotation_to(other) * self == other`.
    #[inline]
    pub fn rotation_to(&self, other: &Rotation3<N>) -> Rotation3<N> {
        other * self.inverse()
    }

    /// Raise the quaternion to a given floating power, i.e., returns the rotation with the same
    /// axis as `self` and an angle equal to `self.angle()` multiplied by `n`.
    #[inline]
    pub fn powf(&self, n: N) -> Rotation3<N> {
        if let Some(axis) = self.axis() {
            Self::from_axis_angle(&axis, self.angle() * n)
        } else if self.matrix()[(0, 0)] < N::zero() {
            let minus_id = MatrixN::<N, U3>::from_diagonal_element(-N::one());
            Self::from_matrix_unchecked(minus_id)
        } else {
            Self::identity()
        }
    }
}

impl<N: Real + Rand> Rand for Rotation3<N> {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> Self {
        Self::new(VectorN::rand(rng))
    }
}

#[cfg(feature = "arbitrary")]
impl<N: Real + Arbitrary> Arbitrary for Rotation3<N>
where
    Owned<N, U3, U3>: Send,
    Owned<N, U3>: Send,
{
    #[inline]
    fn arbitrary<G: Gen>(g: &mut G) -> Self {
        Self::new(VectorN::arbitrary(g))
    }
}
<commit_msg>Fix unnecessary parenthesis.<commit_after>#[cfg(feature = "arbitrary")]
use quickcheck::{Arbitrary, Gen};
#[cfg(feature = "arbitrary")]
use core::storage::Owned;

use std::ops::Neg;
use num::Zero;
use rand::{Rand, Rng};
use alga::general::Real;

use core::{MatrixN, Unit, Vector, Vector1, Vector3, VectorN};
use core::dimension::{U1, U2, U3};
use core::storage::Storage;

use geometry::{Rotation2, Rotation3, UnitComplex};

/*
 *
 * 2D Rotation matrix.
 *
 */
impl<N: Real> Rotation2<N> {
    /// Builds a 2 dimensional rotation matrix from an angle in radian.
    pub fn new(angle: N) -> Self {
        let (sia, coa) = angle.sin_cos();
        Self::from_matrix_unchecked(MatrixN::<N, U2>::new(coa, -sia, sia, coa))
    }

    /// Builds a 2 dimensional rotation matrix from an angle in radian wrapped in a 1-dimensional vector.
    ///
    /// Equivalent to `Self::new(axisangle[0])`.
    #[inline]
    pub fn from_scaled_axis<SB: Storage<N, U1>>(axisangle: Vector<N, U1, SB>) -> Self {
        Self::new(axisangle[0])
    }

    /// The rotation matrix required to align `a` and `b` but with its angl.
    ///
    /// This is the rotation `R` such that `(R * a).angle(b) == 0 && (R * a).dot(b).is_positive()`.
    #[inline]
    pub fn rotation_between<SB, SC>(a: &Vector<N, U2, SB>, b: &Vector<N, U2, SC>) -> Self
    where
        SB: Storage<N, U2>,
        SC: Storage<N, U2>,
    {
        ::convert(UnitComplex::rotation_between(a, b).to_rotation_matrix())
    }

    /// The smallest rotation needed to make `a` and `b` collinear and point toward the same
    /// direction, raised to the power `s`.
    #[inline]
    pub fn scaled_rotation_between<SB, SC>(
        a: &Vector<N, U2, SB>,
        b: &Vector<N, U2, SC>,
        s: N,
    ) -> Self
    where
        SB: Storage<N, U2>,
        SC: Storage<N, U2>,
    {
        ::convert(UnitComplex::scaled_rotation_between(a, b, s).to_rotation_matrix())
    }
}

impl<N: Real> Rotation2<N> {
    /// The rotation angle.
    #[inline]
    pub fn angle(&self) -> N {
        self.matrix()[(1, 0)].atan2(self.matrix()[(0, 0)])
    }

    /// The rotation angle needed to make `self` and `other` coincide.
    #[inline]
    pub fn angle_to(&self, other: &Rotation2<N>) -> N {
        self.rotation_to(other).angle()
    }

    /// The rotation matrix needed to make `self` and `other` coincide.
    ///
    /// The result is such that: `self.rotation_to(other) * self == other`.
    #[inline]
    pub fn rotation_to(&self, other: &Rotation2<N>) -> Rotation2<N> {
        other * self.inverse()
    }

    /// Raise the quaternion to a given floating power, i.e., returns the rotation with the angle
    /// of `self` multiplied by `n`.
    #[inline]
    pub fn powf(&self, n: N) -> Rotation2<N> {
        Self::new(self.angle() * n)
    }

    /// The rotation angle returned as a 1-dimensional vector.
    #[inline]
    pub fn scaled_axis(&self) -> VectorN<N, U1> {
        Vector1::new(self.angle())
    }
}

impl<N: Real + Rand> Rand for Rotation2<N> {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> Self {
        Self::new(rng.gen())
    }
}

#[cfg(feature = "arbitrary")]
impl<N: Real + Arbitrary> Arbitrary for Rotation2<N>
where
    Owned<N, U2, U2>: Send,
{
    #[inline]
    fn arbitrary<G: Gen>(g: &mut G) -> Self {
        Self::new(N::arbitrary(g))
    }
}

/*
 *
 * 3D Rotation matrix.
 *
 */
impl<N: Real> Rotation3<N> {
    /// Builds a 3 dimensional rotation matrix from an axis and an angle.
    ///
    /// # Arguments
    ///   * `axisangle` - A vector representing the rotation. Its magnitude is the amount of rotation
    ///   in radian. Its direction is the axis of rotation.
    pub fn new<SB: Storage<N, U3>>(axisangle: Vector<N, U3, SB>) -> Self {
        let axisangle = axisangle.into_owned();
        let (axis, angle) = Unit::new_and_get(axisangle);
        Self::from_axis_angle(&axis, angle)
    }

    /// Builds a 3D rotation matrix from an axis scaled by the rotation angle.
    pub fn from_scaled_axis<SB: Storage<N, U3>>(axisangle: Vector<N, U3, SB>) -> Self {
        Self::new(axisangle)
    }

    /// Builds a 3D rotation matrix from an axis and a rotation angle.
    pub fn from_axis_angle<SB>(axis: &Unit<Vector<N, U3, SB>>, angle: N) -> Self
    where
        SB: Storage<N, U3>,
    {
        if angle.is_zero() {
            Self::identity()
        } else {
            let ux = axis.as_ref()[0];
            let uy = axis.as_ref()[1];
            let uz = axis.as_ref()[2];
            let sqx = ux * ux;
            let sqy = uy * uy;
            let sqz = uz * uz;
            let (sin, cos) = angle.sin_cos();
            let one_m_cos = N::one() - cos;

            Self::from_matrix_unchecked(MatrixN::<N, U3>::new(
                sqx + (N::one() - sqx) * cos,
                ux * uy * one_m_cos - uz * sin,
                ux * uz * one_m_cos + uy * sin,
                ux * uy * one_m_cos + uz * sin,
                sqy + (N::one() - sqy) * cos,
                uy * uz * one_m_cos - ux * sin,
                ux * uz * one_m_cos - uy * sin,
                uy * uz * one_m_cos + ux * sin,
                sqz + (N::one() - sqz) * cos,
            ))
        }
    }

    /// Creates a new rotation from Euler angles.
    ///
    /// The primitive rotations are applied in order: 1 roll − 2 pitch − 3 yaw.
    pub fn from_euler_angles(roll: N, pitch: N, yaw: N) -> Self {
        let (sr, cr) = roll.sin_cos();
        let (sp, cp) = pitch.sin_cos();
        let (sy, cy) = yaw.sin_cos();

        Self::from_matrix_unchecked(MatrixN::<N, U3>::new(
            cy * cp,
            cy * sp * sr - sy * cr,
            cy * sp * cr + sy * sr,
            sy * cp,
            sy * sp * sr + cy * cr,
            sy * sp * cr - cy * sr,
            -sp,
            cp * sr,
            cp * cr,
        ))
    }

    /// Creates Euler angles from a rotation.
    ///
    /// The angles are produced in the form (roll, yaw, pitch).
    pub fn to_euler_angles(&self) -> (N, N, N) {
        // Implementation informed by "Computing Euler angles from a rotation matrix", by Gregory G. Slabaugh
        //  http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.371.6578
        if self[(2,0)].abs() != N::one() {
            let yaw   = -self[(2,0)].asin();
            let roll  = (self[(2,1)] / yaw.cos()).atan2(self[(2,2)] / yaw.cos());
            let pitch = (self[(1,0)] / yaw.cos()).atan2(self[(0,0)] / yaw.cos());
            (roll, yaw, pitch)
        } else if self[(2,0)] == -N::one() {
            (self[(0,1)].atan2(self[(0,2)]), N::frac_pi_2(), N::zero())
        } else {
            (-self[(0,1)].atan2(-self[(0,2)]), -N::frac_pi_2(), N::zero())
        }
    }

    /// Creates a rotation that corresponds to the local frame of an observer standing at the
    /// origin and looking toward `dir`.
    ///
    /// It maps the view direction `dir` to the positive `z` axis.
    ///
    /// # Arguments
    ///   * dir - The look direction, that is, direction the matrix `z` axis will be aligned with.
    ///   * up - The vertical direction. The only requirement of this parameter is to not be
    ///   collinear
    ///   to `dir`. Non-collinearity is not checked.
    #[inline]
    pub fn new_observer_frame<SB, SC>(dir: &Vector<N, U3, SB>, up: &Vector<N, U3, SC>) -> Self
    where
        SB: Storage<N, U3>,
        SC: Storage<N, U3>,
    {
        let zaxis = dir.normalize();
        let xaxis = up.cross(&zaxis).normalize();
        let yaxis = zaxis.cross(&xaxis).normalize();

        Self::from_matrix_unchecked(MatrixN::<N, U3>::new(
            xaxis.x,
            yaxis.x,
            zaxis.x,
            xaxis.y,
            yaxis.y,
            zaxis.y,
            xaxis.z,
            yaxis.z,
            zaxis.z,
        ))
    }

    /// Builds a right-handed look-at view matrix without translation.
    ///
    /// This conforms to the common notion of right handed look-at matrix from the computer
    /// graphics community.
    ///
    /// # Arguments
    ///   * eye - The eye position.
    ///   * target - The target position.
    ///   * up - A vector approximately aligned with required the vertical axis. The only
    ///   requirement of this parameter is to not be collinear to `target - eye`.
    #[inline]
    pub fn look_at_rh<SB, SC>(dir: &Vector<N, U3, SB>, up: &Vector<N, U3, SC>) -> Self
    where
        SB: Storage<N, U3>,
        SC: Storage<N, U3>,
    {
        Self::new_observer_frame(&dir.neg(), up).inverse()
    }

    /// Builds a left-handed look-at view matrix without translation.
    ///
    /// This conforms to the common notion of left handed look-at matrix from the computer
    /// graphics community.
    ///
    /// # Arguments
    ///   * eye - The eye position.
    ///   * target - The target position.
    ///   * up - A vector approximately aligned with required the vertical axis. The only
    ///   requirement of this parameter is to not be collinear to `target - eye`.
    #[inline]
    pub fn look_at_lh<SB, SC>(dir: &Vector<N, U3, SB>, up: &Vector<N, U3, SC>) -> Self
    where
        SB: Storage<N, U3>,
        SC: Storage<N, U3>,
    {
        Self::new_observer_frame(dir, up).inverse()
    }

    /// The rotation matrix required to align `a` and `b` but with its angl.
    ///
    /// This is the rotation `R` such that `(R * a).angle(b) == 0 && (R * a).dot(b).is_positive()`.
    #[inline]
    pub fn rotation_between<SB, SC>(a: &Vector<N, U3, SB>, b: &Vector<N, U3, SC>) -> Option<Self>
    where
        SB: Storage<N, U3>,
        SC: Storage<N, U3>,
    {
        Self::scaled_rotation_between(a, b, N::one())
    }

    /// The smallest rotation needed to make `a` and `b` collinear and point toward the same
    /// direction, raised to the power `s`.
    #[inline]
    pub fn scaled_rotation_between<SB, SC>(
        a: &Vector<N, U3, SB>,
        b: &Vector<N, U3, SC>,
        n: N,
    ) -> Option<Self>
    where
        SB: Storage<N, U3>,
        SC: Storage<N, U3>,
    {
        // FIXME: code duplication with Rotation.
        if let (Some(na), Some(nb)) = (a.try_normalize(N::zero()), b.try_normalize(N::zero())) {
            let c = na.cross(&nb);

            if let Some(axis) = Unit::try_new(c, N::default_epsilon()) {
                return Some(Self::from_axis_angle(&axis, na.dot(&nb).acos() * n));
            }

            // Zero or PI.
            if na.dot(&nb) < N::zero() {
                // PI
                //
                // The rotation axis is undefined but the angle not zero. This is not a
                // simple rotation.
                return None;
            }
        }

        Some(Self::identity())
    }

    /// The rotation angle.
    #[inline]
    pub fn angle(&self) -> N {
        ((self.matrix()[(0, 0)] + self.matrix()[(1, 1)] + self.matrix()[(2, 2)] - N::one())
            / ::convert(2.0))
            .acos()
    }

    /// The rotation axis. Returns `None` if the rotation angle is zero or PI.
    #[inline]
    pub fn axis(&self) -> Option<Unit<Vector3<N>>> {
        let axis = VectorN::<N, U3>::new(
            self.matrix()[(2, 1)] - self.matrix()[(1, 2)],
            self.matrix()[(0, 2)] - self.matrix()[(2, 0)],
            self.matrix()[(1, 0)] - self.matrix()[(0, 1)],
        );

        Unit::try_new(axis, N::default_epsilon())
    }

    /// The rotation axis multiplied by the rotation angle.
    #[inline]
    pub fn scaled_axis(&self) -> Vector3<N> {
        if let Some(axis) = self.axis() {
            axis.unwrap() * self.angle()
        } else {
            Vector::zero()
        }
    }

    /// The rotation angle needed to make `self` and `other` coincide.
    #[inline]
    pub fn angle_to(&self, other: &Rotation3<N>) -> N {
        self.rotation_to(other).angle()
    }

    /// The rotation matrix needed to make `self` and `other` coincide.
    ///
    /// The result is such that: `self.rotation_to(other) * self == other`.
    #[inline]
    pub fn rotation_to(&self, other: &Rotation3<N>) -> Rotation3<N> {
        other * self.inverse()
    }

    /// Raise the quaternion to a given floating power, i.e., returns the rotation with the same
    /// axis as `self` and an angle equal to `self.angle()` multiplied by `n`.
    #[inline]
    pub fn powf(&self, n: N) -> Rotation3<N> {
        if let Some(axis) = self.axis() {
            Self::from_axis_angle(&axis, self.angle() * n)
        } else if self.matrix()[(0, 0)] < N::zero() {
            let minus_id = MatrixN::<N, U3>::from_diagonal_element(-N::one());
            Self::from_matrix_unchecked(minus_id)
        } else {
            Self::identity()
        }
    }
}

impl<N: Real + Rand> Rand for Rotation3<N> {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> Self {
        Self::new(VectorN::rand(rng))
    }
}

#[cfg(feature = "arbitrary")]
impl<N: Real + Arbitrary> Arbitrary for Rotation3<N>
where
    Owned<N, U3, U3>: Send,
    Owned<N, U3>: Send,
{
    #[inline]
    fn arbitrary<G: Gen>(g: &mut G) -> Self {
        Self::new(VectorN::arbitrary(g))
    }
}
<|endoftext|>


<commit_before>//! This pass is overloaded and runs two different lints.
//!
//! - MISSING_DOC_CODE_EXAMPLES: this lint is **UNSTABLE** and looks for public items missing doc-tests
//! - PRIVATE_DOC_TESTS: this lint is **STABLE** and looks for private items with doc-tests.

use super::{span_of_attrs, Pass};
use crate::clean;
use crate::clean::*;
use crate::core::DocContext;
use crate::fold::DocFolder;
use crate::html::markdown::{find_testable_code, ErrorCodes, LangString};
use rustc_session::lint;

pub const CHECK_PRIVATE_ITEMS_DOC_TESTS: Pass = Pass {
    name: "check-private-items-doc-tests",
    run: check_private_items_doc_tests,
    description: "check private items doc tests",
};

struct PrivateItemDocTestLinter<'a, 'tcx> {
    cx: &'a DocContext<'tcx>,
}

impl<'a, 'tcx> PrivateItemDocTestLinter<'a, 'tcx> {
    fn new(cx: &'a DocContext<'tcx>) -> Self {
        PrivateItemDocTestLinter { cx }
    }
}

pub fn check_private_items_doc_tests(krate: Crate, cx: &DocContext<'_>) -> Crate {
    let mut coll = PrivateItemDocTestLinter::new(cx);

    coll.fold_crate(krate)
}

impl<'a, 'tcx> DocFolder for PrivateItemDocTestLinter<'a, 'tcx> {
    fn fold_item(&mut self, item: Item) -> Option<Item> {
        let cx = self.cx;
        let dox = item.attrs.collapsed_doc_value().unwrap_or_else(String::new);

        look_for_tests(&cx, &dox, &item);

        self.fold_item_recur(item)
    }
}

pub(crate) struct Tests {
    pub(crate) found_tests: usize,
}

impl Tests {
    pub(crate) fn new() -> Tests {
        Tests { found_tests: 0 }
    }
}

impl crate::doctest::Tester for Tests {
    fn add_test(&mut self, _: String, _: LangString, _: usize) {
        self.found_tests += 1;
    }
}

pub fn should_have_doc_example(item_kind: &clean::ItemEnum) -> bool {
    !matches!(item_kind,
        clean::StructFieldItem(_)
        | clean::VariantItem(_)
        | clean::AssocConstItem(_, _)
        | clean::AssocTypeItem(_, _)
        | clean::TypedefItem(_, _)
        | clean::StaticItem(_)
        | clean::ConstantItem(_)
        | clean::ExternCrateItem(_, _)
        | clean::ImportItem(_)
        | clean::PrimitiveItem(_)
        | clean::KeywordItem(_)
    )
}

pub fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
    let hir_id = match cx.as_local_hir_id(item.def_id) {
        Some(hir_id) => hir_id,
        None => {
            // If non-local, no need to check anything.
            return;
        }
    };

    let mut tests = Tests::new();

    find_testable_code(&dox, &mut tests, ErrorCodes::No, false, None);

    if tests.found_tests == 0
        && rustc_feature::UnstableFeatures::from_environment().is_nightly_build()
    {
        if should_have_doc_example(&item.inner) {
            debug!("reporting error for {:?} (hir_id={:?})", item, hir_id);
            let sp = span_of_attrs(&item.attrs).unwrap_or(item.source.span());
            cx.tcx.struct_span_lint_hir(
                lint::builtin::MISSING_DOC_CODE_EXAMPLES,
                hir_id,
                sp,
                |lint| lint.build("missing code example in this documentation").emit(),
            );
        }
    } else if tests.found_tests > 0 && !cx.renderinfo.borrow().access_levels.is_public(item.def_id)
    {
        cx.tcx.struct_span_lint_hir(
            lint::builtin::PRIVATE_DOC_TESTS,
            hir_id,
            span_of_attrs(&item.attrs).unwrap_or(item.source.span()),
            |lint| lint.build("documentation test in private item").emit(),
        );
    }
}
<commit_msg>Don't emit an error on private doc tests when they're ignored<commit_after>//! This pass is overloaded and runs two different lints.
//!
//! - MISSING_DOC_CODE_EXAMPLES: this lint is **UNSTABLE** and looks for public items missing doc-tests
//! - PRIVATE_DOC_TESTS: this lint is **STABLE** and looks for private items with doc-tests.

use super::{span_of_attrs, Pass};
use crate::clean;
use crate::clean::*;
use crate::core::DocContext;
use crate::fold::DocFolder;
use crate::html::markdown::{find_testable_code, ErrorCodes, Ignore, LangString};
use rustc_session::lint;

pub const CHECK_PRIVATE_ITEMS_DOC_TESTS: Pass = Pass {
    name: "check-private-items-doc-tests",
    run: check_private_items_doc_tests,
    description: "check private items doc tests",
};

struct PrivateItemDocTestLinter<'a, 'tcx> {
    cx: &'a DocContext<'tcx>,
}

impl<'a, 'tcx> PrivateItemDocTestLinter<'a, 'tcx> {
    fn new(cx: &'a DocContext<'tcx>) -> Self {
        PrivateItemDocTestLinter { cx }
    }
}

pub fn check_private_items_doc_tests(krate: Crate, cx: &DocContext<'_>) -> Crate {
    let mut coll = PrivateItemDocTestLinter::new(cx);

    coll.fold_crate(krate)
}

impl<'a, 'tcx> DocFolder for PrivateItemDocTestLinter<'a, 'tcx> {
    fn fold_item(&mut self, item: Item) -> Option<Item> {
        let cx = self.cx;
        let dox = item.attrs.collapsed_doc_value().unwrap_or_else(String::new);

        look_for_tests(&cx, &dox, &item);

        self.fold_item_recur(item)
    }
}

pub(crate) struct Tests {
    pub(crate) found_tests: usize,
}

impl crate::doctest::Tester for Tests {
    fn add_test(&mut self, _: String, config: LangString, _: usize) {
        if config.rust && config.ignore == Ignore::None {
            self.found_tests += 1;
        }
    }
}

pub fn should_have_doc_example(item_kind: &clean::ItemEnum) -> bool {
    !matches!(item_kind,
        clean::StructFieldItem(_)
        | clean::VariantItem(_)
        | clean::AssocConstItem(_, _)
        | clean::AssocTypeItem(_, _)
        | clean::TypedefItem(_, _)
        | clean::StaticItem(_)
        | clean::ConstantItem(_)
        | clean::ExternCrateItem(_, _)
        | clean::ImportItem(_)
        | clean::PrimitiveItem(_)
        | clean::KeywordItem(_)
    )
}

pub fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
    let hir_id = match cx.as_local_hir_id(item.def_id) {
        Some(hir_id) => hir_id,
        None => {
            // If non-local, no need to check anything.
            return;
        }
    };

    let mut tests = Tests { found_tests: 0 };

    find_testable_code(&dox, &mut tests, ErrorCodes::No, false, None);

    if tests.found_tests == 0
        && rustc_feature::UnstableFeatures::from_environment().is_nightly_build()
    {
        if should_have_doc_example(&item.inner) {
            debug!("reporting error for {:?} (hir_id={:?})", item, hir_id);
            let sp = span_of_attrs(&item.attrs).unwrap_or(item.source.span());
            cx.tcx.struct_span_lint_hir(
                lint::builtin::MISSING_DOC_CODE_EXAMPLES,
                hir_id,
                sp,
                |lint| lint.build("missing code example in this documentation").emit(),
            );
        }
    } else if tests.found_tests > 0 && !cx.renderinfo.borrow().access_levels.is_public(item.def_id)
    {
        cx.tcx.struct_span_lint_hir(
            lint::builtin::PRIVATE_DOC_TESTS,
            hir_id,
            span_of_attrs(&item.attrs).unwrap_or(item.source.span()),
            |lint| lint.build("documentation test in private item").emit(),
        );
    }
}
<|endoftext|>


<commit_before>use std::{
    cell::{Cell, RefCell},
    collections::BTreeMap,
    rc::Rc,
};

use dces::prelude::{Entity, EntityComponentManager, System};

use crate::{css_engine::*, prelude::*, shell::WindowShell, tree::Tree, utils::*};

/// The `EventStateSystem` pops events from the event queue and delegates the events to the corresponding event handlers of the widgets and updates the states.
pub struct EventStateSystem {
    pub shell: Rc<RefCell<WindowShell<WindowAdapter>>>,
    pub handlers: EventHandlerMap,
    pub update: Rc<Cell<bool>>,
    pub running: Rc<Cell<bool>>,
    pub mouse_down_nodes: RefCell<Vec<Entity>>,
    pub states: Rc<RefCell<BTreeMap<Entity, Rc<dyn State>>>>,
    pub render_objects: Rc<RefCell<BTreeMap<Entity, Box<dyn RenderObject>>>>,
    pub layouts: Rc<RefCell<BTreeMap<Entity, Box<dyn Layout>>>>,
}

impl EventStateSystem {
    fn process_top_down_event(
        &self,
        _event: &EventBox,
        _ecm: &mut EntityComponentManager<Tree, StringComponentStore>,
    ) {
    }

    fn process_bottom_up_event(
        &self,
        mouse_position: Point,
        event: &EventBox,
        ecm: &mut EntityComponentManager<Tree, StringComponentStore>,
    ) {
        let mut matching_nodes = vec![];

        let mut current_node = event.source;
        let root = ecm.entity_store().root;

        let theme = ecm
            .component_store()
            .get::<Theme>("theme", root)
            .unwrap()
            .clone();

        // resize
        if let Ok(WindowEvent::Resize { width, height }) = event.downcast_ref::<WindowEvent>() {
            // update window size
            if let Ok(bounds) = ecm
                .component_store_mut()
                .get_mut::<Rectangle>("bounds", root)
            {
                bounds.set_width(*width);
                bounds.set_height(*height);
            }

            if let Ok(constraint) = ecm
                .component_store_mut()
                .get_mut::<Constraint>("constraint", root)
            {
                constraint.set_width(*width);
                constraint.set_height(*height);
            }

            self.update.set(true);
        }

        // global key handling
        if let Ok(event) = event.downcast_ref::<KeyDownEvent>() {
            if let Ok(global) = ecm.component_store_mut().get_mut::<Global>("global", root) {
                // Set this value on the keyboard state
                global.keyboard_state.set_key_state(event.event.key, true);
            }
        }

        if let Ok(event) = event.downcast_ref::<KeyUpEvent>() {
            if let Ok(global) = ecm.component_store_mut().get_mut::<Global>("global", root) {
                // Set this value on the keyboard state
                global.keyboard_state.set_key_state(event.event.key, false);
            }
        }

        let mut unknown_event = true;
        let mut clipped_parent = vec![];

        loop {
            let mut has_handler = false;
            if let Some(handlers) = self.handlers.borrow().get(&current_node) {
                if handlers.iter().any(|handler| handler.handles_event(event)) {
                    has_handler = true;
                }
            }

            if let Some(cp) = clipped_parent.last() {
                if ecm.entity_store().parent[&current_node] == Some(*cp) {
                    clipped_parent.push(current_node);
                } else {
                    clipped_parent.pop();
                }
            }

            // key down event
            if event.downcast_ref::<KeyDownEvent>().is_ok() {
                if let Some(focused) = ecm
                    .component_store()
                    .get::<Global>("global", root)
                    .unwrap()
                    .focused_widget
                {
                    if current_node == focused && has_handler {
                        matching_nodes.push(current_node);
                    }
                }

                unknown_event = false;
            }

            // key up event
            if event.downcast_ref::<KeyUpEvent>().is_ok() {
                if let Some(focused) = ecm
                    .component_store()
                    .get::<Global>("global", root)
                    .unwrap()
                    .focused_widget
                {
                    if current_node == focused && has_handler {
                        matching_nodes.push(current_node);
                    }
                }

                unknown_event = false;
            }

            // scroll handling
            if event.downcast_ref::<ScrollEvent>().is_ok() {
                if check_mouse_condition(
                    mouse_position,
                    &WidgetContainer::new(current_node, ecm, &theme),
                ) && has_handler
                {
                    matching_nodes.push(current_node);
                }

                unknown_event = false;
            }

            // click handling
            if let Ok(event) = event.downcast_ref::<ClickEvent>() {
                if check_mouse_condition(
                    event.position,
                    &WidgetContainer::new(current_node, ecm, &theme),
                ) {
                    let mut add = true;
                    if let Some(op) = clipped_parent.get(0) {
                        if !check_mouse_condition(
                            event.position,
                            &WidgetContainer::new(*op, ecm, &theme),
                        ) {
                            add = false;
                        }
                    }

                    if add && has_handler {
                        matching_nodes.push(current_node);
                        self.mouse_down_nodes.borrow_mut().push(current_node);
                    }
                }

                unknown_event = false;
            }

            // mouse down handling
            if let Ok(event) = event.downcast_ref::<MouseDownEvent>() {
                if check_mouse_condition(
                    Point::new(event.x, event.y),
                    &WidgetContainer::new(current_node, ecm, &theme),
                ) {
                    let mut add = true;
                    if let Some(op) = clipped_parent.get(0) {
                        // todo: improve check path if exists
                        if !check_mouse_condition(
                            Point::new(event.x, event.y),
                            &WidgetContainer::new(*op, ecm, &theme),
                        ) && has_handler
                        {
                            add = false;
                        }
                    }

                    if add {
                        matching_nodes.push(current_node);
                        self.mouse_down_nodes.borrow_mut().push(current_node);
                    }
                }

                unknown_event = false;
            }

            // mouse move handling
            if let Ok(event) = event.downcast_ref::<MouseMoveEvent>() {
                if check_mouse_condition(
                    Point::new(event.x, event.y),
                    &WidgetContainer::new(current_node, ecm, &theme),
                ) {
                    let mut add = true;
                    if let Some(op) = clipped_parent.get(0) {
                        // todo: improve check path if exists
                        if !check_mouse_condition(
                            Point::new(event.x, event.y),
                            &WidgetContainer::new(*op, ecm, &theme),
                        ) {
                            add = false;
                        }
                    }

                    if add && has_handler {
                        matching_nodes.push(current_node);
                        self.mouse_down_nodes.borrow_mut().push(current_node);
                    }
                }

                unknown_event = false;
            }

            // mouse up handling
            if event.downcast_ref::<MouseUpEvent>().is_ok() {
                if self.mouse_down_nodes.borrow().contains(&current_node) && has_handler {
                    matching_nodes.push(current_node);
                    let index = self
                        .mouse_down_nodes
                        .borrow()
                        .iter()
                        .position(|x| *x == current_node)
                        .unwrap();
                    self.mouse_down_nodes.borrow_mut().remove(index);
                }

                unknown_event = false;
            }

            if unknown_event
                && *WidgetContainer::new(current_node, ecm, &theme).get::<bool>("enabled")
            {
                if has_handler {
                    matching_nodes.push(current_node);
                }
            }

            if let Ok(clip) = ecm.component_store().get::<bool>("clip", current_node) {
                if *clip {
                    clipped_parent.clear();
                    clipped_parent.push(current_node);
                }
            }

            let mut it = ecm.entity_store().start_node(current_node).into_iter();
            it.next();

            if let Some(node) = it.next() {
                current_node = node;
            } else {
                break;
            }
        }

        let mut handled = false;
        let mut disabled_parent = None;

        for node in matching_nodes.iter().rev() {
            if let Some(dp) = disabled_parent {
                if ecm.entity_store().parent[&node] == Some(dp) {
                    disabled_parent = Some(*node);
                    continue;
                } else {
                    disabled_parent = None;
                }
            }

            if let Ok(enabled) = ecm.component_store().get::<bool>("enabled", *node) {
                if !enabled {
                    disabled_parent = Some(*node);
                    continue;
                }
            }

            if let Some(handlers) = self.handlers.borrow().get(node) {
                handled = handlers.iter().any(|handler| handler.handle_event(event));

                self.update.set(true);
            }

            if handled {
                break;
            }
        }
    }
}

impl System<Tree, StringComponentStore> for EventStateSystem {
    fn run(&self, ecm: &mut EntityComponentManager<Tree, StringComponentStore>) {
        let mut shell = self.shell.borrow_mut();

        loop {
            {
                let adapter = shell.adapter();
                let mouse_position = adapter.mouse_position;
                for event in adapter.event_queue.into_iter() {
                    if let Ok(event) = event.downcast_ref::<SystemEvent>() {
                        match event {
                            SystemEvent::Quit => {
                                self.running.set(false);
                                return;
                            }
                        }
                    }

                    match event.strategy {
                        EventStrategy::TopDown => {
                            self.process_top_down_event(&event, ecm);
                        }
                        EventStrategy::BottomUp => {
                            self.process_bottom_up_event(mouse_position, &event, ecm);
                        }
                        _ => {}
                    }
                }
            }

            // handle states

            let root = ecm.entity_store().root;

            let theme = ecm
                .component_store()
                .get::<Theme>("theme", root)
                .unwrap()
                .clone();
            let mut current_node = root;

            loop {
                let mut skip = false;

                {
                    let mut ctx = Context::new(
                        (current_node, ecm),
                        &mut shell,
                        &theme,
                        self.render_objects.clone(),
                        self.layouts.clone(),
                        self.handlers.clone(),
                        self.states.clone(),
                    );

                    if !self.states.borrow().contains_key(&current_node) {
                        skip = true;
                    }

                    if !skip {
                        if let Some(state) = self.states.borrow().get(&current_node) {
                            state.update(&mut ctx);
                        }
                    }
                }
                let mut it = ecm.entity_store().start_node(current_node).into_iter();
                it.next();

                if let Some(node) = it.next() {
                    current_node = node;
                } else {
                    break;
                }
            }

            if shell.adapter().event_queue.is_empty() {
                break;
            }
        }
    }
}
<commit_msg>Fix mouse up event.<commit_after>use std::{
    cell::{Cell, RefCell},
    collections::BTreeMap,
    rc::Rc,
};

use dces::prelude::{Entity, EntityComponentManager, System};

use crate::{css_engine::*, prelude::*, shell::WindowShell, tree::Tree, utils::*};

/// The `EventStateSystem` pops events from the event queue and delegates the events to the corresponding event handlers of the widgets and updates the states.
pub struct EventStateSystem {
    pub shell: Rc<RefCell<WindowShell<WindowAdapter>>>,
    pub handlers: EventHandlerMap,
    pub update: Rc<Cell<bool>>,
    pub running: Rc<Cell<bool>>,
    pub mouse_down_nodes: RefCell<Vec<Entity>>,
    pub states: Rc<RefCell<BTreeMap<Entity, Rc<dyn State>>>>,
    pub render_objects: Rc<RefCell<BTreeMap<Entity, Box<dyn RenderObject>>>>,
    pub layouts: Rc<RefCell<BTreeMap<Entity, Box<dyn Layout>>>>,
}

impl EventStateSystem {
    fn process_top_down_event(
        &self,
        _event: &EventBox,
        _ecm: &mut EntityComponentManager<Tree, StringComponentStore>,
    ) {
    }

    fn process_bottom_up_event(
        &self,
        mouse_position: Point,
        event: &EventBox,
        ecm: &mut EntityComponentManager<Tree, StringComponentStore>,
    ) {
        let mut matching_nodes = vec![];

        let mut current_node = event.source;
        let root = ecm.entity_store().root;

        let theme = ecm
            .component_store()
            .get::<Theme>("theme", root)
            .unwrap()
            .clone();

        // resize
        if let Ok(WindowEvent::Resize { width, height }) = event.downcast_ref::<WindowEvent>() {
            // update window size
            if let Ok(bounds) = ecm
                .component_store_mut()
                .get_mut::<Rectangle>("bounds", root)
            {
                bounds.set_width(*width);
                bounds.set_height(*height);
            }

            if let Ok(constraint) = ecm
                .component_store_mut()
                .get_mut::<Constraint>("constraint", root)
            {
                constraint.set_width(*width);
                constraint.set_height(*height);
            }

            self.update.set(true);
        }

        // global key handling
        if let Ok(event) = event.downcast_ref::<KeyDownEvent>() {
            if let Ok(global) = ecm.component_store_mut().get_mut::<Global>("global", root) {
                // Set this value on the keyboard state
                global.keyboard_state.set_key_state(event.event.key, true);
            }
        }

        if let Ok(event) = event.downcast_ref::<KeyUpEvent>() {
            if let Ok(global) = ecm.component_store_mut().get_mut::<Global>("global", root) {
                // Set this value on the keyboard state
                global.keyboard_state.set_key_state(event.event.key, false);
            }
        }

        let mut unknown_event = true;
        let mut clipped_parent = vec![];

        loop {
            let mut has_handler = false;
            if let Some(handlers) = self.handlers.borrow().get(&current_node) {
                if handlers.iter().any(|handler| handler.handles_event(event)) {
                    has_handler = true;
                }
            }

            if let Some(cp) = clipped_parent.last() {
                if ecm.entity_store().parent[&current_node] == Some(*cp) {
                    clipped_parent.push(current_node);
                } else {
                    clipped_parent.pop();
                }
            }

            // key down event
            if event.downcast_ref::<KeyDownEvent>().is_ok() {
                if let Some(focused) = ecm
                    .component_store()
                    .get::<Global>("global", root)
                    .unwrap()
                    .focused_widget
                {
                    if current_node == focused && has_handler {
                        matching_nodes.push(current_node);
                    }
                }

                unknown_event = false;
            }

            // key up event
            if event.downcast_ref::<KeyUpEvent>().is_ok() {
                if let Some(focused) = ecm
                    .component_store()
                    .get::<Global>("global", root)
                    .unwrap()
                    .focused_widget
                {
                    if current_node == focused && has_handler {
                        matching_nodes.push(current_node);
                    }
                }

                unknown_event = false;
            }

            // scroll handling
            if event.downcast_ref::<ScrollEvent>().is_ok() {
                if check_mouse_condition(
                    mouse_position,
                    &WidgetContainer::new(current_node, ecm, &theme),
                ) && has_handler
                {
                    matching_nodes.push(current_node);
                }

                unknown_event = false;
            }

            // click handling
            if let Ok(event) = event.downcast_ref::<ClickEvent>() {
                if check_mouse_condition(
                    event.position,
                    &WidgetContainer::new(current_node, ecm, &theme),
                ) {
                    let mut add = true;
                    if let Some(op) = clipped_parent.get(0) {
                        if !check_mouse_condition(
                            event.position,
                            &WidgetContainer::new(*op, ecm, &theme),
                        ) {
                            add = false;
                        }
                    }

                    if add && has_handler {
                        matching_nodes.push(current_node);
                        self.mouse_down_nodes.borrow_mut().push(current_node);
                    }
                }

                unknown_event = false;
            }

            // mouse down handling
            if let Ok(event) = event.downcast_ref::<MouseDownEvent>() {
                if check_mouse_condition(
                    Point::new(event.x, event.y),
                    &WidgetContainer::new(current_node, ecm, &theme),
                ) {
                    let mut add = true;
                    if let Some(op) = clipped_parent.get(0) {
                        // todo: improve check path if exists
                        if !check_mouse_condition(
                            Point::new(event.x, event.y),
                            &WidgetContainer::new(*op, ecm, &theme),
                        ) && has_handler
                        {
                            add = false;
                        }
                    }

                    if add {
                        matching_nodes.push(current_node);
                        self.mouse_down_nodes.borrow_mut().push(current_node);
                    }
                }

                unknown_event = false;
            }

            // mouse move handling
            if let Ok(event) = event.downcast_ref::<MouseMoveEvent>() {
                if check_mouse_condition(
                    Point::new(event.x, event.y),
                    &WidgetContainer::new(current_node, ecm, &theme),
                ) {
                    let mut add = true;
                    if let Some(op) = clipped_parent.get(0) {
                        // todo: improve check path if exists
                        if !check_mouse_condition(
                            Point::new(event.x, event.y),
                            &WidgetContainer::new(*op, ecm, &theme),
                        ) {
                            add = false;
                        }
                    }

                    if add && has_handler {
                        matching_nodes.push(current_node);
                        self.mouse_down_nodes.borrow_mut().push(current_node);
                    }
                }

                unknown_event = false;
            }

            // mouse up handling
            if event.downcast_ref::<MouseUpEvent>().is_ok() {
                if self.mouse_down_nodes.borrow().contains(&current_node) {
                    matching_nodes.push(current_node);
                    let index = self
                        .mouse_down_nodes
                        .borrow()
                        .iter()
                        .position(|x| *x == current_node)
                        .unwrap();
                    self.mouse_down_nodes.borrow_mut().remove(index);
                }

                unknown_event = false;
            }

            if unknown_event
                && *WidgetContainer::new(current_node, ecm, &theme).get::<bool>("enabled")
            {
                if has_handler {
                    matching_nodes.push(current_node);
                }
            }

            if let Ok(clip) = ecm.component_store().get::<bool>("clip", current_node) {
                if *clip {
                    clipped_parent.clear();
                    clipped_parent.push(current_node);
                }
            }

            let mut it = ecm.entity_store().start_node(current_node).into_iter();
            it.next();

            if let Some(node) = it.next() {
                current_node = node;
            } else {
                break;
            }
        }

        let mut handled = false;
        let mut disabled_parent = None;

        for node in matching_nodes.iter().rev() {
            if let Some(dp) = disabled_parent {
                if ecm.entity_store().parent[&node] == Some(dp) {
                    disabled_parent = Some(*node);
                    continue;
                } else {
                    disabled_parent = None;
                }
            }

            if let Ok(enabled) = ecm.component_store().get::<bool>("enabled", *node) {
                if !enabled {
                    disabled_parent = Some(*node);
                    continue;
                }
            }

            if let Some(handlers) = self.handlers.borrow().get(node) {
                handled = handlers.iter().any(|handler| handler.handle_event(event));

                self.update.set(true);
            }

            if handled {
                break;
            }
        }
    }
}

impl System<Tree, StringComponentStore> for EventStateSystem {
    fn run(&self, ecm: &mut EntityComponentManager<Tree, StringComponentStore>) {
        let mut shell = self.shell.borrow_mut();

        loop {
            {
                let adapter = shell.adapter();
                let mouse_position = adapter.mouse_position;
                for event in adapter.event_queue.into_iter() {
                    if let Ok(event) = event.downcast_ref::<SystemEvent>() {
                        match event {
                            SystemEvent::Quit => {
                                self.running.set(false);
                                return;
                            }
                        }
                    }

                    match event.strategy {
                        EventStrategy::TopDown => {
                            self.process_top_down_event(&event, ecm);
                        }
                        EventStrategy::BottomUp => {
                            self.process_bottom_up_event(mouse_position, &event, ecm);
                        }
                        _ => {}
                    }
                }
            }

            // handle states

            let root = ecm.entity_store().root;

            let theme = ecm
                .component_store()
                .get::<Theme>("theme", root)
                .unwrap()
                .clone();
            let mut current_node = root;

            loop {
                let mut skip = false;

                {
                    let mut ctx = Context::new(
                        (current_node, ecm),
                        &mut shell,
                        &theme,
                        self.render_objects.clone(),
                        self.layouts.clone(),
                        self.handlers.clone(),
                        self.states.clone(),
                    );

                    if !self.states.borrow().contains_key(&current_node) {
                        skip = true;
                    }

                    if !skip {
                        if let Some(state) = self.states.borrow().get(&current_node) {
                            state.update(&mut ctx);
                        }
                    }
                }
                let mut it = ecm.entity_store().start_node(current_node).into_iter();
                it.next();

                if let Some(node) = it.next() {
                    current_node = node;
                } else {
                    break;
                }
            }

            if shell.adapter().event_queue.is_empty() {
                break;
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2012 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.

// compile-flags: -Z parse-only

//error-pattern: discriminator values can only be used with a c-like enum

enum color {
    red = 0xff0000,
    green = 0x00ff00,
    blue = 0x0000ff,
    black = 0x000000,
    white = 0xffffff,
    other (str),
}
<commit_msg>Rename C-like enum to Field-less enum<commit_after>// Copyright 2012 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.

// compile-flags: -Z parse-only

//error-pattern: discriminator values can only be used with a field-less enum

enum color {
    red = 0xff0000,
    green = 0x00ff00,
    blue = 0x0000ff,
    black = 0x000000,
    white = 0xffffff,
    other (str),
}
<|endoftext|>


<commit_before>use gmp::mpq::Mpq;
use std::collections::btree_map::{BTreeMap, Entry as BEntry};
use std::collections::hash_map::{HashMap, Entry as HEntry};
use std::cmp::Ordering;
use std::vec::Vec;

fn encode_pattern(a: &[Ordering]) -> (usize, usize) {
    a.iter().rev().fold((0, 0), |(eq, gt), &o| {
        (eq << 1 | if o == Ordering::Equal { 1 } else { 0 },
         gt << 1 | if o == Ordering::Greater { 1 } else { 0 })
    })
}

fn decode_bits(mut gt: usize) -> Box<[usize]> {
    let mut cs = Vec::new();
    cs.reserve(gt.count_ones() as usize);
    while gt != 0 {
        let k = gt.trailing_zeros();
        cs.push(k as usize);
        gt &= !(1 << k);
    }
    cs.into_boxed_slice()
}

pub fn proportional_completion<'a, Patterns>(patterns: Patterns) -> Box<[(Box<[usize]>, Mpq)]>
    where Patterns: Iterator<Item = (&'a [Ordering], &'a Mpq)>
{
    let mut pattern_map = BTreeMap::new();
    let mut total = Mpq::zero();
    for (a, w) in patterns {
        if !w.is_zero() {
            match pattern_map.entry(encode_pattern(a)) {
                BEntry::Occupied(mut e) => {
                    let w1 = e.get() + w;
                    e.insert(w1);
                }
                BEntry::Vacant(e) => {
                    e.insert(w.clone());
                }
            }
            total = total + w;
        }
    }
    while let Some((&(eq, _), _)) = pattern_map.iter().next_back() {
        if eq == 0 {
            return pattern_map.iter()
                .map(|(&(_, gt), w)| (decode_bits(gt), w.clone()))
                .collect::<Vec<_>>()
                .into_boxed_slice();
        }

        let m = pattern_map.split_off(&(eq, 0));

        if pattern_map.is_empty() {
            return m.iter()
                .map(|(&(_, gt), w)| (decode_bits(gt), w / Mpq::from(2u64)))
                .chain(pattern_map.iter()
                    .map(|(&(_, gt), w)| (decode_bits(gt | eq), w / Mpq::from(2u64))))
                .collect::<Vec<_>>()
                .into_boxed_slice();
        }

        let scale = m.iter().fold(total.clone(), |acc, (_, w)| acc - w);

        let mut h = HashMap::new();
        for (&(eq1, gt1), w1) in &pattern_map {
            debug_assert!(eq1 < eq);
            match h.entry((eq & eq1, eq & gt1)) {
                HEntry::Occupied(mut e) => {
                    let w2 = e.get() + w1;
                    e.insert(w2);
                }
                HEntry::Vacant(e) => {
                    e.insert(w1.clone());
                }
            }
        }

        for ((eq_, gt), w) in m {
            let w_scaled = w / &scale;
            debug_assert_eq!(eq_, eq);
            for (&(eq1, gt1), w1) in &h {
                match pattern_map.entry((eq1, gt | gt1)) {
                    BEntry::Occupied(mut e) => {
                        let w2 = e.get() + w1 * &w_scaled;
                        e.insert(w2);
                    }
                    BEntry::Vacant(e) => {
                        e.insert(w1 * &w_scaled);
                    }
                }
            }
        }
        debug_assert_eq!(pattern_map.iter().fold(Mpq::zero(), |acc, (_, w)| acc + w),
                         total);
    }
    Box::new([])
}

#[cfg(test)]
mod tests {
    use gmp::mpq::Mpq;
    use gmp::mpz::Mpz;
    use std::cmp::Ordering;
    use std::str::FromStr;

    use super::proportional_completion;

    const Q: fn(i64) -> Mpq = Mpq::from;

    fn sorted<T: Clone + Ord>(v: &[T]) -> Box<[T]> {
        let mut v1 = v.to_vec().into_boxed_slice();
        v1.sort();
        v1
    }

    #[test]
    fn test_proportional_completion_1() {
        // Schulze’s calcul02.pdf
        let (_1, _2, _3) = (Ordering::Greater, Ordering::Equal, Ordering::Less);
        let patterns: &[(&[Ordering], &Mpq)] = &[(&[_1, _1, _1, _1], &Q(46)),
                                                 (&[_1, _1, _1, _2], &Q(15)),
                                                 (&[_1, _1, _1, _3], &Q(24)),
                                                 (&[_1, _1, _2, _1], &Q(8)),
                                                 (&[_1, _1, _2, _2], &Q(10)),
                                                 (&[_1, _1, _3, _1], &Q(10)),
                                                 (&[_1, _1, _3, _3], &Q(19)),
                                                 (&[_1, _2, _1, _1], &Q(8)),
                                                 (&[_1, _2, _1, _2], &Q(29)),
                                                 (&[_1, _2, _2, _1], &Q(10)),
                                                 (&[_1, _2, _2, _2], &Q(26)),
                                                 (&[_1, _3, _1, _1], &Q(10)),
                                                 (&[_1, _3, _1, _3], &Q(15)),
                                                 (&[_1, _3, _2, _1], &Q(1)),
                                                 (&[_1, _3, _3, _1], &Q(9)),
                                                 (&[_1, _3, _3, _3], &Q(41)),
                                                 (&[_2, _1, _1, _1], &Q(3)),
                                                 (&[_2, _1, _1, _2], &Q(5)),
                                                 (&[_2, _1, _2, _1], &Q(5)),
                                                 (&[_2, _1, _2, _2], &Q(10)),
                                                 (&[_2, _2, _1, _1], &Q(7)),
                                                 (&[_2, _2, _1, _2], &Q(22)),
                                                 (&[_2, _2, _2, _1], &Q(14)),
                                                 (&[_2, _2, _2, _2], &Q(23)),
                                                 (&[_2, _3, _3, _3], &Q(1)),
                                                 (&[_3, _1, _1, _1], &Q(1)),
                                                 (&[_3, _1, _1, _3], &Q(3)),
                                                 (&[_3, _1, _3, _1], &Q(4)),
                                                 (&[_3, _1, _3, _3], &Q(5)),
                                                 (&[_3, _3, _1, _1], &Q(4)),
                                                 (&[_3, _3, _1, _3], &Q(11)),
                                                 (&[_3, _3, _3, _1], &Q(6)),
                                                 (&[_3, _3, _3, _3], &Q(55))];
        let expected: &[(&[Ordering], Mpq)] =
            &[(&[_1, _1, _1, _1],
               Mpq::ratio(&Mpz::from_str("45513455366183031714312799").unwrap(),
                          &Mpz::from_str("392675963004164103979050").unwrap())),
              (&[_1, _1, _1, _3], Q(313141398725389) / Q(5802708856700)),
              (&[_1, _1, _3, _1], Q(398610303226324835) / Q(17955446458922532)),
              (&[_1, _1, _3, _3], Q(56713304320) / Q(2097364647)),
              (&[_1, _3, _1, _1],
               Mpq::ratio(&Mpz::from_str("323263789854293839067").unwrap(),
                          &Mpz::from_str("10819009863732307590").unwrap())),
              (&[_1, _3, _1, _3], Q(2664088261) / Q(79938130)),
              (&[_1, _3, _3, _1], Q(10276259658824) / Q(618385674987)),
              (&[_1, _3, _3, _3], Q(14567002) / Q(288933)),
              (&[_3, _1, _1, _1], Q(9026619205849313) / Q(2353019619161400)),
              (&[_3, _1, _1, _3], Q(25937418993) / Q(4983004600)),
              (&[_3, _1, _3, _1], Q(16829300885) / Q(2878135428)),
              (&[_3, _1, _3, _3], Q(2025680) / Q(300181)),
              (&[_3, _3, _1, _1], Q(57854720993) / Q(8103800865)),
              (&[_3, _3, _1, _3], Q(4456496) / Q(291745)),
              (&[_3, _3, _3, _1], Q(837524) / Q(99123)),
              (&[_3, _3, _3, _3], Q(40878) / Q(703))];
        let expected = expected.iter()
            .map(|&(ref a, ref w)| {
                (a.iter()
                     .enumerate()
                     .filter(|&(_, &o)| o == _1)
                     .map(|(i, _)| i)
                     .collect::<Vec<_>>()
                     .into_boxed_slice(),
                 w.clone())
            })
            .collect::<Vec<_>>();
        assert_eq!(*sorted(&proportional_completion(patterns.iter().cloned())),
                   *sorted(&expected));
    }
}
<commit_msg>proportional_completion: Add another small test<commit_after>use gmp::mpq::Mpq;
use std::collections::btree_map::{BTreeMap, Entry as BEntry};
use std::collections::hash_map::{HashMap, Entry as HEntry};
use std::cmp::Ordering;
use std::vec::Vec;

fn encode_pattern(a: &[Ordering]) -> (usize, usize) {
    a.iter().rev().fold((0, 0), |(eq, gt), &o| {
        (eq << 1 | if o == Ordering::Equal { 1 } else { 0 },
         gt << 1 | if o == Ordering::Greater { 1 } else { 0 })
    })
}

fn decode_bits(mut gt: usize) -> Box<[usize]> {
    let mut cs = Vec::new();
    cs.reserve(gt.count_ones() as usize);
    while gt != 0 {
        let k = gt.trailing_zeros();
        cs.push(k as usize);
        gt &= !(1 << k);
    }
    cs.into_boxed_slice()
}

pub fn proportional_completion<'a, Patterns>(patterns: Patterns) -> Box<[(Box<[usize]>, Mpq)]>
    where Patterns: Iterator<Item = (&'a [Ordering], &'a Mpq)>
{
    let mut pattern_map = BTreeMap::new();
    let mut total = Mpq::zero();
    for (a, w) in patterns {
        if !w.is_zero() {
            match pattern_map.entry(encode_pattern(a)) {
                BEntry::Occupied(mut e) => {
                    let w1 = e.get() + w;
                    e.insert(w1);
                }
                BEntry::Vacant(e) => {
                    e.insert(w.clone());
                }
            }
            total = total + w;
        }
    }
    while let Some((&(eq, _), _)) = pattern_map.iter().next_back() {
        if eq == 0 {
            return pattern_map.iter()
                .map(|(&(_, gt), w)| (decode_bits(gt), w.clone()))
                .collect::<Vec<_>>()
                .into_boxed_slice();
        }

        let m = pattern_map.split_off(&(eq, 0));

        if pattern_map.is_empty() {
            return m.iter()
                .map(|(&(_, gt), w)| (decode_bits(gt), w / Mpq::from(2u64)))
                .chain(pattern_map.iter()
                    .map(|(&(_, gt), w)| (decode_bits(gt | eq), w / Mpq::from(2u64))))
                .collect::<Vec<_>>()
                .into_boxed_slice();
        }

        let scale = m.iter().fold(total.clone(), |acc, (_, w)| acc - w);

        let mut h = HashMap::new();
        for (&(eq1, gt1), w1) in &pattern_map {
            debug_assert!(eq1 < eq);
            match h.entry((eq & eq1, eq & gt1)) {
                HEntry::Occupied(mut e) => {
                    let w2 = e.get() + w1;
                    e.insert(w2);
                }
                HEntry::Vacant(e) => {
                    e.insert(w1.clone());
                }
            }
        }

        for ((eq_, gt), w) in m {
            let w_scaled = w / &scale;
            debug_assert_eq!(eq_, eq);
            for (&(eq1, gt1), w1) in &h {
                match pattern_map.entry((eq1, gt | gt1)) {
                    BEntry::Occupied(mut e) => {
                        let w2 = e.get() + w1 * &w_scaled;
                        e.insert(w2);
                    }
                    BEntry::Vacant(e) => {
                        e.insert(w1 * &w_scaled);
                    }
                }
            }
        }
        debug_assert_eq!(pattern_map.iter().fold(Mpq::zero(), |acc, (_, w)| acc + w),
                         total);
    }
    Box::new([])
}

#[cfg(test)]
mod tests {
    use gmp::mpq::Mpq;
    use gmp::mpz::Mpz;
    use std::cmp::Ordering::{self, Greater as _1, Equal as _2, Less as _3};
    use std::str::FromStr;

    use super::proportional_completion;

    const Q: fn(i64) -> Mpq = Mpq::from;

    fn sorted<T: Clone + Ord>(v: &[T]) -> Box<[T]> {
        let mut v1 = v.to_vec().into_boxed_slice();
        v1.sort();
        v1
    }

    #[test]
    fn test_proportional_completion_1() {
        // Schulze’s calcul02.pdf
        let patterns: &[(&[Ordering], &Mpq)] = &[(&[_1, _1, _1, _1], &Q(46)),
                                                 (&[_1, _1, _1, _2], &Q(15)),
                                                 (&[_1, _1, _1, _3], &Q(24)),
                                                 (&[_1, _1, _2, _1], &Q(8)),
                                                 (&[_1, _1, _2, _2], &Q(10)),
                                                 (&[_1, _1, _3, _1], &Q(10)),
                                                 (&[_1, _1, _3, _3], &Q(19)),
                                                 (&[_1, _2, _1, _1], &Q(8)),
                                                 (&[_1, _2, _1, _2], &Q(29)),
                                                 (&[_1, _2, _2, _1], &Q(10)),
                                                 (&[_1, _2, _2, _2], &Q(26)),
                                                 (&[_1, _3, _1, _1], &Q(10)),
                                                 (&[_1, _3, _1, _3], &Q(15)),
                                                 (&[_1, _3, _2, _1], &Q(1)),
                                                 (&[_1, _3, _3, _1], &Q(9)),
                                                 (&[_1, _3, _3, _3], &Q(41)),
                                                 (&[_2, _1, _1, _1], &Q(3)),
                                                 (&[_2, _1, _1, _2], &Q(5)),
                                                 (&[_2, _1, _2, _1], &Q(5)),
                                                 (&[_2, _1, _2, _2], &Q(10)),
                                                 (&[_2, _2, _1, _1], &Q(7)),
                                                 (&[_2, _2, _1, _2], &Q(22)),
                                                 (&[_2, _2, _2, _1], &Q(14)),
                                                 (&[_2, _2, _2, _2], &Q(23)),
                                                 (&[_2, _3, _3, _3], &Q(1)),
                                                 (&[_3, _1, _1, _1], &Q(1)),
                                                 (&[_3, _1, _1, _3], &Q(3)),
                                                 (&[_3, _1, _3, _1], &Q(4)),
                                                 (&[_3, _1, _3, _3], &Q(5)),
                                                 (&[_3, _3, _1, _1], &Q(4)),
                                                 (&[_3, _3, _1, _3], &Q(11)),
                                                 (&[_3, _3, _3, _1], &Q(6)),
                                                 (&[_3, _3, _3, _3], &Q(55))];
        let expected: &[(&[Ordering], Mpq)] =
            &[(&[_1, _1, _1, _1],
               Mpq::ratio(&Mpz::from_str("45513455366183031714312799").unwrap(),
                          &Mpz::from_str("392675963004164103979050").unwrap())),
              (&[_1, _1, _1, _3], Q(313141398725389) / Q(5802708856700)),
              (&[_1, _1, _3, _1], Q(398610303226324835) / Q(17955446458922532)),
              (&[_1, _1, _3, _3], Q(56713304320) / Q(2097364647)),
              (&[_1, _3, _1, _1],
               Mpq::ratio(&Mpz::from_str("323263789854293839067").unwrap(),
                          &Mpz::from_str("10819009863732307590").unwrap())),
              (&[_1, _3, _1, _3], Q(2664088261) / Q(79938130)),
              (&[_1, _3, _3, _1], Q(10276259658824) / Q(618385674987)),
              (&[_1, _3, _3, _3], Q(14567002) / Q(288933)),
              (&[_3, _1, _1, _1], Q(9026619205849313) / Q(2353019619161400)),
              (&[_3, _1, _1, _3], Q(25937418993) / Q(4983004600)),
              (&[_3, _1, _3, _1], Q(16829300885) / Q(2878135428)),
              (&[_3, _1, _3, _3], Q(2025680) / Q(300181)),
              (&[_3, _3, _1, _1], Q(57854720993) / Q(8103800865)),
              (&[_3, _3, _1, _3], Q(4456496) / Q(291745)),
              (&[_3, _3, _3, _1], Q(837524) / Q(99123)),
              (&[_3, _3, _3, _3], Q(40878) / Q(703))];
        let expected = expected.iter()
            .map(|&(ref a, ref w)| {
                (a.iter()
                     .enumerate()
                     .filter(|&(_, &o)| o == _1)
                     .map(|(i, _)| i)
                     .collect::<Vec<_>>()
                     .into_boxed_slice(),
                 w.clone())
            })
            .collect::<Vec<_>>();
        assert_eq!(*sorted(&proportional_completion(patterns.iter().cloned())),
                   *sorted(&expected));
    }

    #[test]
    fn test_proportional_completion_2() {
        let patterns: &[(&[Ordering], &Mpq)] = &[(&[_1, _3], &Q(1)), (&[_3, _2], &Q(1))];
        let expected: &[(Box<[usize]>, Mpq)] = &[(Box::new([]), Q(1)), (Box::new([0]), Q(1))];
        assert_eq!(*sorted(&proportional_completion(patterns.iter().cloned())),
                   *sorted(&expected));
    }
}
<|endoftext|>


<commit_before>

use EventLoopHandle;

use std::io::Error as IoError;
use std::io::Write;
use std::os::raw::{c_int, c_void};

use std::os::unix::io::RawFd;
use wayland_sys::server::*;

// fd_event_source
//

/// A handle to a registered FD event source
///
/// Dropping this struct does not remove the event source,
/// use the `remove` method for that.
pub struct FdEventSource {
    ptr: *mut wl_event_source,
    data: *mut (*mut c_void, *mut EventLoopHandle),
}

bitflags!{
    /// Flags to register interest on a file descriptor
    pub struct FdInterest: u32 {
        /// Interest to be notified when the file descriptor is readable
        const READ  = 0x01;
        /// Interest to be notified when the file descriptor is writable
        const WRITE = 0x02;
    }
}

pub fn make_fd_event_source(ptr: *mut wl_event_source, data: Box<(*mut c_void, *mut EventLoopHandle)>)
                            -> FdEventSource {
    FdEventSource {
        ptr: ptr,
        data: Box::into_raw(data),
    }
}

impl FdEventSource {
    /// Change the registered interest for this FD
    pub fn update_mask(&mut self, mask: FdInterest) {
        unsafe {
            ffi_dispatch!(
                WAYLAND_SERVER_HANDLE,
                wl_event_source_fd_update,
                self.ptr,
                mask.bits()
            );
        }
    }

    /// Remove this event source from its event loop
    pub fn remove(self) {
        unsafe {
            ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_event_source_remove, self.ptr);
            let _ = Box::from_raw(self.data);
        }
    }
}

/// Trait for handlers for FD events
pub trait FdEventSourceHandler {
    /// The FD is ready to be read/written
    ///
    /// Details of the capability state are given as argument.
    fn ready(&mut self, evlh: &mut EventLoopHandle, fd: RawFd, mask: FdInterest);
    /// An error occured with this FD
    ///
    /// Most likely it won't be usable any longer
    fn error(&mut self, evlh: &mut EventLoopHandle, fd: RawFd, error: IoError);
}

pub unsafe extern "C" fn event_source_fd_dispatcher<H>(fd: c_int, mask: u32, data: *mut c_void) -> c_int
where
    H: FdEventSourceHandler,
{
    // We don't need to worry about panic-safeness, because if there is a panic,
    // we'll abort the process, so no access to corrupted data is possible.
    let ret = ::std::panic::catch_unwind(move || {
        let (handler_ptr, evlh_ptr) = *(data as *mut (*mut c_void, *mut EventLoopHandle));
        let handler = &mut *(handler_ptr as *mut H);
        let evlh = &mut *(evlh_ptr);
        if mask & 0x04 > 0 {
            // EPOLLERR
            use nix::sys::socket;
            let err = match socket::getsockopt(fd, socket::sockopt::SocketError) {
                Ok(err) => err,
                Err(_) => {
                    // error while retrieving the error code ???
                    let _ = write!(
                        ::std::io::stderr(),
                        "[wayland-server error] Error while retrieving error code on socket {}, aborting.",
                        fd
                    );
                    ::libc::abort();
                }
            };
            handler.error(evlh, fd, IoError::from_raw_os_error(err));
        } else if mask & 0x03 > 0 {
            // EPOLLHUP
            handler.error(
                evlh,
                fd,
                IoError::new(::std::io::ErrorKind::ConnectionAborted, ""),
            )
        } else {
            let mut bits = FdInterest::empty();
            if mask & 0x02 > 0 {
                bits = bits | WRITE;
            }
            if mask & 0x01 > 0 {
                bits = bits | READ;
            }
            handler.ready(evlh, fd, bits)
        }
    });
    match ret {
        Ok(()) => return 0,   // all went well
        Err(_) => {
            // a panic occured
            let _ = write!(
                ::std::io::stderr(),
                "[wayland-server error] A handler for fd {} event source panicked, aborting.",
                fd
            );
            ::libc::abort();
        }
    }
}

// timer_event_source
//

/// A handle to a registered timer event source
///
/// Dropping this struct does not remove the event source,
/// use the `remove` method for that.
pub struct TimerEventSource {
    ptr: *mut wl_event_source,
    _data: Box<(*mut c_void, *mut EventLoopHandle)>,
}

pub fn make_timer_event_source(ptr: *mut wl_event_source, data: Box<(*mut c_void, *mut EventLoopHandle)>)
                               -> TimerEventSource {
    TimerEventSource {
        ptr: ptr,
        _data: data,
    }
}

impl TimerEventSource {
    /// Set the delay of this timer
    ///
    /// The handler will be called during the next dispatch of the
    /// event loop after this time (in milliseconds) is elapsed.
    pub fn set_delay_ms(&mut self, delay: i32) {
        unsafe {
            ffi_dispatch!(
                WAYLAND_SERVER_HANDLE,
                wl_event_source_timer_update,
                self.ptr,
                delay
            );
        }
    }

    /// Remove this event source from its event loop
    pub fn remove(self) {
        unsafe {
            ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_event_source_remove, self.ptr);
        }
    }
}

/// Trait for handlers for timer event sources
pub trait TimerEventSourceHandler {
    /// The countdown has reached zero
    fn timeout(&mut self, evlh: &mut EventLoopHandle);
}

pub unsafe extern "C" fn event_source_timer_dispatcher<H>(data: *mut c_void) -> c_int
where
    H: TimerEventSourceHandler,
{
    // We don't need to worry about panic-safeness, because if there is a panic,
    // we'll abort the process, so no access to corrupted data is possible.
    let ret = ::std::panic::catch_unwind(move || {
        let (handler_ptr, evlh_ptr) = *(data as *mut (*mut c_void, *mut EventLoopHandle));
        let handler = &mut *(handler_ptr as *mut H);
        let evlh = &mut *(evlh_ptr);
        handler.timeout(evlh);
    });
    match ret {
        Ok(()) => return 0,   // all went well
        Err(_) => {
            // a panic occured
            let _ =
                write!(
                ::std::io::stderr(),
                "[wayland-server error] A handler for a timer event source panicked, aborting.",
            );
            ::libc::abort();
        }
    }
}

// signal_event_source
//

/// A handle to a registered signal event source
///
/// Dropping this struct does not remove the event source,
/// use the `remove` method for that.
pub struct SignalEventSource {
    ptr: *mut wl_event_source,
    _data: Box<(*mut c_void, *mut EventLoopHandle)>,
}

pub fn make_signal_event_source(ptr: *mut wl_event_source, data: Box<(*mut c_void, *mut EventLoopHandle)>)
                                -> SignalEventSource {
    SignalEventSource {
        ptr: ptr,
        _data: data,
    }
}

impl SignalEventSource {
    /// Remove this event source from its event loop
    pub fn remove(self) {
        unsafe {
            ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_event_source_remove, self.ptr);
        }
    }
}

/// Trait for handlers of signal event sources
pub trait SignalEventSourceHandler {
    /// A signal has been received
    ///
    /// The signal number is given has argument
    fn signal(&mut self, evlh: &mut EventLoopHandle, signal: ::nix::sys::signal::Signal);
}

pub unsafe extern "C" fn event_source_signal_dispatcher<H>(signal: c_int, data: *mut c_void) -> c_int
where
    H: SignalEventSourceHandler,
{
    // We don't need to worry about panic-safeness, because if there is a panic,
    // we'll abort the process, so no access to corrupted data is possible.
    let ret = ::std::panic::catch_unwind(move || {
        let (handler_ptr, evlh_ptr) = *(data as *mut (*mut c_void, *mut EventLoopHandle));
        let handler = &mut *(handler_ptr as *mut H);
        let evlh = &mut *(evlh_ptr);
        let sig = match ::nix::sys::signal::Signal::from_c_int(signal) {
            Ok(sig) => sig,
            Err(_) => {
                // Actually, this cannot happen, as we cannot register an event source for
                // an unknown signal...
                let _ = write!(
                    ::std::io::stderr(),
                    "[wayland-server error] Unknown signal in signal event source: {}, aborting.",
                    signal
                );
                ::libc::abort();
            }
        };
        handler.signal(evlh, sig);
    });
    match ret {
        Ok(()) => return 0,   // all went well
        Err(_) => {
            // a panic occured
            let _ =
                write!(
                ::std::io::stderr(),
                "[wayland-server error] A handler for a timer event source panicked, aborting.",
            );
            ::libc::abort();
        }
    }
}
<commit_msg>Fix FdEventSource error detection<commit_after>

use EventLoopHandle;

use std::io::Error as IoError;
use std::io::Write;
use std::os::raw::{c_int, c_void};

use std::os::unix::io::RawFd;
use wayland_sys::server::*;

// fd_event_source
//

/// A handle to a registered FD event source
///
/// Dropping this struct does not remove the event source,
/// use the `remove` method for that.
pub struct FdEventSource {
    ptr: *mut wl_event_source,
    data: *mut (*mut c_void, *mut EventLoopHandle),
}

bitflags!{
    /// Flags to register interest on a file descriptor
    pub struct FdInterest: u32 {
        /// Interest to be notified when the file descriptor is readable
        const READ  = 0x01;
        /// Interest to be notified when the file descriptor is writable
        const WRITE = 0x02;
    }
}

pub fn make_fd_event_source(ptr: *mut wl_event_source, data: Box<(*mut c_void, *mut EventLoopHandle)>)
                            -> FdEventSource {
    FdEventSource {
        ptr: ptr,
        data: Box::into_raw(data),
    }
}

impl FdEventSource {
    /// Change the registered interest for this FD
    pub fn update_mask(&mut self, mask: FdInterest) {
        unsafe {
            ffi_dispatch!(
                WAYLAND_SERVER_HANDLE,
                wl_event_source_fd_update,
                self.ptr,
                mask.bits()
            );
        }
    }

    /// Remove this event source from its event loop
    pub fn remove(self) {
        unsafe {
            ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_event_source_remove, self.ptr);
            let _ = Box::from_raw(self.data);
        }
    }
}

/// Trait for handlers for FD events
pub trait FdEventSourceHandler {
    /// The FD is ready to be read/written
    ///
    /// Details of the capability state are given as argument.
    fn ready(&mut self, evlh: &mut EventLoopHandle, fd: RawFd, mask: FdInterest);
    /// An error occured with this FD
    ///
    /// Most likely it won't be usable any longer
    fn error(&mut self, evlh: &mut EventLoopHandle, fd: RawFd, error: IoError);
}

pub unsafe extern "C" fn event_source_fd_dispatcher<H>(fd: c_int, mask: u32, data: *mut c_void) -> c_int
where
    H: FdEventSourceHandler,
{
    // We don't need to worry about panic-safeness, because if there is a panic,
    // we'll abort the process, so no access to corrupted data is possible.
    let ret = ::std::panic::catch_unwind(move || {
        let (handler_ptr, evlh_ptr) = *(data as *mut (*mut c_void, *mut EventLoopHandle));
        let handler = &mut *(handler_ptr as *mut H);
        let evlh = &mut *(evlh_ptr);
        if mask & 0x08 > 0 {
            // EPOLLERR
            use nix::sys::socket;
            let err = match socket::getsockopt(fd, socket::sockopt::SocketError) {
                Ok(err) => err,
                Err(_) => {
                    // error while retrieving the error code ???
                    let _ = write!(
                        ::std::io::stderr(),
                        "[wayland-server error] Error while retrieving error code on socket {}, aborting.",
                        fd
                    );
                    ::libc::abort();
                }
            };
            handler.error(evlh, fd, IoError::from_raw_os_error(err));
        } else if mask & 0x04 > 0 {
            // EPOLLHUP
            handler.error(
                evlh,
                fd,
                IoError::new(::std::io::ErrorKind::ConnectionAborted, ""),
            )
        } else {
            let mut bits = FdInterest::empty();
            if mask & 0x02 > 0 {
                bits = bits | WRITE;
            }
            if mask & 0x01 > 0 {
                bits = bits | READ;
            }
            handler.ready(evlh, fd, bits)
        }
    });
    match ret {
        Ok(()) => return 0,   // all went well
        Err(_) => {
            // a panic occured
            let _ = write!(
                ::std::io::stderr(),
                "[wayland-server error] A handler for fd {} event source panicked, aborting.",
                fd
            );
            ::libc::abort();
        }
    }
}

// timer_event_source
//

/// A handle to a registered timer event source
///
/// Dropping this struct does not remove the event source,
/// use the `remove` method for that.
pub struct TimerEventSource {
    ptr: *mut wl_event_source,
    _data: Box<(*mut c_void, *mut EventLoopHandle)>,
}

pub fn make_timer_event_source(ptr: *mut wl_event_source, data: Box<(*mut c_void, *mut EventLoopHandle)>)
                               -> TimerEventSource {
    TimerEventSource {
        ptr: ptr,
        _data: data,
    }
}

impl TimerEventSource {
    /// Set the delay of this timer
    ///
    /// The handler will be called during the next dispatch of the
    /// event loop after this time (in milliseconds) is elapsed.
    pub fn set_delay_ms(&mut self, delay: i32) {
        unsafe {
            ffi_dispatch!(
                WAYLAND_SERVER_HANDLE,
                wl_event_source_timer_update,
                self.ptr,
                delay
            );
        }
    }

    /// Remove this event source from its event loop
    pub fn remove(self) {
        unsafe {
            ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_event_source_remove, self.ptr);
        }
    }
}

/// Trait for handlers for timer event sources
pub trait TimerEventSourceHandler {
    /// The countdown has reached zero
    fn timeout(&mut self, evlh: &mut EventLoopHandle);
}

pub unsafe extern "C" fn event_source_timer_dispatcher<H>(data: *mut c_void) -> c_int
where
    H: TimerEventSourceHandler,
{
    // We don't need to worry about panic-safeness, because if there is a panic,
    // we'll abort the process, so no access to corrupted data is possible.
    let ret = ::std::panic::catch_unwind(move || {
        let (handler_ptr, evlh_ptr) = *(data as *mut (*mut c_void, *mut EventLoopHandle));
        let handler = &mut *(handler_ptr as *mut H);
        let evlh = &mut *(evlh_ptr);
        handler.timeout(evlh);
    });
    match ret {
        Ok(()) => return 0,   // all went well
        Err(_) => {
            // a panic occured
            let _ =
                write!(
                ::std::io::stderr(),
                "[wayland-server error] A handler for a timer event source panicked, aborting.",
            );
            ::libc::abort();
        }
    }
}

// signal_event_source
//

/// A handle to a registered signal event source
///
/// Dropping this struct does not remove the event source,
/// use the `remove` method for that.
pub struct SignalEventSource {
    ptr: *mut wl_event_source,
    _data: Box<(*mut c_void, *mut EventLoopHandle)>,
}

pub fn make_signal_event_source(ptr: *mut wl_event_source, data: Box<(*mut c_void, *mut EventLoopHandle)>)
                                -> SignalEventSource {
    SignalEventSource {
        ptr: ptr,
        _data: data,
    }
}

impl SignalEventSource {
    /// Remove this event source from its event loop
    pub fn remove(self) {
        unsafe {
            ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_event_source_remove, self.ptr);
        }
    }
}

/// Trait for handlers of signal event sources
pub trait SignalEventSourceHandler {
    /// A signal has been received
    ///
    /// The signal number is given has argument
    fn signal(&mut self, evlh: &mut EventLoopHandle, signal: ::nix::sys::signal::Signal);
}

pub unsafe extern "C" fn event_source_signal_dispatcher<H>(signal: c_int, data: *mut c_void) -> c_int
where
    H: SignalEventSourceHandler,
{
    // We don't need to worry about panic-safeness, because if there is a panic,
    // we'll abort the process, so no access to corrupted data is possible.
    let ret = ::std::panic::catch_unwind(move || {
        let (handler_ptr, evlh_ptr) = *(data as *mut (*mut c_void, *mut EventLoopHandle));
        let handler = &mut *(handler_ptr as *mut H);
        let evlh = &mut *(evlh_ptr);
        let sig = match ::nix::sys::signal::Signal::from_c_int(signal) {
            Ok(sig) => sig,
            Err(_) => {
                // Actually, this cannot happen, as we cannot register an event source for
                // an unknown signal...
                let _ = write!(
                    ::std::io::stderr(),
                    "[wayland-server error] Unknown signal in signal event source: {}, aborting.",
                    signal
                );
                ::libc::abort();
            }
        };
        handler.signal(evlh, sig);
    });
    match ret {
        Ok(()) => return 0,   // all went well
        Err(_) => {
            // a panic occured
            let _ =
                write!(
                ::std::io::stderr(),
                "[wayland-server error] A handler for a timer event source panicked, aborting.",
            );
            ::libc::abort();
        }
    }
}
<|endoftext|>