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

use approxeq::ApproxEq;
use num::{One, Zero};

use num_lib::NumCast;
use std::ops::{Add, Mul, Div, Neg, Sub};

pub fn Matrix4<T:Add<T, Output=T> + Clone + ApproxEq<T> + Mul<T, Output=T> + One + Zero>(
        m11: T, m12: T, m13: T, m14: T,
        m21: T, m22: T, m23: T, m24: T,
        m31: T, m32: T, m33: T, m34: T,
        m41: T, m42: T, m43: T, m44: T)
     -> Matrix4<T> {
    Matrix4 {
        m11: m11, m12: m12, m13: m13, m14: m14,
        m21: m21, m22: m22, m23: m23, m24: m24,
        m31: m31, m32: m32, m33: m33, m34: m34,
        m41: m41, m42: m42, m43: m43, m44: m44
    }
}

#[derive(Debug, Copy, Clone)]
pub struct Matrix4<T> {
    pub m11: T, pub m12: T, pub m13: T, pub m14: T,
    pub m21: T, pub m22: T, pub m23: T, pub m24: T,
    pub m31: T, pub m32: T, pub m33: T, pub m34: T,
    pub m41: T, pub m42: T, pub m43: T, pub m44: T,
}

impl<T:Add<T, Output=T> + Copy + Clone + ApproxEq<T> + Mul<T, Output=T> + One + Zero> Matrix4<T> {
    pub fn approx_eq(&self, other: &Matrix4<T>) -> bool {
        self.m11.approx_eq(&other.m11) && self.m12.approx_eq(&other.m12) &&
        self.m13.approx_eq(&other.m13) && self.m14.approx_eq(&other.m14) &&
        self.m21.approx_eq(&other.m21) && self.m22.approx_eq(&other.m22) &&
        self.m23.approx_eq(&other.m23) && self.m24.approx_eq(&other.m24) &&
        self.m31.approx_eq(&other.m31) && self.m32.approx_eq(&other.m32) &&
        self.m33.approx_eq(&other.m33) && self.m34.approx_eq(&other.m34) &&
        self.m41.approx_eq(&other.m41) && self.m42.approx_eq(&other.m42) &&
        self.m43.approx_eq(&other.m43) && self.m44.approx_eq(&other.m44)
    }

    pub fn mul(&self, m: &Matrix4<T>) -> Matrix4<T> {
        Matrix4(m.m11*self.m11 + m.m12*self.m21 + m.m13*self.m31 + m.m14*self.m41,
                m.m11*self.m12 + m.m12*self.m22 + m.m13*self.m32 + m.m14*self.m42,
                m.m11*self.m13 + m.m12*self.m23 + m.m13*self.m33 + m.m14*self.m43,
                m.m11*self.m14 + m.m12*self.m24 + m.m13*self.m34 + m.m14*self.m44,
                m.m21*self.m11 + m.m22*self.m21 + m.m23*self.m31 + m.m24*self.m41,
                m.m21*self.m12 + m.m22*self.m22 + m.m23*self.m32 + m.m24*self.m42,
                m.m21*self.m13 + m.m22*self.m23 + m.m23*self.m33 + m.m24*self.m43,
                m.m21*self.m14 + m.m22*self.m24 + m.m23*self.m34 + m.m24*self.m44,
                m.m31*self.m11 + m.m32*self.m21 + m.m33*self.m31 + m.m34*self.m41,
                m.m31*self.m12 + m.m32*self.m22 + m.m33*self.m32 + m.m34*self.m42,
                m.m31*self.m13 + m.m32*self.m23 + m.m33*self.m33 + m.m34*self.m43,
                m.m31*self.m14 + m.m32*self.m24 + m.m33*self.m34 + m.m34*self.m44,
                m.m41*self.m11 + m.m42*self.m21 + m.m43*self.m31 + m.m44*self.m41,
                m.m41*self.m12 + m.m42*self.m22 + m.m43*self.m32 + m.m44*self.m42,
                m.m41*self.m13 + m.m42*self.m23 + m.m43*self.m33 + m.m44*self.m43,
                m.m41*self.m14 + m.m42*self.m24 + m.m43*self.m34 + m.m44*self.m44)
    }

    pub fn mul_s(&self, x: T) -> Matrix4<T> {
        Matrix4(self.m11 * x, self.m12 * x, self.m13 * x, self.m14 * x,
                self.m21 * x, self.m22 * x, self.m23 * x, self.m24 * x,
                self.m31 * x, self.m32 * x, self.m33 * x, self.m34 * x,
                self.m41 * x, self.m42 * x, self.m43 * x, self.m44 * x)
    }

    pub fn scale(&self, x: T, y: T, z: T) -> Matrix4<T> {
        Matrix4(self.m11 * x,     self.m12.clone(), self.m13.clone(), self.m14.clone(),
                self.m21.clone(), self.m22 * y,     self.m23.clone(), self.m24.clone(),
                self.m31.clone(), self.m32.clone(), self.m33 * z,     self.m34.clone(),
                self.m41.clone(), self.m42.clone(), self.m43.clone(), self.m44.clone())
    }

    pub fn to_array(&self) -> [T; 16] {
        [
            self.m11.clone(), self.m12.clone(), self.m13.clone(), self.m14.clone(),
            self.m21.clone(), self.m22.clone(), self.m23.clone(), self.m24.clone(),
            self.m31.clone(), self.m32.clone(), self.m33.clone(), self.m34.clone(),
            self.m41.clone(), self.m42.clone(), self.m43.clone(), self.m44.clone()
        ]
    }

    pub fn translate(&self, x: T, y: T, z: T) -> Matrix4<T> {
        let (_0, _1): (T, T) = (Zero::zero(), One::one());
        let matrix = Matrix4(_1.clone(), _0.clone(), _0.clone(), _0.clone(),
                             _0.clone(), _1.clone(), _0.clone(), _0.clone(),
                             _0.clone(), _0.clone(), _1.clone(), _0.clone(),
                             x,  y,  z,  _1.clone());

        return self.mul(&matrix);
    }
}

pub fn ortho<T:Add<T, Output=T> + Copy + Clone + Div<T, Output=T> + ApproxEq<T> + Mul<T, Output=T> + Neg<Output=T> + NumCast + One +
               Sub<T, Output=T> + Zero>
        (left: T,
         right: T,
         bottom: T,
         top: T,
         near: T,
         far: T)
      -> Matrix4<T> {
    let _2: T = NumCast::from(2).unwrap();
    let _1: T = One::one();
    let _0: T = Zero::zero();

    let tx = -((right + left) / (right - left));
    let ty = -((top + bottom) / (top - bottom));
    let tz = -((far + near) / (far - near));

    Matrix4(_2 / (right - left), _0.clone(),          _0.clone(),         _0.clone(),
            _0.clone(),          _2 / (top - bottom), _0.clone(),         _0.clone(),
            _0.clone(),          _0.clone(),          -_2 / (far - near), _0.clone(),
            tx,                  ty,                  tz,                 _1.clone())
}

pub fn identity<T:Add<T, Output=T> + Clone + ApproxEq<T> + Mul<T, Output=T> + One + Zero>() -> Matrix4<T> {
    let (_0, _1): (T, T) = (Zero::zero(), One::one());
    Matrix4(_1.clone(), _0.clone(), _0.clone(), _0.clone(),
            _0.clone(), _1.clone(), _0.clone(), _0.clone(),
            _0.clone(), _0.clone(), _1.clone(), _0.clone(),
            _0.clone(), _0.clone(), _0.clone(), _1.clone())
}

#[test]
pub fn test_ortho() {
    let (left, right, bottom, top) = (0.0f32, 1.0f32, 0.1f32, 1.0f32);
    let (near, far) = (-1.0f32, 1.0f32);
    let result = ortho(left, right, bottom, top, near, far);
    let expected = Matrix4(2.0,  0.0,         0.0,  0.0,
                           0.0,  2.22222222,  0.0,  0.0,
                           0.0,  0.0,         -1.0, 0.0,
                           -1.0, -1.22222222, -0.0, 1.0);
    debug!("result={:?} expected={:?}", result, expected);
    assert!(result.approx_eq(&expected));
}

<commit_msg>Add method to transform 2d point by 4x4 matrix.<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use approxeq::ApproxEq;
use point::Point2D;
use num::{One, Zero};

use num_lib::NumCast;
use std::ops::{Add, Mul, Div, Neg, Sub};

pub fn Matrix4<T:Add<T, Output=T> + Clone + ApproxEq<T> + Mul<T, Output=T> + One + Zero>(
        m11: T, m12: T, m13: T, m14: T,
        m21: T, m22: T, m23: T, m24: T,
        m31: T, m32: T, m33: T, m34: T,
        m41: T, m42: T, m43: T, m44: T)
     -> Matrix4<T> {
    Matrix4 {
        m11: m11, m12: m12, m13: m13, m14: m14,
        m21: m21, m22: m22, m23: m23, m24: m24,
        m31: m31, m32: m32, m33: m33, m34: m34,
        m41: m41, m42: m42, m43: m43, m44: m44
    }
}

#[derive(Debug, Copy, Clone)]
pub struct Matrix4<T> {
    pub m11: T, pub m12: T, pub m13: T, pub m14: T,
    pub m21: T, pub m22: T, pub m23: T, pub m24: T,
    pub m31: T, pub m32: T, pub m33: T, pub m34: T,
    pub m41: T, pub m42: T, pub m43: T, pub m44: T,
}

impl<T:Add<T, Output=T> + Copy + Clone + ApproxEq<T> + Mul<T, Output=T> + One + Zero> Matrix4<T> {
    pub fn approx_eq(&self, other: &Matrix4<T>) -> bool {
        self.m11.approx_eq(&other.m11) && self.m12.approx_eq(&other.m12) &&
        self.m13.approx_eq(&other.m13) && self.m14.approx_eq(&other.m14) &&
        self.m21.approx_eq(&other.m21) && self.m22.approx_eq(&other.m22) &&
        self.m23.approx_eq(&other.m23) && self.m24.approx_eq(&other.m24) &&
        self.m31.approx_eq(&other.m31) && self.m32.approx_eq(&other.m32) &&
        self.m33.approx_eq(&other.m33) && self.m34.approx_eq(&other.m34) &&
        self.m41.approx_eq(&other.m41) && self.m42.approx_eq(&other.m42) &&
        self.m43.approx_eq(&other.m43) && self.m44.approx_eq(&other.m44)
    }

    pub fn mul(&self, m: &Matrix4<T>) -> Matrix4<T> {
        Matrix4(m.m11*self.m11 + m.m12*self.m21 + m.m13*self.m31 + m.m14*self.m41,
                m.m11*self.m12 + m.m12*self.m22 + m.m13*self.m32 + m.m14*self.m42,
                m.m11*self.m13 + m.m12*self.m23 + m.m13*self.m33 + m.m14*self.m43,
                m.m11*self.m14 + m.m12*self.m24 + m.m13*self.m34 + m.m14*self.m44,
                m.m21*self.m11 + m.m22*self.m21 + m.m23*self.m31 + m.m24*self.m41,
                m.m21*self.m12 + m.m22*self.m22 + m.m23*self.m32 + m.m24*self.m42,
                m.m21*self.m13 + m.m22*self.m23 + m.m23*self.m33 + m.m24*self.m43,
                m.m21*self.m14 + m.m22*self.m24 + m.m23*self.m34 + m.m24*self.m44,
                m.m31*self.m11 + m.m32*self.m21 + m.m33*self.m31 + m.m34*self.m41,
                m.m31*self.m12 + m.m32*self.m22 + m.m33*self.m32 + m.m34*self.m42,
                m.m31*self.m13 + m.m32*self.m23 + m.m33*self.m33 + m.m34*self.m43,
                m.m31*self.m14 + m.m32*self.m24 + m.m33*self.m34 + m.m34*self.m44,
                m.m41*self.m11 + m.m42*self.m21 + m.m43*self.m31 + m.m44*self.m41,
                m.m41*self.m12 + m.m42*self.m22 + m.m43*self.m32 + m.m44*self.m42,
                m.m41*self.m13 + m.m42*self.m23 + m.m43*self.m33 + m.m44*self.m43,
                m.m41*self.m14 + m.m42*self.m24 + m.m43*self.m34 + m.m44*self.m44)
    }

    pub fn mul_s(&self, x: T) -> Matrix4<T> {
        Matrix4(self.m11 * x, self.m12 * x, self.m13 * x, self.m14 * x,
                self.m21 * x, self.m22 * x, self.m23 * x, self.m24 * x,
                self.m31 * x, self.m32 * x, self.m33 * x, self.m34 * x,
                self.m41 * x, self.m42 * x, self.m43 * x, self.m44 * x)
    }

    pub fn scale(&self, x: T, y: T, z: T) -> Matrix4<T> {
        Matrix4(self.m11 * x,     self.m12.clone(), self.m13.clone(), self.m14.clone(),
                self.m21.clone(), self.m22 * y,     self.m23.clone(), self.m24.clone(),
                self.m31.clone(), self.m32.clone(), self.m33 * z,     self.m34.clone(),
                self.m41.clone(), self.m42.clone(), self.m43.clone(), self.m44.clone())
    }

    /// Returns the given point transformed by this matrix.
    #[inline]
    pub fn transform_point(&self, p: &Point2D<T>) -> Point2D<T> {
        Point2D(p.x * self.m11 + p.y * self.m21 + self.m41,
                p.x * self.m12 + p.y * self.m22 + self.m42)
    }

    pub fn to_array(&self) -> [T; 16] {
        [
            self.m11.clone(), self.m12.clone(), self.m13.clone(), self.m14.clone(),
            self.m21.clone(), self.m22.clone(), self.m23.clone(), self.m24.clone(),
            self.m31.clone(), self.m32.clone(), self.m33.clone(), self.m34.clone(),
            self.m41.clone(), self.m42.clone(), self.m43.clone(), self.m44.clone()
        ]
    }

    pub fn translate(&self, x: T, y: T, z: T) -> Matrix4<T> {
        let (_0, _1): (T, T) = (Zero::zero(), One::one());
        let matrix = Matrix4(_1.clone(), _0.clone(), _0.clone(), _0.clone(),
                             _0.clone(), _1.clone(), _0.clone(), _0.clone(),
                             _0.clone(), _0.clone(), _1.clone(), _0.clone(),
                             x,  y,  z,  _1.clone());

        return self.mul(&matrix);
    }
}

pub fn ortho<T:Add<T, Output=T> + Copy + Clone + Div<T, Output=T> + ApproxEq<T> + Mul<T, Output=T> + Neg<Output=T> + NumCast + One +
               Sub<T, Output=T> + Zero>
        (left: T,
         right: T,
         bottom: T,
         top: T,
         near: T,
         far: T)
      -> Matrix4<T> {
    let _2: T = NumCast::from(2).unwrap();
    let _1: T = One::one();
    let _0: T = Zero::zero();

    let tx = -((right + left) / (right - left));
    let ty = -((top + bottom) / (top - bottom));
    let tz = -((far + near) / (far - near));

    Matrix4(_2 / (right - left), _0.clone(),          _0.clone(),         _0.clone(),
            _0.clone(),          _2 / (top - bottom), _0.clone(),         _0.clone(),
            _0.clone(),          _0.clone(),          -_2 / (far - near), _0.clone(),
            tx,                  ty,                  tz,                 _1.clone())
}

pub fn identity<T:Add<T, Output=T> + Clone + ApproxEq<T> + Mul<T, Output=T> + One + Zero>() -> Matrix4<T> {
    let (_0, _1): (T, T) = (Zero::zero(), One::one());
    Matrix4(_1.clone(), _0.clone(), _0.clone(), _0.clone(),
            _0.clone(), _1.clone(), _0.clone(), _0.clone(),
            _0.clone(), _0.clone(), _1.clone(), _0.clone(),
            _0.clone(), _0.clone(), _0.clone(), _1.clone())
}

#[test]
pub fn test_ortho() {
    let (left, right, bottom, top) = (0.0f32, 1.0f32, 0.1f32, 1.0f32);
    let (near, far) = (-1.0f32, 1.0f32);
    let result = ortho(left, right, bottom, top, near, far);
    let expected = Matrix4(2.0,  0.0,         0.0,  0.0,
                           0.0,  2.22222222,  0.0,  0.0,
                           0.0,  0.0,         -1.0, 0.0,
                           -1.0, -1.22222222, -0.0, 1.0);
    debug!("result={:?} expected={:?}", result, expected);
    assert!(result.approx_eq(&expected));
}

<|endoftext|>


<commit_before>use super::coordinates::{CoordinateSystem, Point};
use super::tensors::{
    ContravariantIndex, CovariantIndex, InnerProduct, InvTwoForm, Tensor, TwoForm,
};
use crate::typenum::consts::{U1, U2, U3};
use crate::typenum::{Exp, Pow};
use generic_array::ArrayLength;

/// Trait representing the metric properties of the coordinate system
pub trait MetricSystem: CoordinateSystem
where
    <Self as CoordinateSystem>::Dimension: Pow<U2> + Pow<U3>,
    Exp<<Self as CoordinateSystem>::Dimension, U2>: ArrayLength<f64>,
    Exp<<Self as CoordinateSystem>::Dimension, U3>: ArrayLength<f64>,
{
    /// Returns the metric tensor at a given point.
    fn g(point: &Point<Self>) -> TwoForm<Self>;

    /// Returns the inverse metric tensor at a given point.
    ///
    /// The default implementation calculates the metric and then inverts it. A direct
    /// implementation may be desirable for more performance.
    fn inv_g(point: &Point<Self>) -> InvTwoForm<Self> {
        Self::g(point).inverse().unwrap()
    }

    /// Returns the partial derivatives of the metric at a given point.
    ///
    /// The default implementation calculates them numerically. A direct implementation
    /// may be desirable for performance.
    fn dg(point: &Point<Self>) -> Tensor<Self, (CovariantIndex, (CovariantIndex, CovariantIndex))> {
        let d = Self::dimension();
        let mut result = Tensor::zero(point.clone());
        let h = Self::small(point);

        for j in 0..d {
            let mut x = point.clone();
            x[j] = x[j] - h;
            let g1 = Self::g(&x);

            x[j] = x[j] + h * 2.0;
            let g2 = Self::g(&x);

            for coord in g1.iter_coords() {
                // calculate dg_i/dx^j
                let index = [coord[0], coord[1], j];
                result[&index[..]] = (g2[&*coord] - g1[&*coord]) / (2.0 * h);
            }
        }

        result
    }

    /// Returns the covariant Christoffel symbols (with three lower indices).
    ///
    /// The default implementation calculates them from the metric. A direct implementation
    /// may be desirable for performance.
    fn covariant_christoffel(
        point: &Point<Self>,
    ) -> Tensor<Self, (CovariantIndex, (CovariantIndex, CovariantIndex))> {
        let dg = Self::dg(point);
        let mut result =
            Tensor::<Self, (CovariantIndex, (CovariantIndex, CovariantIndex))>::zero(point.clone());

        for i in result.iter_coords() {
            result[&*i] =
                0.5 * (dg[&*i] + dg[&[i[0], i[2], i[1]][..]] - dg[&[i[1], i[2], i[0]][..]]);
        }

        result
    }

    /// Returns the Christoffel symbols.
    ///
    /// The default implementation calculates them from the metric. A direct implementation
    /// may be desirable for performance.
    fn christoffel(
        point: &Point<Self>,
    ) -> Tensor<Self, (ContravariantIndex, (CovariantIndex, CovariantIndex))> {
        let ig = Self::inv_g(point);
        let gamma = Self::covariant_christoffel(point);

        <InvTwoForm<Self> as InnerProduct<
            Tensor<Self, (CovariantIndex, (CovariantIndex, CovariantIndex))>,
            U1,
            U2,
        >>::inner_product(ig, gamma)
    }
}
<commit_msg>Implement vector and covector square and normalization<commit_after>use super::coordinates::{CoordinateSystem, Point};
use super::tensors::{
    ContravariantIndex, CovariantIndex, InnerProduct, InvTwoForm, Tensor, TwoForm,
};
use crate::inner;
use crate::typenum::consts::{U0, U1, U2, U3};
use crate::typenum::{Exp, Pow, Unsigned};
use generic_array::ArrayLength;

/// Trait representing the metric properties of the coordinate system
pub trait MetricSystem: CoordinateSystem
where
    <Self as CoordinateSystem>::Dimension: Pow<U2> + Pow<U3>,
    Exp<<Self as CoordinateSystem>::Dimension, U2>: ArrayLength<f64>,
    Exp<<Self as CoordinateSystem>::Dimension, U3>: ArrayLength<f64>,
{
    /// Returns the metric tensor at a given point.
    fn g(point: &Point<Self>) -> TwoForm<Self>;

    /// Returns the inverse metric tensor at a given point.
    ///
    /// The default implementation calculates the metric and then inverts it. A direct
    /// implementation may be desirable for more performance.
    fn inv_g(point: &Point<Self>) -> InvTwoForm<Self> {
        Self::g(point).inverse().unwrap()
    }

    /// Returns the partial derivatives of the metric at a given point.
    ///
    /// The default implementation calculates them numerically. A direct implementation
    /// may be desirable for performance.
    fn dg(point: &Point<Self>) -> Tensor<Self, (CovariantIndex, (CovariantIndex, CovariantIndex))> {
        let d = Self::dimension();
        let mut result = Tensor::zero(point.clone());
        let h = Self::small(point);

        for j in 0..d {
            let mut x = point.clone();
            x[j] = x[j] - h;
            let g1 = Self::g(&x);

            x[j] = x[j] + h * 2.0;
            let g2 = Self::g(&x);

            for coord in g1.iter_coords() {
                // calculate dg_i/dx^j
                let index = [coord[0], coord[1], j];
                result[&index[..]] = (g2[&*coord] - g1[&*coord]) / (2.0 * h);
            }
        }

        result
    }

    /// Returns the covariant Christoffel symbols (with three lower indices).
    ///
    /// The default implementation calculates them from the metric. A direct implementation
    /// may be desirable for performance.
    fn covariant_christoffel(
        point: &Point<Self>,
    ) -> Tensor<Self, (CovariantIndex, (CovariantIndex, CovariantIndex))> {
        let dg = Self::dg(point);
        let mut result =
            Tensor::<Self, (CovariantIndex, (CovariantIndex, CovariantIndex))>::zero(point.clone());

        for i in result.iter_coords() {
            result[&*i] =
                0.5 * (dg[&*i] + dg[&[i[0], i[2], i[1]][..]] - dg[&[i[1], i[2], i[0]][..]]);
        }

        result
    }

    /// Returns the Christoffel symbols.
    ///
    /// The default implementation calculates them from the metric. A direct implementation
    /// may be desirable for performance.
    fn christoffel(
        point: &Point<Self>,
    ) -> Tensor<Self, (ContravariantIndex, (CovariantIndex, CovariantIndex))> {
        let ig = Self::inv_g(point);
        let gamma = Self::covariant_christoffel(point);

        <InvTwoForm<Self> as InnerProduct<
            Tensor<Self, (CovariantIndex, (CovariantIndex, CovariantIndex))>,
            U1,
            U2,
        >>::inner_product(ig, gamma)
    }
}

impl<T> Tensor<T, ContravariantIndex>
where
    T: MetricSystem,
    T::Dimension: Pow<U1> + Pow<U2> + Pow<U3> + Unsigned,
    Exp<T::Dimension, U1>: ArrayLength<f64>,
    Exp<T::Dimension, U2>: ArrayLength<f64>,
    Exp<T::Dimension, U3>: ArrayLength<f64>,
{
    pub fn square(&self) -> f64 {
        let g = T::g(self.get_point());
        let temp = inner!(_, _; U1, U2; g, self.clone());
        *inner!(_, _; U0, U1; temp, self.clone())
    }

    pub fn normalize(&mut self) {
        let len = self.square().abs().sqrt();
        for i in 0..T::Dimension::to_usize() {
            self[i] /= len;
        }
    }
}

impl<T> Tensor<T, CovariantIndex>
where
    T: MetricSystem,
    T::Dimension: Pow<U1> + Pow<U2> + Pow<U3> + Unsigned,
    Exp<T::Dimension, U1>: ArrayLength<f64>,
    Exp<T::Dimension, U2>: ArrayLength<f64>,
    Exp<T::Dimension, U3>: ArrayLength<f64>,
{
    pub fn square(&self) -> f64 {
        let g = T::inv_g(self.get_point());
        let temp = inner!(_, _; U1, U2; g, self.clone());
        *inner!(_, _; U0, U1; temp, self.clone())
    }

    pub fn normalize(&mut self) {
        let len = self.square().abs().sqrt();
        for i in 0..T::Dimension::to_usize() {
            self[i] /= len;
        }
    }
}
<|endoftext|>


<commit_before>use std::io::{Read, BufRead, Error as IoError, ErrorKind};
use std::str::{from_utf8, Utf8Error};

use num::bigint::{BigInt, ToBigInt, Sign, ParseBigIntError};
use byteorder::{ReadBytesExt, LittleEndian, Error as ByteorderError};

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        ReadError(err: ByteorderError) {
            from()
        }
        IoError(err: IoError) {
            from()
        }
        UnknownOpcode(opcode: u8) {}
        InvalidInt {
            from(Utf8Error)
            from(ParseBigIntError)
        }
        InvalidString
        ExpectedTrailingL
        InvalidLong
    }
}

#[derive(Debug)]
pub enum OpCode {
    Int(BigInt),
    BinInt(i32),
    BinInt1(u8),
    BinInt2(u16),
    Long(BigInt),
    Long1(BigInt),
    Long4(BigInt),

    String(Vec<u8>),
    BinString(Vec<u8>),
    ShortBinString(Vec<u8>),

    None,

    NewTrue,
    NewFalse,

    Unicode(String),
    BinUnicode(String),

    Float(f64),
    BinFloat(f64),

    EmptyList,
    Append,
    Appends,
    List,

    EmptyTuple,
    Tuple,
    Tuple1,
    Tuple2,
    Tuple3,

    EmptyDict,
    Dict,
    SetItem,
    SetItems,

    Pop,
    Dup,
    Mark,
    PopMark,

    Get(usize),
    BinGet(usize),
    LongBinGet(usize),
    Put(usize),
    BinPut(usize),
    LongBinPut(usize),

    Ext1(u8),
    Ext2(u16),
    Ext4(i32),

    Global(Vec<u8>, Vec<u8>),
    Reduce,
    Build,
    Inst(Vec<u8>, Vec<u8>),
    Obj,
    NewObj,
    Proto(u8),
    Stop,
    PersId(Vec<u8>),
    BinPersId,
}

fn read_exact<R>(rd: &mut R, mut buf: &mut [u8]) -> Result<(), IoError> where R: Read {
    while !buf.is_empty() {
        match rd.read(buf) {
            Ok(0) => break,
            Ok(n) => { let tmp = buf; buf = &mut tmp[n..]; }
            Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
            Err(e) => return Err(e),
        }
    }
    if !buf.is_empty() {
        Err(IoError::new(ErrorKind::Other,
                       "failed to fill whole buffer"))
    } else {
        Ok(())
    }
}

pub fn read_until_newline<R>(rd: &mut R) -> Result<Vec<u8>, Error> where R: Read + BufRead {
    let mut buf = Vec::new();
    try!(rd.read_until('\n' as u8, &mut buf));

    // Skip last symbol — \n
    match buf.split_last() {
        None => Err(Error::InvalidString),
        Some((_last, init)) => Ok(init.to_vec()),
    }
}

pub fn read_long<R>(rd: &mut R, length: usize) -> Result<BigInt, Error> where R: Read + BufRead {
    let mut buf = vec![0; length];
    try!(read_exact(rd, buf.as_mut()));

    let mut n = BigInt::from_bytes_le(Sign::Plus, &buf);

    let last = match buf.last_mut() {
        None => return Err(Error::InvalidLong),
        Some(last) => last,
    };

    if *last > 127 {
        n = n - (1.to_bigint().unwrap() << (length * 8))
    }

    Ok(n)
}

pub fn read_opcode<R>(rd: &mut R) -> Result<OpCode, Error> where R: Read + BufRead {
    let marker = try!(rd.read_u8());
    return Ok(match marker {
        73 => {
            let s = try!(read_until_newline(rd));
            OpCode::Int(try!(try!(from_utf8(&s)).parse()))  // http://rust-num.github.io/num/num/bigint/struct.BigInt.html#method.parse_bytes
        },
        74 => OpCode::BinInt(try!(rd.read_i32::<LittleEndian>())),
        75 => OpCode::BinInt1(try!(rd.read_u8())),
        77 => OpCode::BinInt2(try!(rd.read_u16::<LittleEndian>())),
        76 => {
            let s = try!(read_until_newline(rd));

            let init = match s.split_last() {
                None => return Err(Error::InvalidString),
                Some((&76, init)) => init,
                Some(_) => return Err(Error::ExpectedTrailingL),
            };

            OpCode::Long(try!(try!(from_utf8(init)).parse()))
        },
        138 => {
            let length = try!(rd.read_u8());
            OpCode::Long1(try!(read_long(rd, length as usize)))

        },
        139 => {
            let length = try!(rd.read_i32::<LittleEndian>());
            OpCode::Long4(try!(read_long(rd, length as usize)))

        },
        83 => {OpCode::String(try!(read_until_newline(rd)))} // TODO: escaping
        84 => {
            let length = try!(rd.read_i32::<LittleEndian>());
            let mut buf = vec![0; length as usize];
            try!(read_exact(rd, &mut buf));
            OpCode::BinString(buf)
        }
        85 => {
            let length = try!(rd.read_u8());
            let mut buf = vec![0; length as usize];
            try!(read_exact(rd, &mut buf));
            OpCode::ShortBinString(buf)
        }
        78 => OpCode::None,
        136 => OpCode::NewTrue,
        137 => OpCode::NewFalse,
        c => return Err(Error::UnknownOpcode(c)),
    })
}

#[cfg(test)]
mod tests {
    use std::io::{Cursor};

    use num::{FromPrimitive};

    use super::{OpCode, Error, read_opcode};

    macro_rules! t {
        ($buffer: expr, $pat:pat, $result:expr) => ({
            match read_opcode(&mut Cursor::new(&$buffer[..])) {
                $pat => $result,
                other => {
                    println!("ERROR {:?}", other);
                    assert!(false)
                },
            }
        })
    }

    macro_rules! n {
        ($x: expr) => ({FromPrimitive::from_isize($x).unwrap()})
    }

    #[test]
    fn test_int() {
        t!(b"I", Err(Error::InvalidString), assert!(true));
        t!(b"I\n", Err(Error::InvalidInt), assert!(true));
        t!(b"Iabc\n", Err(Error::InvalidInt), assert!(true));
        t!(b"I123\n", Ok(OpCode::Int(n)), assert_eq!(n, n!(123)));
    }

    #[test]
    fn test_bin_int() {
        t!(b"J\x0a", Err(Error::ReadError(_)), assert!(true));
        t!(b"J\x0a\x00\x00\x00", Ok(OpCode::BinInt(n)), assert_eq!(n, 10));
        t!(b"J\x0a\x00\x00\x01", Ok(OpCode::BinInt(n)), assert_eq!(n, 16777226));
    }

    #[test]
    fn test_bin_int1() {
        t!(b"K", Err(Error::ReadError(_)), assert!(true));
        t!(b"K\x0a", Ok(OpCode::BinInt1(n)), assert_eq!(n, 10));
    }

    #[test]
    fn test_bin_int2() {
        t!(b"M\x0a", Err(Error::ReadError(_)), assert!(true));
        t!(b"M\x0a\x00\x00\x00", Ok(OpCode::BinInt2(n)), assert_eq!(n, 10));
        t!(b"M\x0a\x01\x00\x00", Ok(OpCode::BinInt2(n)), assert_eq!(n, 266));
    }

    #[test]
    fn test_long() {
        t!(b"L", Err(Error::InvalidString), assert!(true));
        t!(b"L\n", Err(Error::InvalidString), assert!(true));
        t!(b"Labc\n", Err(Error::ExpectedTrailingL), assert!(true));
        t!(b"LabcL\n", Err(Error::InvalidInt), assert!(true));
        t!(b"L123L\n", Ok(OpCode::Long(n)), assert_eq!(n, n!(123)));
    }

    #[test]
    fn test_long1() {
        t!(b"\x8a", Err(Error::ReadError(_)), assert!(true));
        t!(b"\x8a\x01\x0a", Ok(OpCode::Long1(n)), assert_eq!(n, n!(10)));
        t!(b"\x8a\x01\xf6", Ok(OpCode::Long1(n)), assert_eq!(n, n!(-10)));
        t!(b"\x8a\x02.\xfb", Ok(OpCode::Long1(n)), assert_eq!(n, n!(-1234)));
    }

    #[test]
    fn test_long4() {
        t!(b"\x8b\x0a", Err(Error::ReadError(_)), assert!(true));
        t!(b"\x8b\x01\x00\x00\x00\x0a", Ok(OpCode::Long4(n)), assert_eq!(n, n!(10)));
        t!(b"\x8b\x01\x00\x00\x00\xf6", Ok(OpCode::Long4(n)), assert_eq!(n, n!(-10)));
        t!(b"\x8b\x02\x00\x00\x00.\xfb", Ok(OpCode::Long4(n)), assert_eq!(n, n!(-1234)));
    }

    #[test]
    fn test_string() {
        t!(b"S", Err(Error::InvalidString), assert!(true));
        t!(b"S\n", Ok(OpCode::String(s)), assert_eq!(s, b""));
        t!(b"Sabc\n", Ok(OpCode::String(s)), assert_eq!(s, b"abc"));
        t!(b"S123\n", Ok(OpCode::String(s)), assert_eq!(s, b"123"));
        t!(b"S\\n\n", Ok(OpCode::String(s)), assert_eq!(s, b"\\n"));
    }

    #[test]
    fn test_bin_string() {
        t!(b"T\x00\x00\x00\x00", Ok(OpCode::BinString(s)), assert_eq!(s, b""));
        t!(b"T\x03\x00\x00\x00abc", Ok(OpCode::BinString(s)), assert_eq!(s, b"abc"));
        t!(b"T\x03\x00\x00\x00123", Ok(OpCode::BinString(s)), assert_eq!(s, b"123"));
        t!(b"T\x02\x00\x00\x00\\n", Ok(OpCode::BinString(s)), assert_eq!(s, b"\\n"));
    }

    #[test]
    fn test_short_bin_string() {
        t!(b"U\x00", Ok(OpCode::ShortBinString(s)), assert_eq!(s, b""));
        t!(b"U\x03abc", Ok(OpCode::ShortBinString(s)), assert_eq!(s, b"abc"));
        t!(b"U\x03123", Ok(OpCode::ShortBinString(s)), assert_eq!(s, b"123"));
        t!(b"U\x02\\n", Ok(OpCode::ShortBinString(s)), assert_eq!(s, b"\\n"));
    }

    #[test]
    fn test_none() {
        t!(b"N", Ok(OpCode::None), assert!(true));
    }

    #[test]
    fn test_new_true() {
        t!(b"\x88", Ok(OpCode::NewTrue), assert!(true));
    }

    #[test]
    fn test_new_false() {
        t!(b"\x89", Ok(OpCode::NewFalse), assert!(true));
    }
}
<commit_msg>Check negative length<commit_after>use std::io::{Read, BufRead, Error as IoError, ErrorKind};
use std::str::{from_utf8, Utf8Error};

use num::bigint::{BigInt, ToBigInt, Sign, ParseBigIntError};
use byteorder::{ReadBytesExt, LittleEndian, Error as ByteorderError};

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        ReadError(err: ByteorderError) {
            from()
        }
        IoError(err: IoError) {
            from()
        }
        UnknownOpcode(opcode: u8) {}
        InvalidInt {
            from(Utf8Error)
            from(ParseBigIntError)
        }
        InvalidString
        ExpectedTrailingL
        InvalidLong
        NegativeLength
    }
}

#[derive(Debug)]
pub enum OpCode {
    Int(BigInt),
    BinInt(i32),
    BinInt1(u8),
    BinInt2(u16),
    Long(BigInt),
    Long1(BigInt),
    Long4(BigInt),

    String(Vec<u8>),
    BinString(Vec<u8>),
    ShortBinString(Vec<u8>),

    None,

    NewTrue,
    NewFalse,

    Unicode(String),
    BinUnicode(String),

    Float(f64),
    BinFloat(f64),

    EmptyList,
    Append,
    Appends,
    List,

    EmptyTuple,
    Tuple,
    Tuple1,
    Tuple2,
    Tuple3,

    EmptyDict,
    Dict,
    SetItem,
    SetItems,

    Pop,
    Dup,
    Mark,
    PopMark,

    Get(usize),
    BinGet(usize),
    LongBinGet(usize),
    Put(usize),
    BinPut(usize),
    LongBinPut(usize),

    Ext1(u8),
    Ext2(u16),
    Ext4(i32),

    Global(Vec<u8>, Vec<u8>),
    Reduce,
    Build,
    Inst(Vec<u8>, Vec<u8>),
    Obj,
    NewObj,
    Proto(u8),
    Stop,
    PersId(Vec<u8>),
    BinPersId,
}

fn read_exact<R>(rd: &mut R, mut buf: &mut [u8]) -> Result<(), IoError> where R: Read {
    while !buf.is_empty() {
        match rd.read(buf) {
            Ok(0) => break,
            Ok(n) => { let tmp = buf; buf = &mut tmp[n..]; }
            Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
            Err(e) => return Err(e),
        }
    }
    if !buf.is_empty() {
        Err(IoError::new(ErrorKind::Other,
                       "failed to fill whole buffer"))
    } else {
        Ok(())
    }
}

pub fn read_until_newline<R>(rd: &mut R) -> Result<Vec<u8>, Error> where R: Read + BufRead {
    let mut buf = Vec::new();
    try!(rd.read_until('\n' as u8, &mut buf));

    // Skip last symbol — \n
    match buf.split_last() {
        None => Err(Error::InvalidString),
        Some((_last, init)) => Ok(init.to_vec()),
    }
}

pub fn read_long<R>(rd: &mut R, length: usize) -> Result<BigInt, Error> where R: Read + BufRead {
    let mut buf = vec![0; length];
    try!(read_exact(rd, buf.as_mut()));

    let mut n = BigInt::from_bytes_le(Sign::Plus, &buf);

    let last = match buf.last_mut() {
        None => return Err(Error::InvalidLong),
        Some(last) => last,
    };

    if *last > 127 {
        n = n - (1.to_bigint().unwrap() << (length * 8))
    }

    Ok(n)
}

pub fn read_opcode<R>(rd: &mut R) -> Result<OpCode, Error> where R: Read + BufRead {
    let marker = try!(rd.read_u8());
    return Ok(match marker {
        73 => {
            let s = try!(read_until_newline(rd));
            OpCode::Int(try!(try!(from_utf8(&s)).parse()))  // http://rust-num.github.io/num/num/bigint/struct.BigInt.html#method.parse_bytes
        },
        74 => OpCode::BinInt(try!(rd.read_i32::<LittleEndian>())),
        75 => OpCode::BinInt1(try!(rd.read_u8())),
        77 => OpCode::BinInt2(try!(rd.read_u16::<LittleEndian>())),
        76 => {
            let s = try!(read_until_newline(rd));

            let init = match s.split_last() {
                None => return Err(Error::InvalidString),
                Some((&76, init)) => init,
                Some(_) => return Err(Error::ExpectedTrailingL),
            };

            OpCode::Long(try!(try!(from_utf8(init)).parse()))
        },
        138 => {
            let length = try!(rd.read_u8());
            OpCode::Long1(try!(read_long(rd, length as usize)))

        },
        139 => {
            let length = try!(rd.read_i32::<LittleEndian>());
            if length < 0 {
                return Err(Error::NegativeLength)
            }
            OpCode::Long4(try!(read_long(rd, length as usize)))

        },
        83 => {OpCode::String(try!(read_until_newline(rd)))} // TODO: escaping
        84 => {
            let length = try!(rd.read_i32::<LittleEndian>());
            if length < 0 {
                return Err(Error::NegativeLength)
            }
            let mut buf = vec![0; length as usize];
            try!(read_exact(rd, &mut buf));
            OpCode::BinString(buf)
        }
        85 => {
            let length = try!(rd.read_u8());
            let mut buf = vec![0; length as usize];
            try!(read_exact(rd, &mut buf));
            OpCode::ShortBinString(buf)
        }
        78 => OpCode::None,
        136 => OpCode::NewTrue,
        137 => OpCode::NewFalse,
        c => return Err(Error::UnknownOpcode(c)),
    })
}

#[cfg(test)]
mod tests {
    use std::io::{Cursor};

    use num::{FromPrimitive};

    use super::{OpCode, Error, read_opcode};

    macro_rules! t {
        ($buffer: expr, $pat:pat, $result:expr) => ({
            match read_opcode(&mut Cursor::new(&$buffer[..])) {
                $pat => $result,
                other => {
                    println!("ERROR {:?}", other);
                    assert!(false)
                },
            }
        })
    }

    macro_rules! n {
        ($x: expr) => ({FromPrimitive::from_isize($x).unwrap()})
    }

    #[test]
    fn test_int() {
        t!(b"I", Err(Error::InvalidString), assert!(true));
        t!(b"I\n", Err(Error::InvalidInt), assert!(true));
        t!(b"Iabc\n", Err(Error::InvalidInt), assert!(true));
        t!(b"I123\n", Ok(OpCode::Int(n)), assert_eq!(n, n!(123)));
    }

    #[test]
    fn test_bin_int() {
        t!(b"J\x0a", Err(Error::ReadError(_)), assert!(true));
        t!(b"J\x0a\x00\x00\x00", Ok(OpCode::BinInt(n)), assert_eq!(n, 10));
        t!(b"J\x0a\x00\x00\x01", Ok(OpCode::BinInt(n)), assert_eq!(n, 16777226));
    }

    #[test]
    fn test_bin_int1() {
        t!(b"K", Err(Error::ReadError(_)), assert!(true));
        t!(b"K\x0a", Ok(OpCode::BinInt1(n)), assert_eq!(n, 10));
    }

    #[test]
    fn test_bin_int2() {
        t!(b"M\x0a", Err(Error::ReadError(_)), assert!(true));
        t!(b"M\x0a\x00\x00\x00", Ok(OpCode::BinInt2(n)), assert_eq!(n, 10));
        t!(b"M\x0a\x01\x00\x00", Ok(OpCode::BinInt2(n)), assert_eq!(n, 266));
    }

    #[test]
    fn test_long() {
        t!(b"L", Err(Error::InvalidString), assert!(true));
        t!(b"L\n", Err(Error::InvalidString), assert!(true));
        t!(b"Labc\n", Err(Error::ExpectedTrailingL), assert!(true));
        t!(b"LabcL\n", Err(Error::InvalidInt), assert!(true));
        t!(b"L123L\n", Ok(OpCode::Long(n)), assert_eq!(n, n!(123)));
    }

    #[test]
    fn test_long1() {
        t!(b"\x8a", Err(Error::ReadError(_)), assert!(true));
        t!(b"\x8a\x01\x0a", Ok(OpCode::Long1(n)), assert_eq!(n, n!(10)));
        t!(b"\x8a\x01\xf6", Ok(OpCode::Long1(n)), assert_eq!(n, n!(-10)));
        t!(b"\x8a\x02.\xfb", Ok(OpCode::Long1(n)), assert_eq!(n, n!(-1234)));
    }

    #[test]
    fn test_long4() {
        t!(b"\x8b\xff\xff\xff\xff", Err(Error::NegativeLength), assert!(true));
        t!(b"\x8b\x0a", Err(Error::ReadError(_)), assert!(true));
        t!(b"\x8b\x01\x00\x00\x00\x0a", Ok(OpCode::Long4(n)), assert_eq!(n, n!(10)));
        t!(b"\x8b\x01\x00\x00\x00\xf6", Ok(OpCode::Long4(n)), assert_eq!(n, n!(-10)));
        t!(b"\x8b\x02\x00\x00\x00.\xfb", Ok(OpCode::Long4(n)), assert_eq!(n, n!(-1234)));
    }

    #[test]
    fn test_string() {
        t!(b"S", Err(Error::InvalidString), assert!(true));
        t!(b"S\n", Ok(OpCode::String(s)), assert_eq!(s, b""));
        t!(b"Sabc\n", Ok(OpCode::String(s)), assert_eq!(s, b"abc"));
        t!(b"S123\n", Ok(OpCode::String(s)), assert_eq!(s, b"123"));
        t!(b"S\\n\n", Ok(OpCode::String(s)), assert_eq!(s, b"\\n"));
    }

    #[test]
    fn test_bin_string() {
        t!(b"T\xff\xff\xff\xff", Err(Error::NegativeLength), assert!(true));
        t!(b"T\x00\x00\x00\x00", Ok(OpCode::BinString(s)), assert_eq!(s, b""));
        t!(b"T\x03\x00\x00\x00abc", Ok(OpCode::BinString(s)), assert_eq!(s, b"abc"));
        t!(b"T\x03\x00\x00\x00123", Ok(OpCode::BinString(s)), assert_eq!(s, b"123"));
        t!(b"T\x02\x00\x00\x00\\n", Ok(OpCode::BinString(s)), assert_eq!(s, b"\\n"));
    }

    #[test]
    fn test_short_bin_string() {
        t!(b"U\x00", Ok(OpCode::ShortBinString(s)), assert_eq!(s, b""));
        t!(b"U\x03abc", Ok(OpCode::ShortBinString(s)), assert_eq!(s, b"abc"));
        t!(b"U\x03123", Ok(OpCode::ShortBinString(s)), assert_eq!(s, b"123"));
        t!(b"U\x02\\n", Ok(OpCode::ShortBinString(s)), assert_eq!(s, b"\\n"));
    }

    #[test]
    fn test_none() {
        t!(b"N", Ok(OpCode::None), assert!(true));
    }

    #[test]
    fn test_new_true() {
        t!(b"\x88", Ok(OpCode::NewTrue), assert!(true));
    }

    #[test]
    fn test_new_false() {
        t!(b"\x89", Ok(OpCode::NewFalse), assert!(true));
    }
}
<|endoftext|>


<commit_before>/*
use lexer::{TokenType, ArmorToken, ArmorLexer};

pub struct ArmorParser<'a> {
    input:          ArmorLexer<'a>,
    lookahead_size: usize,           // How many lookahead symbols?
    lookahead:      Vec<ArmorToken>,
    p:              usize,
}

impl<'a> ArmorParser<'a> {
    fn new(mut input: ArmorLexer<'a>, n: usize) -> ArmorParser<'a> {
        let mut lookahead = Vec::with_capacity(n);
        let mut p = 0;
        // Initialize buffer.
        loop {
            let token = input.next_token();
            match token {
                Some(val) => {
                    lookahead.push(val);
                    p += 1;
                }
                None => break,
            }
        }

        ArmorParser {
            input: input,
            lookahead: lookahead,
            lookahead_size: n,
            p: p,
        }
    }

    #[inline]
    fn consume(&mut self) -> Result<(), ()> {
        let next_token = self.input.next_token();
        match next_token {
            Some(token) => {
                self.lookahead[self.p] = token;
                self.p = (self.p + 1) % self.lookahead_size;
                Ok(())
            }
            None => Err(()),
        }
    }

    #[inline]
    pub fn lookahead_token(&self, i: usize) -> ArmorToken {
        self.lookahead[(self.p+i-1) % self.lookahead_size]
    }

    #[inline]
    pub fn lookahead_type(&self, i: usize) -> TokenType {
        self.lookahead_token(i).token_type()
    }

    pub fn match_token(&mut self, token_type: TokenType) -> Result<ArmorToken, String> {
        if self.lookahead_type(1) == token_type {
            let token = self.lookahead_token(1);
            self.consume();
            Ok(token)
        } else {
            let err_str = format!("Expecting: {:?}; Found {:?}", token_type, self.lookahead_token(1));
            Err(err_str)
        }
    }

    pub fn upper_case_letter(&mut self) -> Result<ArmorToken, ()> {
        let token = self.lookahead_token(1);
        if token.is_upper_case() {
            self.consume();
            Ok(token)
        } else {
            Err(())
        }
    }

    pub fn lower_case_letter(&mut self) -> Result<ArmorToken, ()> {
        let token = self.lookahead_token(1);
        if token.is_lower_case() {
            self.consume();
            Ok(token)
        } else {
            Err(())
        }
    }

    pub fn letter(&mut self) -> Result<ArmorToken, ()> {
        let token = self.lookahead_token(1);
        if token.is_letter() {
            self.consume();
            Ok(token)
        } else {
            Err(())
        }
    }

    pub fn digit(&mut self) -> Result<ArmorToken, ()> {
        let token = self.lookahead_token(1);
        if token.is_digit() {
            self.consume();
            Ok(token)
        } else {
            Err(())
        }
    }

    pub fn whitespace(&mut self) -> Result<ArmorToken, ()> {
        let token = self.lookahead_token(1);
        if token.is_whitespace() {
            self.consume();
            Ok(token)
        } else {
            Err(())
        }
    }

    pub fn number(&mut self) -> Result<String, ()> {
        let mut parsed_number = String::new();

        loop {
            let result = self.digit();
            match result {
                Ok(token) => {
                    parsed_number.push(token.token());
                }
                Err(_) => {
                    break;
                }
            }
        }

        if parsed_number.is_empty() {
            return Err(());
        }

        Ok(parsed_number)
    }

    pub fn pad(&mut self) -> Result<ArmorToken, ()> {
        let token = self.lookahead_token(1);
        if token.is_equal_sign() {
            self.consume();
            Ok(token)
        } else {
            Err(())
        }
    }

    pub fn blank_line(&mut self) -> Result<String, ()> {
        let mut parsed_blank = String::new();

        loop {
            let token = self.lookahead_token(1);
            if token.is_whitespace() {
                self.consume();
                parsed_blank.push(token.token());
            }
        }

        let last_token = self.lookahead_token(1);
        if last_token.is_newline() {
            self.consume();
            parsed_blank.push(last_token.token());

            Ok(parsed_blank)
        } else {
            Err(())
        }
    }
}

#[cfg(test)]
mod tests {

}
*/<commit_msg>Define Armor parser.<commit_after>use lexer::{Lexer, Token, TokenType};

pub struct Parser<S> where S: Iterator<Item = char> {
    input:          Lexer<S>,
    lookahead_size: usize,           // How many lookahead symbols?
    lookahead:      Vec<Token>,
    p:              usize,
}

impl<S> Parser<S>  where S: Iterator<Item = char> {
    pub fn new(mut input: Lexer<S>, n: usize) -> Parser<S> {
        let mut lookahead = Vec::with_capacity(n);
        let mut p = 0;
        // Initialize buffer.
        loop {
            let next_token = input.next();
            match next_token {
                Some(token) => {
                    lookahead.push(token);
                    p += 1;
                }
                None => break
            }
        }

        Parser {
            input: input,
            lookahead: lookahead,
            lookahead_size: n,
            p: p,
        }
    }
}

#[cfg(test)]
mod tests {

}
<|endoftext|>


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

use chomp::types::{Buffer, U8Input, ParseResult};
use chomp::ascii::{is_alpha, is_alphanumeric};
use chomp::parsers::{SimpleResult, Error, any, token, satisfy, string, take_while, skip_while};
use chomp::combinators::{many_till, many, option, or};

pub type Name = String;
pub type SelectionSet = Vec<Selection>;

#[derive(Debug,PartialEq)]
pub struct Document {
  definitions: Vec<Definition>,
}

#[derive(Debug,PartialEq)]
pub enum Definition {
  OperationDefinition(Operation),
  SelectionSetDefinition(SelectionSet),
  FragmentDefinition(Fragment),
}

#[derive(Debug,PartialEq)]
pub struct Operation {
  op_type: OperationType,
  name: Option<Name>,
  variable_definitions: Vec<VariableDefinition>,
  directives: Vec<Directive>,
}

impl Operation {
  fn new(op_type: OperationType, name: Option<Name>, variable_definitions: Vec<VariableDefinition>, directives: Vec<Directive>) -> Operation {
    Operation { op_type: op_type, name: name, variable_definitions: variable_definitions, directives: directives }
  }
}

#[derive(Debug,PartialEq)]
pub enum OperationType {
  Query,
  Mutation,
}

#[derive(Debug,PartialEq)]
pub struct VariableDefinition {
  variable: Variable,
  var_type: Type,
  default_value: Option<Value>,
}

type Variable = String;

#[derive(Debug,PartialEq)]
pub enum Type {
  NamedType(Name),
  ListType(Box<Type>),
  NonNullType(Box<Type>),
}

#[derive(Debug,PartialEq)]
pub enum Value {
  Var(Variable),
  IntValue(i32),
  FloatValue(f32),
  StringValue(String),
  BooleanValue(bool),
  NullValue,
  EnumValue(String),
  ListValue(Vec<Value>),
  ObjectValue(HashMap<String, Value>),
}

#[derive(Debug,PartialEq)]
pub struct Directive {
  name: Name,
  arguments: Vec<Argument>,
}

#[derive(Debug,PartialEq)]
pub struct Argument {
  name: Name,
  value: Value,
}

#[derive(Debug,PartialEq)]
pub enum Selection {
  FieldSelection(Field),
  FragmentSpread(Name, Vec<Directive>),
  InlineFragment(Option<Type>, Vec<Directive>, SelectionSet),
}

#[derive(Debug,PartialEq)]
pub struct Field {
  alias: Option<Name>,
  name: Name,
  arguments: Vec<Argument>,
  directives: Vec<Directive>,
  selection_set: SelectionSet,
}

impl Field {
  fn new(alias: Option<Name>, name: Name, arguments: Vec<Argument>, directives: Vec<Directive>, selection_set: SelectionSet) -> Field {
    Field { alias: alias, name: name, arguments: arguments, directives: directives, selection_set: selection_set }
  }
}

#[derive(Debug,PartialEq)]
pub struct Fragment {
  name: Name,
  type_condition: Type,
  directives: Vec<Directive>,
  selection_set: SelectionSet,
}

pub fn white_space<I: U8Input>(i: I) -> SimpleResult<I, ()>
{
  skip_while(i, |c| c == b' ' || c == b'\t')
}

pub fn line_terminator<I: U8Input>(i: I) -> SimpleResult<I, ()>
{
  parse!{i;
    string(b"\r\n") <|> string(b"\r") <|> string(b"\n") >> ret ()
  }
}

pub fn comment<I: U8Input>(i: I) -> SimpleResult<I, ()>
{
  parse!{i;
    token(b'#');
    let _rest: Vec<_> = many_till(any, line_terminator);
    ret ()
  }
}

pub fn comma<I: U8Input>(i: I) -> SimpleResult<I,u8>
{
  token(i, b',')
}

pub fn operation_definition<I: U8Input>(i: I) -> SimpleResult<I,Definition>
{
  parse!{i;
    let op_type = operation_type();
    white_space() <|> line_terminator();
    let name = option(|i| name(i).map(Some), None);

    ret {
      let op = Operation::new(op_type, name, Vec::new(), Vec::new());
      Definition::OperationDefinition(op)
    }
  }
}

pub fn operation_type<I: U8Input>(i: I) -> SimpleResult<I,OperationType>
{
  let op_type = |i,b,r| string(i,b).map(|_| r);
  parse!{i;
      op_type(b"query", OperationType::Query) <|>
      op_type(b"mutation", OperationType::Mutation)
  }
}

pub fn name<I: U8Input>(i: I) -> SimpleResult<I,Name>
{
  parse!{i;
    let start = satisfy(|c| is_alpha(c) || c == b'_');
    let rest = take_while(|c| is_alphanumeric(c) || c == b'_');

    ret {
      let mut start = String::from_utf8(vec![start]).unwrap();
      let rest = String::from_utf8(rest.to_vec()).unwrap();
      start.push_str(&rest);
      start
    }
  }
}

pub fn alias<I: U8Input>(i: I) -> SimpleResult<I, Option<Name>>
{
  // GRAMMAR:
  // name [white_space<|>line_terminator] :
  let parser: SimpleResult<I,Name> = parse!{i;
    name() <* (white_space() <|> line_terminator()) <* token(b':')
  };
  option(i, parser.map(Some), None)
}

#[cfg(test)]
mod tests {
  // use super::{OperationType, Operation, Definition white_space, line_terminator, comment, comma, operation_type, name, operation_definition};
  use super::*;
  use chomp::prelude::parse_only;

  #[test]
  fn test_parse_comment() {
    assert_eq!(parse_only(comment, b"#test\r"), Ok(()));
    assert_eq!(parse_only(comment, b"#test\n"), Ok(()));
    assert_eq!(parse_only(comment, b"#test\r\n"), Ok(()));
  }

  #[test]
  fn test_operation_type() {
    assert_eq!(parse_only(operation_type, b"query"), Ok(OperationType::Query));
    assert_eq!(parse_only(operation_type, b"mutation"), Ok(OperationType::Mutation));
  }
}
<commit_msg>working on issue #1<commit_after>use std::collections::HashMap;

use chomp::types::{Buffer, U8Input, ParseResult};
use chomp::ascii::{is_alpha, is_alphanumeric};
use chomp::parsers::{SimpleResult, Error, any, token, satisfy, string, take_while, skip_while};
use chomp::combinators::{many_till, many, option, either, or};

pub type Name = String;
pub type SelectionSet = Vec<Selection>;

#[derive(Debug,PartialEq)]
pub struct Document {
  definitions: Vec<Definition>,
}

#[derive(Debug,PartialEq)]
pub enum Definition {
  OperationDefinition(Operation),
  SelectionSetDefinition(SelectionSet),
  FragmentDefinition(Fragment),
}

#[derive(Debug,PartialEq)]
pub struct Operation {
  op_type: OperationType,
  name: Option<Name>,
  variable_definitions: Vec<VariableDefinition>,
  directives: Vec<Directive>,
}

impl Operation {
  fn new(op_type: OperationType, name: Option<Name>, variable_definitions: Vec<VariableDefinition>, directives: Vec<Directive>) -> Operation {
    Operation { op_type: op_type, name: name, variable_definitions: variable_definitions, directives: directives }
  }
}

#[derive(Debug,PartialEq)]
pub enum OperationType {
  Query,
  Mutation,
}

#[derive(Debug,PartialEq)]
pub struct VariableDefinition {
  variable: Variable,
  var_type: Type,
  default_value: Option<Value>,
}

type Variable = String;

#[derive(Debug,PartialEq)]
pub enum Type {
  NamedType(Name),
  ListType(Box<Type>),
  NonNullType(Box<Type>),
}

#[derive(Debug,PartialEq)]
pub enum Value {
  Var(Variable),
  IntValue(i32),
  FloatValue(f32),
  StringValue(String),
  BooleanValue(bool),
  NullValue,
  EnumValue(String),
  ListValue(Vec<Value>),
  ObjectValue(HashMap<String, Value>),
}

#[derive(Debug,PartialEq)]
pub struct Directive {
  name: Name,
  arguments: Vec<Argument>,
}

#[derive(Debug,PartialEq)]
pub struct Argument {
  name: Name,
  value: Value,
}

#[derive(Debug,PartialEq)]
pub enum Selection {
  FieldSelection(Field),
  FragmentSpread(Name, Vec<Directive>),
  InlineFragment(Option<Type>, Vec<Directive>, SelectionSet),
}

#[derive(Debug,PartialEq)]
pub struct Field {
  alias: Option<Name>,
  name: Name,
  arguments: Vec<Argument>,
  directives: Vec<Directive>,
  selection_set: SelectionSet,
}

impl Field {
  fn new(alias: Option<Name>, name: Name, arguments: Vec<Argument>, directives: Vec<Directive>, selection_set: SelectionSet) -> Field {
    Field { alias: alias, name: name, arguments: arguments, directives: directives, selection_set: selection_set }
  }
}

#[derive(Debug,PartialEq)]
pub struct Fragment {
  name: Name,
  type_condition: Type,
  directives: Vec<Directive>,
  selection_set: SelectionSet,
}

pub fn white_space<I: U8Input>(i: I) -> SimpleResult<I, ()>
{
  skip_while(i, |c| c == b' ' || c == b'\t')
}

pub fn line_terminator<I: U8Input>(i: I) -> SimpleResult<I, ()>
{
  parse!{i;
    string(b"\r\n") <|> string(b"\r") <|> string(b"\n") >> ret ()
  }
}

pub fn comment<I: U8Input>(i: I) -> SimpleResult<I, ()>
{
  parse!{i;
    token(b'#');
    let _rest: Vec<_> = many_till(any, line_terminator);
    ret ()
  }
}

pub fn comma<I: U8Input>(i: I) -> SimpleResult<I,u8>
{
  token(i, b',')
}

pub fn operation_definition<I: U8Input>(i: I) -> SimpleResult<I,Definition>
{
  parse!{i;
    let op_type = operation_type();
    white_space() <|> line_terminator();
    let name = option(|i| name(i).map(Some), None);

    ret {
      let op = Operation::new(op_type, name, Vec::new(), Vec::new());
      Definition::OperationDefinition(op)
    }
  }
}

pub fn operation_type<I: U8Input>(i: I) -> SimpleResult<I,OperationType>
{
  let op_type = |i,b,r| string(i,b).map(|_| r);
  parse!{i;
      op_type(b"query", OperationType::Query) <|>
      op_type(b"mutation", OperationType::Mutation)
  }
}

pub fn name<I: U8Input>(i: I) -> SimpleResult<I,Name>
{
  parse!{i;
    let start = satisfy(|c| is_alpha(c) || c == b'_');
    let rest = take_while(|c| is_alphanumeric(c) || c == b'_');

    ret {
      let mut start = String::from_utf8(vec![start]).unwrap();
      let rest = String::from_utf8(rest.to_vec()).unwrap();
      start.push_str(&rest);
      start
    }
  }
}

pub fn alias<I: U8Input>(i: I) -> SimpleResult<I, Option<Name>>
{
  let parser = parse!{i;
    let name = name();

    either(white_space, line_terminator);
    token(b':');

    ret Some(name)
  };

  option(i, parser, None)
}

#[cfg(test)]
mod tests {
  // use super::{OperationType, Operation, Definition white_space, line_terminator, comment, comma, operation_type, name, operation_definition};
  use super::*;
  use chomp::prelude::parse_only;

  #[test]
  fn test_parse_comment() {
    assert_eq!(parse_only(comment, b"#test\r"), Ok(()));
    assert_eq!(parse_only(comment, b"#test\n"), Ok(()));
    assert_eq!(parse_only(comment, b"#test\r\n"), Ok(()));
  }

  #[test]
  fn test_operation_type() {
    assert_eq!(parse_only(operation_type, b"query"), Ok(OperationType::Query));
    assert_eq!(parse_only(operation_type, b"mutation"), Ok(OperationType::Mutation));
  }
}
<|endoftext|>


<commit_before>use std::env;
use ansi_term::Colour::{Cyan, Blue, Red};
use ansi_term::ANSIStrings;
use git2;
use git2::{Repository, StatusOptions};
use regex::Regex;
use clap::{ArgMatches, App, SubCommand};

fn first_char(s: &str) -> String {
  let chars: Vec<char> = s.chars().collect();
  match chars.len() {
    0 => String::from(""),
    _ => chars[0].to_string(),
  }
}

fn fmt_current_path(cwd: &str) -> String {
  let home: Regex = match env::home_dir() {
    Some(path) => Regex::new(path.to_str().unwrap()).unwrap(),
    None => Regex::new("").unwrap(),
  };
  let friendly_path = home.replace(cwd, "~").to_string();
  let mut friendly_path_split: Vec<&str> = friendly_path.split("/").collect();
  let current_dir = friendly_path_split.pop().unwrap().to_string();
  let mut short_path: Vec<String> = friendly_path_split.iter().map(|s| first_char(s)).collect();
  short_path.push(current_dir);
  short_path.join("/")
}

fn repo_status(r: Repository) -> String {
  let mut opts = StatusOptions::new();
  opts.include_untracked(true);
  let head = r.head().unwrap();
  let shorthand = Cyan.paint(head.shorthand().unwrap().to_string());
  let statuses = r.statuses(Some(&mut opts)).unwrap();

  let mut is_dirty = false;

  for entry in statuses.iter().filter(
    |e| e.status() != git2::STATUS_CURRENT,
  ) {
    is_dirty = match entry.status() {
      s if s.contains(git2::STATUS_INDEX_NEW) => true,
      s if s.contains(git2::STATUS_INDEX_MODIFIED) => true,
      s if s.contains(git2::STATUS_INDEX_DELETED) => true,
      s if s.contains(git2::STATUS_INDEX_RENAMED) => true,
      s if s.contains(git2::STATUS_INDEX_TYPECHANGE) => true,
      s if s.contains(git2::STATUS_WT_NEW) => true,
      s if s.contains(git2::STATUS_WT_MODIFIED) => true,
      s if s.contains(git2::STATUS_WT_DELETED) => true,
      s if s.contains(git2::STATUS_WT_RENAMED) => true,
      s if s.contains(git2::STATUS_WT_TYPECHANGE) => true,
      _ => false,
    };
    match is_dirty {
      true => break,
      false => continue,
    }
  }
  let mut out = vec![shorthand];
  if is_dirty == true {
    out.push(Red.bold().paint("*"));
  }

  ANSIStrings(&out).to_string()
}

pub fn display(_sub: &ArgMatches) {
  let my_path = env::current_dir().unwrap();
  let display_path = Blue.paint(fmt_current_path(my_path.to_str().unwrap()));

  let branch = match Repository::open(my_path) {
    Ok(repo) => repo_status(repo),
    Err(_e) => String::from(""),
  };
  let display_branch = Cyan.paint(branch);

  println!("");
  println!("{} {}", display_path, display_branch);
}

pub fn cli_arguments<'a>() -> App<'a, 'a> {
  SubCommand::with_name("precmd")
}
<commit_msg>Refactor friendly_path<commit_after>use std::env;
use ansi_term::Colour::{Cyan, Blue, Red};
use ansi_term::ANSIStrings;
use git2;
use git2::{Repository, StatusOptions};
use regex::Regex;
use clap::{ArgMatches, App, SubCommand};

fn first_char(s: &str) -> String {
  let chars: Vec<char> = s.chars().collect();
  match chars.len() {
    0 => String::from(""),
    _ => chars[0].to_string(),
  }
}

fn fmt_current_path(cwd: &str) -> String {
  let friendly_path = if let Some(path) = env::home_dir() {
    Regex::new(path.to_str().unwrap()).unwrap().replace(cwd, "~").to_string()
  } else {
    String::from("")
  };

  let mut friendly_path_split: Vec<&str> = friendly_path.split("/").collect();
  let current_dir = friendly_path_split.pop().unwrap().to_string();
  let mut short_path: Vec<String> = friendly_path_split.iter().map(|s| first_char(s)).collect();
  short_path.push(current_dir);
  short_path.join("/")
}

fn repo_status(r: Repository) -> String {
  let mut opts = StatusOptions::new();
  opts.include_untracked(true);
  let head = r.head().unwrap();
  let shorthand = Cyan.paint(head.shorthand().unwrap().to_string());
  let statuses = r.statuses(Some(&mut opts)).unwrap();

  let mut is_dirty = false;

  for entry in statuses.iter().filter(
    |e| e.status() != git2::STATUS_CURRENT,
  ) {
    is_dirty = match entry.status() {
      s if s.contains(git2::STATUS_INDEX_NEW) => true,
      s if s.contains(git2::STATUS_INDEX_MODIFIED) => true,
      s if s.contains(git2::STATUS_INDEX_DELETED) => true,
      s if s.contains(git2::STATUS_INDEX_RENAMED) => true,
      s if s.contains(git2::STATUS_INDEX_TYPECHANGE) => true,
      s if s.contains(git2::STATUS_WT_NEW) => true,
      s if s.contains(git2::STATUS_WT_MODIFIED) => true,
      s if s.contains(git2::STATUS_WT_DELETED) => true,
      s if s.contains(git2::STATUS_WT_RENAMED) => true,
      s if s.contains(git2::STATUS_WT_TYPECHANGE) => true,
      _ => false,
    };
    match is_dirty {
      true => break,
      false => continue,
    }
  }
  let mut out = vec![shorthand];
  if is_dirty == true {
    out.push(Red.bold().paint("*"));
  }

  ANSIStrings(&out).to_string()
}

pub fn display(_sub: &ArgMatches) {
  let my_path = env::current_dir().unwrap();
  let display_path = Blue.paint(fmt_current_path(my_path.to_str().unwrap()));

  let branch = match Repository::open(my_path) {
    Ok(repo) => repo_status(repo),
    Err(_e) => String::from(""),
  };
  let display_branch = Cyan.paint(branch);

  println!("");
  println!("{} {}", display_path, display_branch);
}

pub fn cli_arguments<'a>() -> App<'a, 'a> {
  SubCommand::with_name("precmd")
}
<|endoftext|>


<commit_before>use std;
pub fn prime_filter(iter_size: usize) -> std::vec::Vec<bool>{
    //Sieve of Atkin
    if iter_size < 100 {
        slow_prime_filter(iter_size)
    }else{
        let mut prime_filter = vec![false; iter_size];
        prime_filter[2] = true;
        prime_filter[3] = true;
        prime_filter[5] = true;
        let mut y_sq = 1;
        let mut to_next_y_sq = 3;
        while y_sq<iter_size {
            if y_sq%2 == 1 {
                //n_1 = 4x^2 + y^2 === 1 (mod 4)
                let (mut n_1, mut to_next_n_1) = (y_sq, 4);
                loop{
                    n_1 += to_next_n_1;
                    to_next_n_1 += 8;
                    match n_1%60{
                        _ if n_1 >= iter_size => break,
                        1 | 13 | 17 | 29 | 37 | 41 | 49 | 53 => (),
                        _ => continue,
                    };

                    // println!("1: {}", n_1);
                    prime_filter[n_1] ^= true;
                };
            };
            if y_sq%3 == 1 {
                //n_2 = 3x^2 + y^2 === 1 (mod 6)
                let (mut n_2, mut to_next_n_2) = (y_sq, 3);
                loop {
                    n_2 += to_next_n_2;
                    to_next_n_2 += 6;
                    match n_2%60{
                        _ if n_2 >= iter_size => break,
                        7 | 19 | 31 | 43 => (),
                        _ => continue,
                    };
                    // println!("2: {}", n_2);
                    prime_filter[n_2] ^= true;
                };
                //n_3 = 3x^2 - y^2 === 11 (mod 12)
                let (mut n_3, mut to_next_n_3) = (2*y_sq, 3*to_next_y_sq);
                loop {
                    n_3 += to_next_n_3;
                    to_next_n_3 += 6;
                    match n_3%60{
                        _ if n_3 >= iter_size => break,
                        11 | 23 | 47 | 59 => (),
                        _ => continue,
                    };
                    // println!("3: {}", n_3);
                    prime_filter[n_3] ^= true;
                };
            };
            while{ //Do-while
                y_sq += to_next_y_sq;
                to_next_y_sq += 2;
                y_sq%6 == 0
            } {};
        };
        //Eliminate non-squarefree numbers
        let mut n_sq = 49; // 7^2
        let mut next_n_sq = 32; //9^2 - 7^2, skip even numbers.
        while n_sq < iter_size {
            let mut non_sq_free = n_sq;
            while non_sq_free < iter_size {
                prime_filter[non_sq_free] = false;
                while{ //Do-while
                    non_sq_free += n_sq + n_sq;
                    (non_sq_free%3==0) | (non_sq_free%5==0)
                } {};
            };
            while{ //Do-while
                n_sq += next_n_sq;
                next_n_sq += 8;
                (n_sq%3==0) | (n_sq%5 == 0)
            } {};
        }
        prime_filter
    }
}

pub fn old_prime_filter(iter_size: usize) -> std::vec::Vec<bool>{
    slow_prime_filter(iter_size)

//not idiomatic, but I'm doing it anyway.
#[test]
fn test_prime_filter(){
    let n = 1234567;
    let new_pf = prime_filter(n);
    let old_pf = old_prime_filter(n);
    for i in 0..n{
        assert_eq!(new_pf[i], old_pf[i], "Failed on number {}", i)
    }
}
<commit_msg>Forgot names<commit_after>use std;
pub fn prime_filter(iter_size: usize) -> std::vec::Vec<bool>{
    //Sieve of Atkin
    if iter_size < 100 {
        slow_prime_filter(iter_size)
    }else{
        let mut prime_filter = vec![false; iter_size];
        prime_filter[2] = true;
        prime_filter[3] = true;
        prime_filter[5] = true;
        let mut y_sq = 1;
        let mut to_next_y_sq = 3;
        while y_sq<iter_size {
            if y_sq%2 == 1 {
                //n_1 = 4x^2 + y^2 === 1 (mod 4)
                let (mut n_1, mut to_next_n_1) = (y_sq, 4);
                loop{
                    n_1 += to_next_n_1;
                    to_next_n_1 += 8;
                    match n_1%60{
                        _ if n_1 >= iter_size => break,
                        1 | 13 | 17 | 29 | 37 | 41 | 49 | 53 => (),
                        _ => continue,
                    };

                    // println!("1: {}", n_1);
                    prime_filter[n_1] ^= true;
                };
            };
            if y_sq%3 == 1 {
                //n_2 = 3x^2 + y^2 === 1 (mod 6)
                let (mut n_2, mut to_next_n_2) = (y_sq, 3);
                loop {
                    n_2 += to_next_n_2;
                    to_next_n_2 += 6;
                    match n_2%60{
                        _ if n_2 >= iter_size => break,
                        7 | 19 | 31 | 43 => (),
                        _ => continue,
                    };
                    // println!("2: {}", n_2);
                    prime_filter[n_2] ^= true;
                };
                //n_3 = 3x^2 - y^2 === 11 (mod 12)
                let (mut n_3, mut to_next_n_3) = (2*y_sq, 3*to_next_y_sq);
                loop {
                    n_3 += to_next_n_3;
                    to_next_n_3 += 6;
                    match n_3%60{
                        _ if n_3 >= iter_size => break,
                        11 | 23 | 47 | 59 => (),
                        _ => continue,
                    };
                    // println!("3: {}", n_3);
                    prime_filter[n_3] ^= true;
                };
            };
            while{ //Do-while
                y_sq += to_next_y_sq;
                to_next_y_sq += 2;
                y_sq%6 == 0
            } {};
        };
        //Eliminate non-squarefree numbers
        let mut n_sq = 49; // 7^2
        let mut next_n_sq = 32; //9^2 - 7^2, skip even numbers.
        while n_sq < iter_size {
            let mut non_sq_free = n_sq;
            while non_sq_free < iter_size {
                prime_filter[non_sq_free] = false;
                while{ //Do-while
                    non_sq_free += n_sq + n_sq;
                    (non_sq_free%3==0) | (non_sq_free%5==0)
                } {};
            };
            while{ //Do-while
                n_sq += next_n_sq;
                next_n_sq += 8;
                (n_sq%3==0) | (n_sq%5 == 0)
            } {};
        }
        prime_filter
    }
}

fn old_prime_filter(iter_size: usize) -> std::vec::Vec<bool>{
    slow_prime_filter(iter_size)

fn slow_prime_filter(iter_size: usize) -> std::vec::Vec<bool>{
    if iter_size < 5 {
         let mut ret = vec![false, false, true, true];
         ret.truncate(iter_size);
         return ret
     }
    let mut prime_filter = vec![true; iter_size];
    prime_filter[0] = false;
    prime_filter[1] = false;
    let mut cur_num = 2;
    'outer: loop{
        for i in (cur_num+1)..iter_size{
            if 0 == i%cur_num { prime_filter[i] = false; }
        }
        cur_num += 1;
        while !prime_filter[cur_num]{
            if cur_num*cur_num > iter_size {
                break 'outer
            }
            cur_num += 1;
        }
    }
}
//not idiomatic, but I'm doing it anyway.
#[test]
fn test_prime_filter(){
    let n = 1234567;
    let new_pf = prime_filter(n);
    let old_pf = old_prime_filter(n);
    for i in 0..n{
        assert_eq!(new_pf[i], old_pf[i], "Failed on number {}", i)
    }
}
<|endoftext|>


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

use capnp::{any_pointer};
use capnp::Error;
use capnp::capability::Promise;
use capnp::private::capability::{ClientHook, ParamsHook, PipelineHook, PipelineOp,
                                 ResultsHook, ResultsDoneHook};

use futures::Future;

use std::cell::RefCell;
use std::rc::{Rc};

use {broken, local, ForkedPromise};

struct PipelineInner {
    promise: ForkedPromise<Promise<Box<PipelineHook>, Error>>,

    // Once the promise resolves, this will become non-null and point to the underlying object.
    redirect: Option<Box<PipelineHook>>,

    // Represents the operation which will set `redirect` when possible.
    self_resolution_op: Promise<(), Error>,
}

pub struct Pipeline {
    inner: Rc<RefCell<PipelineInner>>,
}

impl Pipeline {
    pub fn new(promise_param: Promise<Box<PipelineHook>, Error>) -> Pipeline {
        let promise = ForkedPromise::new_queued(promise_param);
        let branch = promise.clone();
        let inner = Rc::new(RefCell::new(PipelineInner {
            promise: promise,
            redirect: None,
            self_resolution_op: Promise::ok(()),
        }));
        let this = Rc::downgrade(&inner);
        let self_res = ::eagerly_evaluate(branch.then(move |result| {

            let this = match this.upgrade(){
                Some(v) => v,
                None => return Err(Error::failed("dangling self reference in queued::Pipeline".into())),
            };

            match result {
                Ok(pipeline_hook) => {
                    this.borrow_mut().redirect = Some(pipeline_hook);
                }
                Err(e) => {
                    this.borrow_mut().redirect = Some(Box::new(broken::Pipeline::new(e)));
                }
            }
            Ok(())
        }));
        inner.borrow_mut().self_resolution_op = self_res;
        Pipeline { inner: inner }
    }
}

impl Clone for Pipeline {
    fn clone(&self) -> Pipeline {
        Pipeline { inner: self.inner.clone() }
    }
}

impl PipelineHook for Pipeline {
    fn add_ref(&self) -> Box<PipelineHook> {
        Box::new(self.clone())
    }
    fn get_pipelined_cap(&self, ops: &[PipelineOp]) -> Box<ClientHook> {
        self.get_pipelined_cap_move(ops.into())
    }

    fn get_pipelined_cap_move(&self, ops: Vec<PipelineOp>) -> Box<ClientHook> {
        match &self.inner.borrow().redirect {
            &Some(ref p) => {
                return p.get_pipelined_cap_move(ops)
            }
            &None => (),
        }
        let client_promise = self.inner.borrow_mut().promise.clone().map(move |pipeline| {
            pipeline.get_pipelined_cap_move(ops)
        });

        Box::new(Client::new(Promise::from_future(client_promise)))
    }
}

type ClientHookPromiseFork = ForkedPromise<Promise<Box<ClientHook>, Error>>;

struct ClientInner {
    // Once the promise resolves, this will become non-null and point to the underlying object.
    redirect: Option<Box<ClientHook>>,

    // Promise that resolves when we have a new ClientHook to forward to.
    //
    // This fork shall only have three branches:  `selfResolutionOp`, `promiseForCallForwarding`, and
    // `promiseForClientResolution`, in that order.
    _promise: ClientHookPromiseFork,

    // Represents the operation which will set `redirect` when possible.
    self_resolution_op: Promise<(), Error>,

    // When this promise resolves, each queued call will be forwarded to the real client.  This needs
    // to occur *before* any 'whenMoreResolved()' promises resolve, because we want to make sure
    // previously-queued calls are delivered before any new calls made in response to the resolution.
    promise_for_call_forwarding: ClientHookPromiseFork,

    // whenMoreResolved() returns forks of this promise.  These must resolve *after* queued calls
    // have been initiated (so that any calls made in the whenMoreResolved() handler are correctly
    // delivered after calls made earlier), but *before* any queued calls return (because it might
    // confuse the application if a queued call returns before the capability on which it was made
    // resolves).  Luckily, we know that queued calls will involve, at the very least, an
    // eventLoop.evalLater.
    promise_for_client_resolution: ClientHookPromiseFork,
}

pub struct Client {
    inner: Rc<RefCell<ClientInner>>,
}

impl Client {
    pub fn new(promise_param: Promise<Box<ClientHook>, Error>)
           -> Client
    {
        let promise = ForkedPromise::new_queued(promise_param);
        let branch1 = promise.add_branch();
        let branch2 = promise.add_branch();
        let branch3 = promise.add_branch();
        let inner = Rc::new(RefCell::new(ClientInner {
            redirect: None,
            _promise: promise,
            self_resolution_op: Promise::from_future(::futures::future::empty()),
            promise_for_call_forwarding: ForkedPromise::new(Promise::from_future(branch2)),
            promise_for_client_resolution: ForkedPromise::new(Promise::from_future(branch3)),
        }));
        let this = Rc::downgrade(&inner);
        let self_resolution_op = ::eagerly_evaluate(branch1.then(move |result| {
            let state = match this.upgrade() {
                Some(s) => s,
                None => return Err(Error::failed("dangling reference to QueuedClient".into())),
            };
            match result {
                Ok(clienthook) => {
                    state.borrow_mut().redirect = Some(clienthook);
                }
                Err(e) => {
                    state.borrow_mut().redirect = Some(broken::new_cap(e));
                }
            }
            Ok(())
        }));
        inner.borrow_mut().self_resolution_op = self_resolution_op;
        Client {
            inner: inner
        }
    }
}

impl ClientHook for Client {
    fn add_ref(&self) -> Box<ClientHook> {
        Box::new(Client {inner: self.inner.clone()})
    }
    fn new_call(&self, interface_id: u64, method_id: u16,
                size_hint: Option<::capnp::MessageSize>)
                -> ::capnp::capability::Request<any_pointer::Owned, any_pointer::Owned>
    {
        ::capnp::capability::Request::new(
            Box::new(local::Request::new(interface_id, method_id, size_hint, self.add_ref())))
    }

    fn call(&self, interface_id: u64, method_id: u16, params: Box<ParamsHook>, results: Box<ResultsHook>,
            results_done: Promise<Box<ResultsDoneHook>, Error>)
        -> (Promise<(), Error>, Box<PipelineHook>)
    {
        // The main reason this is complicated is that we don't want the call to get cancelled
        // if the caller drops just the returned promise but not the pipeline.
        struct CallResultHolder {
            promise: Option<Promise<(), Error>>,
            pipeline: Option<Box<PipelineHook>>,
        }

        let call_result_promise =
            ForkedPromise::new(Box::new(self.inner.borrow_mut().promise_for_call_forwarding.clone().and_then(move |client| {
                let (promise, pipeline) = client.call(interface_id, method_id, params, results, results_done);
                Ok(Rc::new(RefCell::new(CallResultHolder {
                    promise: Some(promise),
                    pipeline: Some(pipeline),
                })))
            })));

        let pipeline_promise = call_result_promise.clone().and_then(|call_result| {
            Ok(call_result.borrow_mut().pipeline.take().expect("pipeline gone?"))
        });
        let pipeline = Pipeline::new(Promise::from_future(pipeline_promise));

        let completion_promise = call_result_promise.and_then(|call_result| {
            call_result.borrow_mut().promise.take().expect("promise gone?")
        });

        (Promise::from_future(completion_promise), Box::new(pipeline))
    }

    fn get_ptr(&self) -> usize {
        (&*self.inner.borrow()) as * const _ as usize
    }

    fn get_brand(&self) -> usize {
        println!("queued get_brand()");
        0
    }

    fn get_resolved(&self) -> Option<Box<ClientHook>> {
        match self.inner.borrow().redirect {
            Some(ref inner) => Some(inner.clone()),
            None => None,
        }
    }

    fn when_more_resolved(&self) -> Option<Promise<Box<ClientHook>, Error>> {
        Some(Promise::from_future(self.inner.borrow_mut().promise_for_client_resolution.clone()))
    }
}
<commit_msg>don't double fork<commit_after>// Copyright (c) 2013-2016 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use capnp::{any_pointer};
use capnp::Error;
use capnp::capability::Promise;
use capnp::private::capability::{ClientHook, ParamsHook, PipelineHook, PipelineOp,
                                 ResultsHook, ResultsDoneHook};

use futures::Future;

use std::cell::RefCell;
use std::rc::{Rc};

use {broken, local, ForkedPromise};

struct PipelineInner {
    promise: ForkedPromise<Promise<Box<PipelineHook>, Error>>,

    // Once the promise resolves, this will become non-null and point to the underlying object.
    redirect: Option<Box<PipelineHook>>,

    // Represents the operation which will set `redirect` when possible.
    self_resolution_op: Promise<(), Error>,
}

pub struct Pipeline {
    inner: Rc<RefCell<PipelineInner>>,
}

impl Pipeline {
    pub fn new(promise_param: Promise<Box<PipelineHook>, Error>) -> Pipeline {
        let promise = ForkedPromise::new_queued(promise_param);
        let branch = promise.clone();
        let inner = Rc::new(RefCell::new(PipelineInner {
            promise: promise,
            redirect: None,
            self_resolution_op: Promise::ok(()),
        }));
        let this = Rc::downgrade(&inner);
        let self_res = ::eagerly_evaluate(branch.then(move |result| {

            let this = match this.upgrade(){
                Some(v) => v,
                None => return Err(Error::failed("dangling self reference in queued::Pipeline".into())),
            };

            match result {
                Ok(pipeline_hook) => {
                    this.borrow_mut().redirect = Some(pipeline_hook);
                }
                Err(e) => {
                    this.borrow_mut().redirect = Some(Box::new(broken::Pipeline::new(e)));
                }
            }
            Ok(())
        }));
        inner.borrow_mut().self_resolution_op = self_res;
        Pipeline { inner: inner }
    }
}

impl Clone for Pipeline {
    fn clone(&self) -> Pipeline {
        Pipeline { inner: self.inner.clone() }
    }
}

impl PipelineHook for Pipeline {
    fn add_ref(&self) -> Box<PipelineHook> {
        Box::new(self.clone())
    }
    fn get_pipelined_cap(&self, ops: &[PipelineOp]) -> Box<ClientHook> {
        self.get_pipelined_cap_move(ops.into())
    }

    fn get_pipelined_cap_move(&self, ops: Vec<PipelineOp>) -> Box<ClientHook> {
        match &self.inner.borrow().redirect {
            &Some(ref p) => {
                return p.get_pipelined_cap_move(ops)
            }
            &None => (),
        }
        let client_promise = self.inner.borrow_mut().promise.clone().map(move |pipeline| {
            pipeline.get_pipelined_cap_move(ops)
        });

        Box::new(Client::new(Promise::from_future(client_promise)))
    }
}

type ClientHookPromiseFork = ForkedPromise<Promise<Box<ClientHook>, Error>>;

struct ClientInner {
    // Once the promise resolves, this will become non-null and point to the underlying object.
    redirect: Option<Box<ClientHook>>,

    // Promise that resolves when we have a new ClientHook to forward to.
    //
    // This fork shall only have three branches:  `selfResolutionOp`, `promiseForCallForwarding`, and
    // `promiseForClientResolution`, in that order.
    _promise: ClientHookPromiseFork,

    // Represents the operation which will set `redirect` when possible.
    self_resolution_op: Promise<(), Error>,

    // When this promise resolves, each queued call will be forwarded to the real client.  This needs
    // to occur *before* any 'whenMoreResolved()' promises resolve, because we want to make sure
    // previously-queued calls are delivered before any new calls made in response to the resolution.
    promise_for_call_forwarding: ClientHookPromiseFork,

    // whenMoreResolved() returns forks of this promise.  These must resolve *after* queued calls
    // have been initiated (so that any calls made in the whenMoreResolved() handler are correctly
    // delivered after calls made earlier), but *before* any queued calls return (because it might
    // confuse the application if a queued call returns before the capability on which it was made
    // resolves).  Luckily, we know that queued calls will involve, at the very least, an
    // eventLoop.evalLater.
    promise_for_client_resolution: ClientHookPromiseFork,
}

pub struct Client {
    inner: Rc<RefCell<ClientInner>>,
}

impl Client {
    pub fn new(promise_param: Promise<Box<ClientHook>, Error>)
           -> Client
    {
        let promise = ForkedPromise::new_queued(promise_param);
        let branch1 = promise.add_branch();
        let branch2 = promise.add_branch();
        let branch3 = promise.add_branch();
        let inner = Rc::new(RefCell::new(ClientInner {
            redirect: None,
            _promise: promise,
            self_resolution_op: Promise::from_future(::futures::future::empty()),
            promise_for_call_forwarding: branch2,
            promise_for_client_resolution: branch3,
        }));
        let this = Rc::downgrade(&inner);
        let self_resolution_op = ::eagerly_evaluate(branch1.then(move |result| {
            let state = match this.upgrade() {
                Some(s) => s,
                None => return Err(Error::failed("dangling reference to QueuedClient".into())),
            };
            match result {
                Ok(clienthook) => {
                    state.borrow_mut().redirect = Some(clienthook);
                }
                Err(e) => {
                    state.borrow_mut().redirect = Some(broken::new_cap(e));
                }
            }
            Ok(())
        }));
        inner.borrow_mut().self_resolution_op = self_resolution_op;
        Client {
            inner: inner
        }
    }
}

impl ClientHook for Client {
    fn add_ref(&self) -> Box<ClientHook> {
        Box::new(Client {inner: self.inner.clone()})
    }
    fn new_call(&self, interface_id: u64, method_id: u16,
                size_hint: Option<::capnp::MessageSize>)
                -> ::capnp::capability::Request<any_pointer::Owned, any_pointer::Owned>
    {
        ::capnp::capability::Request::new(
            Box::new(local::Request::new(interface_id, method_id, size_hint, self.add_ref())))
    }

    fn call(&self, interface_id: u64, method_id: u16, params: Box<ParamsHook>, results: Box<ResultsHook>,
            results_done: Promise<Box<ResultsDoneHook>, Error>)
        -> (Promise<(), Error>, Box<PipelineHook>)
    {
        // The main reason this is complicated is that we don't want the call to get cancelled
        // if the caller drops just the returned promise but not the pipeline.
        struct CallResultHolder {
            promise: Option<Promise<(), Error>>,
            pipeline: Option<Box<PipelineHook>>,
        }

        let call_result_promise =
            ForkedPromise::new(Box::new(self.inner.borrow_mut().promise_for_call_forwarding.clone().and_then(move |client| {
                let (promise, pipeline) = client.call(interface_id, method_id, params, results, results_done);
                Ok(Rc::new(RefCell::new(CallResultHolder {
                    promise: Some(promise),
                    pipeline: Some(pipeline),
                })))
            })));

        let pipeline_promise = call_result_promise.clone().and_then(|call_result| {
            Ok(call_result.borrow_mut().pipeline.take().expect("pipeline gone?"))
        });
        let pipeline = Pipeline::new(Promise::from_future(pipeline_promise));

        let completion_promise = call_result_promise.and_then(|call_result| {
            call_result.borrow_mut().promise.take().expect("promise gone?")
        });

        (Promise::from_future(completion_promise), Box::new(pipeline))
    }

    fn get_ptr(&self) -> usize {
        (&*self.inner.borrow()) as * const _ as usize
    }

    fn get_brand(&self) -> usize {
        println!("queued get_brand()");
        0
    }

    fn get_resolved(&self) -> Option<Box<ClientHook>> {
        match self.inner.borrow().redirect {
            Some(ref inner) => Some(inner.clone()),
            None => None,
        }
    }

    fn when_more_resolved(&self) -> Option<Promise<Box<ClientHook>, Error>> {
        Some(Promise::from_future(self.inner.borrow_mut().promise_for_client_resolution.clone()))
    }
}
<|endoftext|>


<commit_before>use std::io:: { Error as IOError };
use std::convert::From;
use std::result:: { Result };
use std::collections:: { HashMap };
use std::default::Default;
use lcov_parser::parser:: { LCOVParser, RecordParseError };
use lcov_parser::record:: { LCOVRecord };

pub enum ParseError {
    IOError(IOError),
    RecordParseError(RecordParseError)
}

impl From<IOError> for ParseError {
    fn from(error: IOError) -> Self {
        ParseError::IOError(error)
    }
}

impl From<RecordParseError> for ParseError {
    fn from(error: RecordParseError) -> Self {
        ParseError::RecordParseError(error)
    }
}

pub fn records_from_file(file: &str) -> Result<Vec<LCOVRecord>, ParseError> {
    let parser = try!(LCOVParser::from_file(file));
    Ok(try!(parser.parse()))
}

//
// $testcount = $testdata->{$testname};
// $testfnccount = $testfncdata->{$testname};
// $testbrcount = $testbrdata->{$testname};
//

#[derive(Clone)]
struct Test {
    test_count: HashMap<u32, u32>, // key: line number, value: test count
    test_fn_count: HashMap<String, u32>, // key: function name, value: line number
    test_br_count: u32 // FIXME br data structure
}

impl Default for Test {
    fn default() -> Self {
        Test {
            test_count: HashMap::new(),
            test_fn_count: HashMap::new(),
            test_br_count: 0
        }
    }
}

// my $sumcount
// my $sumbrcount
// my $sumfnccount
struct SumCount {
    sum_count: HashMap<u32, u32>, // key: line number, value: count
    sum_br_count: HashMap<String, u32>, // key: function name, value: execution count
    sum_fn_count: u32 // FIXME br data structure
}

// key: line_number, value: checksum value
type CheckSum = HashMap<u32, String>;

struct ReportParser {
    test_name: Option<String>,
    source_name: Option<String>,
    test: Option<Test>,
    tests: HashMap<String, Test>,
    sum: SumCount,
    checksum: CheckSum
}

impl ReportParser {
    fn parse(&mut self, file: &str) -> Result<(), ParseError> {
        let records = try!(records_from_file(file));

        for record in records.iter() {
            match record {
                &LCOVRecord::TestName(ref name) => self.on_test_name(name),
                &LCOVRecord::SourceFile(ref name) => self.on_source_file(name),
                &LCOVRecord::Data(ref line_number, ref execution_count, ref checksum) => self.on_data(
                    line_number,
                    execution_count,
                    checksum,
                ),
                _ => { continue; }
            };
        }
        Ok(())
    }
    fn on_test_name(&mut self, test_name: &Option<String>) {
        self.test_name = test_name.clone();
    }
    fn on_source_file(&mut self, source_name: &String) {
        self.source_name = Some(source_name.clone());

        match self.test_name {
            Some(ref current_test_name) => {
                // $testcount = $testdata->{$testname};
                // $testfnccount = $testfncdata->{$testname};
                // $testbrcount = $testbrdata->{$testname};
                if !self.tests.contains_key(current_test_name) {
                    self.tests.insert(current_test_name.to_string(), Test::default());
                }
                let test = self.tests.get(current_test_name);
                self.test = Some(test.unwrap().clone());
            },
            None => self.test = Some(Test::default())
        }
    }
    fn on_data(&mut self, line_number: &u32, execution_count: &u32, checksum: &Option<String>) {
        let mut sum_count = self.sum.sum_count.entry(line_number.clone()).or_insert(0);
        *sum_count += *execution_count;

        if self.test_name.is_some() {
            if self.test.is_some() {
                let mut test = self.test.as_mut().unwrap();
                let mut test_count = test.test_count.entry(line_number.clone()).or_insert(0);
                *test_count += *execution_count;
            }
        }

        if checksum.is_none() {
            return;
        }

        if !self.checksum.contains_key(line_number) {
            let checksum_value = checksum.clone().unwrap();
            self.checksum.insert(line_number.clone(), checksum_value);
            return;
        }

        let checksum_value = checksum.clone().unwrap();
        let current_checksum = self.checksum.get(line_number).unwrap();
        if current_checksum != &checksum_value {
            println!("{} {}", current_checksum, checksum_value);
        }
    }
}
<commit_msg>parse function data<commit_after>use std::io:: { Error as IOError };
use std::convert::From;
use std::result:: { Result };
use std::collections:: { HashMap };
use std::default::Default;
use lcov_parser::parser:: { LCOVParser, RecordParseError };
use lcov_parser::record:: { LCOVRecord };

pub enum ParseError {
    IOError(IOError),
    RecordParseError(RecordParseError)
}

impl From<IOError> for ParseError {
    fn from(error: IOError) -> Self {
        ParseError::IOError(error)
    }
}

impl From<RecordParseError> for ParseError {
    fn from(error: RecordParseError) -> Self {
        ParseError::RecordParseError(error)
    }
}

pub fn records_from_file(file: &str) -> Result<Vec<LCOVRecord>, ParseError> {
    let parser = try!(LCOVParser::from_file(file));
    Ok(try!(parser.parse()))
}

//
// $testcount = $testdata->{$testname};
// $testfnccount = $testfncdata->{$testname};
// $testbrcount = $testbrdata->{$testname};
//

#[derive(Clone)]
struct Test {
    test_count: HashMap<u32, u32>, // key: line number, value: test count
    test_fn_count: HashMap<String, u32>, // key: function name, value: line number
    test_br_count: u32 // FIXME br data structure
}

impl Default for Test {
    fn default() -> Self {
        Test {
            test_count: HashMap::new(),
            test_fn_count: HashMap::new(),
            test_br_count: 0
        }
    }
}

// my $sumcount
// my $sumbrcount
// my $sumfnccount
struct SumCount {
    sum_count: HashMap<u32, u32>, // key: line number, value: count
    sum_br_count: HashMap<String, u32>, // key: function name, value: execution count
    sum_fn_count: HashMap<String, u32> // FIXME br data structure
}

// key: line_number, value: checksum value
type CheckSum = HashMap<u32, String>;
type FunctionData = HashMap<String, u32>;

struct ReportParser {
    test_name: Option<String>,
    source_name: Option<String>,
    test: Option<Test>,
    tests: HashMap<String, Test>,
    sum: SumCount,
    checksum: CheckSum,
    func: FunctionData
}

impl ReportParser {
    fn parse(&mut self, file: &str) -> Result<(), ParseError> {
        let records = try!(records_from_file(file));

        for record in records.iter() {
            match record {
                &LCOVRecord::TestName(ref name) => self.on_test_name(name),
                &LCOVRecord::SourceFile(ref name) => self.on_source_file(name),
                &LCOVRecord::Data(ref line_number, ref execution_count, ref checksum) => self.on_data(
                    line_number,
                    execution_count,
                    checksum,
                ),
                &LCOVRecord::FunctionName(ref line_number, ref func_name, ) => self.on_func_data(
                    func_name,
                    line_number
                ),
                _ => { continue; }
            };
        }
        Ok(())
    }
    fn on_test_name(&mut self, test_name: &Option<String>) {
        self.test_name = test_name.clone();
    }
    fn on_source_file(&mut self, source_name: &String) {
        self.source_name = Some(source_name.clone());

        match self.test_name {
            Some(ref current_test_name) => {
                // $testcount = $testdata->{$testname};
                // $testfnccount = $testfncdata->{$testname};
                // $testbrcount = $testbrdata->{$testname};
                if !self.tests.contains_key(current_test_name) {
                    self.tests.insert(current_test_name.to_string(), Test::default());
                }
                let test = self.tests.get(current_test_name);
                self.test = Some(test.unwrap().clone());
            },
            None => self.test = Some(Test::default())
        }
    }
    fn on_data(&mut self, line_number: &u32, execution_count: &u32, checksum: &Option<String>) {
        let mut sum_count = self.sum.sum_count.entry(line_number.clone()).or_insert(0);
        *sum_count += *execution_count;

        if self.test_name.is_some() {
            if self.test.is_some() {
                let mut test = self.test.as_mut().unwrap();
                let mut test_count = test.test_count.entry(line_number.clone()).or_insert(0);
                *test_count += *execution_count;
            }
        }

        if checksum.is_none() {
            return;
        }

        if !self.checksum.contains_key(line_number) {
            let checksum_value = checksum.clone().unwrap();
            self.checksum.insert(line_number.clone(), checksum_value);
            return;
        }

        let checksum_value = checksum.clone().unwrap();
        let current_checksum = self.checksum.get(line_number).unwrap();
        if current_checksum != &checksum_value {
            println!("{} {}", current_checksum, checksum_value);
        }
    }
    fn on_func_data(&mut self, func_name: &String, line_number: &u32) {
        let _ = self.func.entry(func_name.clone())
            .or_insert(line_number.clone());

        let _ = self.sum.sum_fn_count.entry(func_name.clone())
            .or_insert(0);

        if self.test_name.is_some() {
            if self.test.is_some() {
                let mut test = self.test.as_mut().unwrap();
                let _ = test.test_fn_count.entry(func_name.clone()).or_insert(0);
            }
        }

        if !(self.test_name.is_some() && self.test.is_some()) {
            return;
        }
        let mut test = self.test.as_mut().unwrap();
        let _ = test.test_fn_count.entry(func_name.clone()).or_insert(0);
    }
}
<|endoftext|>