<commit_before>//! This module provides a generic iterator and traits for decomposing
//! primitives and tessellating polygons.

use arrayvec::{Array, ArrayVec};
use std::collections::VecDeque;
use std::iter::IntoIterator;

use math::{self, FScalar};
use super::primitive::{Line, Polygon, Polygonal, Primitive, Triangle, Quad};

// A type `F` constrained to `Fn(P, D) -> R` could be used here, but it would
// not be possible to name that type for anything but functions (not closures).
// Instead of a limited and somewhat redundant type `F`, just use `fn(P, D) ->
// R` for the member `f`.
pub struct Decompose<I, P, Q, D, R>
where
    D: Copy,
    R: IntoIterator<Item = Q>,
{
    input: I,
    output: VecDeque<Q>,
    parameter: D,
    f: fn(P, D) -> R,
}

impl<I, P, Q, D, R> Decompose<I, P, Q, D, R>
where
    D: Copy,
    R: IntoIterator<Item = Q>,
{
    pub(super) fn new(input: I, parameter: D, f: fn(P, D) -> R) -> Self {
        Decompose {
            input: input,
            output: VecDeque::new(),
            parameter: parameter,
            f: f,
        }
    }
}

impl<I, P, Q, D, R> Iterator for Decompose<I, P, Q, D, R>
where
    I: Iterator<Item = P>,
    D: Copy,
    R: IntoIterator<Item = Q>,
{
    type Item = Q;

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            if let Some(polygon) = self.output.pop_front() {
                return Some(polygon);
            }
            if let Some(polygon) = self.input.next() {
                self.output.extend((self.f)(polygon, self.parameter));
            }
            else {
                return None;
            }
        }
    }
}

pub trait Interpolate: math::Interpolate<FScalar> {}

impl<T> Interpolate for T
where
    T: math::Interpolate<FScalar>,
{
}

pub trait IntoPoints: Primitive {
    type Output: IntoIterator<Item = Self::Point>;

    fn into_points(self) -> Self::Output;
}

pub trait IntoLines: Primitive {
    type Output: IntoIterator<Item = Line<Self::Point>>;

    fn into_lines(self) -> Self::Output;
}

pub trait IntoTriangles: Polygonal {
    type Output: IntoIterator<Item = Triangle<Self::Point>>;

    fn into_triangles(self) -> Self::Output;
}

pub trait IntoSubdivisions: Polygonal
where
    Self::Point: Clone + Interpolate,
{
    fn into_subdivisions(self, n: usize) -> Vec<Self>;
}

pub trait IntoTetrahedrons: Polygonal
where
    Self::Point: Clone + Interpolate,
{
    fn into_tetrahedrons(self) -> ArrayVec<[Triangle<Self::Point>; 4]>;
}

impl<T> IntoPoints for Line<T>
where
    T: Clone,
{
    type Output = ArrayVec<[Self::Point; 2]>;

    fn into_points(self) -> Self::Output {
        let Line { a, b } = self;
        ArrayVec::from([a, b])
    }
}

impl<T> IntoPoints for Triangle<T>
where
    T: Clone,
{
    type Output = ArrayVec<[Self::Point; 3]>;

    fn into_points(self) -> Self::Output {
        let Triangle { a, b, c } = self;
        ArrayVec::from([a, b, c])
    }
}

impl<T> IntoPoints for Quad<T>
where
    T: Clone,
{
    type Output = ArrayVec<[Self::Point; 4]>;

    fn into_points(self) -> Self::Output {
        let Quad { a, b, c, d } = self;
        ArrayVec::from([a, b, c, d])
    }
}

impl<T> IntoPoints for Polygon<T>
where
    T: Clone,
{
    type Output = Vec<Self::Point>;

    fn into_points(self) -> Self::Output {
        match self {
            Polygon::Triangle(triangle) => triangle.into_points().into_iter().collect(),
            Polygon::Quad(quad) => quad.into_points().into_iter().collect(),
        }
    }
}

impl<T> IntoLines for Line<T>
where
    T: Clone,
{
    type Output = ArrayVec<[Line<Self::Point>; 1]>;

    fn into_lines(self) -> Self::Output {
        ArrayVec::from([self])
    }
}

impl<T> IntoLines for Triangle<T>
where
    T: Clone,
{
    type Output = ArrayVec<[Line<Self::Point>; 3]>;

    fn into_lines(self) -> Self::Output {
        let Triangle { a, b, c } = self;
        ArrayVec::from(
            [
                Line::new(a.clone(), b.clone()),
                Line::new(b, c.clone()),
                Line::new(c, a),
            ],
        )
    }
}

impl<T> IntoLines for Quad<T>
where
    T: Clone,
{
    type Output = ArrayVec<[Line<Self::Point>; 4]>;

    fn into_lines(self) -> Self::Output {
        let Quad { a, b, c, d } = self;
        ArrayVec::from(
            [
                Line::new(a.clone(), b.clone()),
                Line::new(b, c.clone()),
                Line::new(c, d.clone()),
                Line::new(d, a),
            ],
        )
    }
}

impl<T> IntoLines for Polygon<T>
where
    T: Clone,
{
    type Output = Vec<Line<Self::Point>>;

    fn into_lines(self) -> Self::Output {
        match self {
            Polygon::Triangle(triangle) => triangle.into_lines().into_iter().collect(),
            Polygon::Quad(quad) => quad.into_lines().into_iter().collect(),
        }
    }
}

impl<T> IntoTriangles for Triangle<T>
where
    T: Clone,
{
    type Output = ArrayVec<[Triangle<Self::Point>; 1]>;

    fn into_triangles(self) -> Self::Output {
        ArrayVec::from([self])
    }
}

impl<T> IntoTriangles for Quad<T>
where
    T: Clone,
{
    type Output = ArrayVec<[Triangle<Self::Point>; 2]>;

    fn into_triangles(self) -> Self::Output {
        let Quad { a, b, c, d } = self;
        ArrayVec::from(
            [
                Triangle::new(a.clone(), b, c.clone()),
                Triangle::new(c, d, a),
            ],
        )
    }
}

impl<T> IntoTriangles for Polygon<T>
where
    T: Clone,
{
    type Output = Vec<Triangle<Self::Point>>;

    fn into_triangles(self) -> Self::Output {
        match self {
            Polygon::Triangle(triangle) => triangle.into_triangles().into_iter().collect(),
            Polygon::Quad(quad) => quad.into_triangles().into_iter().collect(),
        }
    }
}

impl<T> IntoSubdivisions for Triangle<T>
where
    T: Clone + Interpolate,
{
    fn into_subdivisions(self, n: usize) -> Vec<Self> {
        n_map_polygon(n, self, |triangle| {
            let Triangle { a, b, c } = triangle;
            let ac = a.midpoint(&c);
            ArrayVec::from(
                [
                    Triangle::new(b.clone(), ac.clone(), a),
                    Triangle::new(c, ac, b),
                ],
            )
        })
    }
}

impl<T> IntoSubdivisions for Quad<T>
where
    T: Clone + Interpolate,
{
    fn into_subdivisions(self, n: usize) -> Vec<Self> {
        n_map_polygon(n, self, |quad| {
            let Quad { a, b, c, d } = quad;
            let ab = a.midpoint(&b);
            let bc = b.midpoint(&c);
            let cd = c.midpoint(&d);
            let da = d.midpoint(&a);
            let ac = a.midpoint(&c); // Diagonal.
            ArrayVec::from(
                [
                    Quad::new(a, ab.clone(), ac.clone(), da.clone()),
                    Quad::new(ab, b, bc.clone(), ac.clone()),
                    Quad::new(ac.clone(), bc, c, cd.clone()),
                    Quad::new(da, ac, cd, d),
                ],
            )
        })
    }
}

impl<T> IntoTetrahedrons for Quad<T>
where
    T: Clone + Interpolate,
{
    fn into_tetrahedrons(self) -> ArrayVec<[Triangle<Self::Point>; 4]> {
        let Quad { a, b, c, d } = self;
        let ac = a.midpoint(&c); // Diagonal.
        ArrayVec::from(
            [
                Triangle::new(a.clone(), b.clone(), ac.clone()),
                Triangle::new(b, c.clone(), ac.clone()),
                Triangle::new(c, d.clone(), ac.clone()),
                Triangle::new(d, a, ac),
            ],
        )
    }
}

impl<T> IntoSubdivisions for Polygon<T>
where
    T: Clone + Interpolate,
{
    fn into_subdivisions(self, n: usize) -> Vec<Self> {
        match self {
            Polygon::Triangle(triangle) => {
                triangle
                    .into_subdivisions(n)
                    .into_iter()
                    .map(|triangle| triangle.into())
                    .collect()
            }
            Polygon::Quad(quad) => {
                quad.into_subdivisions(n)
                    .into_iter()
                    .map(|quad| quad.into())
                    .collect()
            }
        }
    }
}

pub trait Points<P>: Sized
where
    P: IntoPoints,
{
    fn points(self) -> Decompose<Self, P, P::Point, (), P::Output>;
}

impl<I, P> Points<P> for I
where
    I: Iterator<Item = P>,
    P: IntoPoints,
    P::Point: Clone,
{
    fn points(self) -> Decompose<Self, P, P::Point, (), P::Output> {
        Decompose::new(self, (), into_points)
    }
}

pub trait Lines<P>: Sized
where
    P: IntoLines,
{
    fn lines(self) -> Decompose<Self, P, Line<P::Point>, (), P::Output>;
}

impl<I, P> Lines<P> for I
where
    I: Iterator<Item = P>,
    P: IntoLines,
    P::Point: Clone,
{
    fn lines(self) -> Decompose<Self, P, Line<P::Point>, (), P::Output> {
        Decompose::new(self, (), into_lines)
    }
}

pub trait Triangulate<P>: Sized
where
    P: IntoTriangles,
{
    fn triangulate(self) -> Decompose<Self, P, Triangle<P::Point>, (), P::Output>;
}

impl<I, P> Triangulate<P> for I
where
    I: Iterator<Item = P>,
    P: IntoTriangles,
    P::Point: Clone,
{
    fn triangulate(self) -> Decompose<Self, P, Triangle<P::Point>, (), P::Output> {
        Decompose::new(self, (), into_triangles)
    }
}

pub trait Subdivide<P>: Sized
where
    P: IntoSubdivisions,
    P::Point: Clone + Interpolate,
{
    fn subdivide(self, n: usize) -> Decompose<Self, P, P, usize, Vec<P>>;
}

impl<I, P> Subdivide<P> for I
where
    I: Iterator<Item = P>,
    P: IntoSubdivisions,
    P::Point: Clone + Interpolate,
{
    fn subdivide(self, n: usize) -> Decompose<Self, P, P, usize, Vec<P>> {
        Decompose::new(self, n, P::into_subdivisions)
    }
}

pub trait Tetrahedrons<T>: Sized {
    #[allow(type_complexity)]
    fn tetrahedrons(self) -> Decompose<Self, Quad<T>, Triangle<T>, (), ArrayVec<[Triangle<T>; 4]>>;
}

impl<I, T> Tetrahedrons<T> for I
where
    I: Iterator<Item = Quad<T>>,
    T: Clone + Interpolate,
{
    #[allow(type_complexity)]
    fn tetrahedrons(self) -> Decompose<Self, Quad<T>, Triangle<T>, (), ArrayVec<[Triangle<T>; 4]>> {
        Decompose::new(self, (), into_tetrahedrons)
    }
}

fn into_points<P>(primitive: P, _: ()) -> P::Output
where
    P: IntoPoints,
    P::Point: Clone,
{
    primitive.into_points()
}

fn into_lines<P>(primitive: P, _: ()) -> P::Output
where
    P: IntoLines,
    P::Point: Clone,
{
    primitive.into_lines()
}

fn into_triangles<P>(polygon: P, _: ()) -> P::Output
where
    P: IntoTriangles,
    P::Point: Clone,
{
    polygon.into_triangles()
}

fn into_tetrahedrons<T>(quad: Quad<T>, _: ()) -> ArrayVec<[Triangle<T>; 4]>
where
    T: Clone + Interpolate,
{
    quad.into_tetrahedrons()
}

fn n_map_polygon<P, A, F>(n: usize, polygon: P, f: F) -> Vec<P>
where
    P: Polygonal,
    P::Point: Clone,
    A: Array<Item = P>,
    F: Fn(P) -> ArrayVec<A>,
{
    let mut polygons = vec![polygon];
    for _ in 0..n {
        polygons = polygons.into_iter().flat_map(&f).collect();
    }
    polygons
}
<commit_msg>Remove parameters from `into_*` conversions and replace `n_map_polygon` with `remap`.<commit_after>//! This module provides a generic iterator and traits for decomposing
//! primitives and tessellating polygons.

use arrayvec::ArrayVec;
use std::collections::VecDeque;
use std::iter::IntoIterator;
use std::vec;

use math::{self, FScalar};
use super::primitive::{Line, Polygon, Polygonal, Primitive, Triangle, Quad};

// A type `F` constrained to `Fn(P, D) -> R` could be used here, but it would
// not be possible to name that type for anything but functions (not closures).
// Instead of a limited and somewhat redundant type `F`, just use `fn(P, D) ->
// R` for the member `f`.
pub struct Decompose<I, P, Q, R>
where
    R: IntoIterator<Item = Q>,
{
    input: I,
    output: VecDeque<Q>,
    f: fn(P) -> R,
}

impl<I, P, Q, R> Decompose<I, P, Q, R>
where
    R: IntoIterator<Item = Q>,
{
    pub(super) fn new(input: I, f: fn(P) -> R) -> Self {
        Decompose {
            input: input,
            output: VecDeque::new(),
            f: f,
        }
    }
}

impl<I, P, R> Decompose<I, P, P, R>
where
    I: Iterator<Item = P>,
    P: Primitive,
    R: IntoIterator<Item = P>,
{
    pub fn remap(self, n: usize) -> Decompose<vec::IntoIter<P>, P, P, R> {
        let Decompose { input, output, f } = self;
        Decompose::new(
            output
                .into_iter()
                .rev()
                .chain(remap(n, input, f))
                .collect::<Vec<_>>() // TODO: Only needed to name the iterator.
                .into_iter(),
            f,
        )
    }
}

impl<I, P, Q, R> Iterator for Decompose<I, P, Q, R>
where
    I: Iterator<Item = P>,
    R: IntoIterator<Item = Q>,
{
    type Item = Q;

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            if let Some(primitive) = self.output.pop_front() {
                return Some(primitive);
            }
            if let Some(primitive) = self.input.next() {
                self.output.extend((self.f)(primitive));
            }
            else {
                return None;
            }
        }
    }
}

pub trait Interpolate: math::Interpolate<FScalar> {}

impl<T> Interpolate for T
where
    T: math::Interpolate<FScalar>,
{
}

pub trait IntoPoints: Primitive {
    type Output: IntoIterator<Item = Self::Point>;

    fn into_points(self) -> Self::Output;
}

pub trait IntoLines: Primitive {
    type Output: IntoIterator<Item = Line<Self::Point>>;

    fn into_lines(self) -> Self::Output;
}

pub trait IntoTriangles: Polygonal {
    type Output: IntoIterator<Item = Triangle<Self::Point>>;

    fn into_triangles(self) -> Self::Output;
}

pub trait IntoSubdivisions: Polygonal
where
    Self::Point: Clone + Interpolate,
{
    type Output: IntoIterator<Item = Self>;

    fn into_subdivisions(self) -> Self::Output;
}

pub trait IntoTetrahedrons: Polygonal
where
    Self::Point: Clone + Interpolate,
{
    fn into_tetrahedrons(self) -> ArrayVec<[Triangle<Self::Point>; 4]>;
}

impl<T> IntoPoints for Line<T>
where
    T: Clone,
{
    type Output = ArrayVec<[Self::Point; 2]>;

    fn into_points(self) -> Self::Output {
        let Line { a, b } = self;
        ArrayVec::from([a, b])
    }
}

impl<T> IntoPoints for Triangle<T>
where
    T: Clone,
{
    type Output = ArrayVec<[Self::Point; 3]>;

    fn into_points(self) -> Self::Output {
        let Triangle { a, b, c } = self;
        ArrayVec::from([a, b, c])
    }
}

impl<T> IntoPoints for Quad<T>
where
    T: Clone,
{
    type Output = ArrayVec<[Self::Point; 4]>;

    fn into_points(self) -> Self::Output {
        let Quad { a, b, c, d } = self;
        ArrayVec::from([a, b, c, d])
    }
}

impl<T> IntoPoints for Polygon<T>
where
    T: Clone,
{
    type Output = Vec<Self::Point>;

    fn into_points(self) -> Self::Output {
        match self {
            Polygon::Triangle(triangle) => triangle.into_points().into_iter().collect(),
            Polygon::Quad(quad) => quad.into_points().into_iter().collect(),
        }
    }
}

impl<T> IntoLines for Line<T>
where
    T: Clone,
{
    type Output = ArrayVec<[Line<Self::Point>; 1]>;

    fn into_lines(self) -> Self::Output {
        ArrayVec::from([self])
    }
}

impl<T> IntoLines for Triangle<T>
where
    T: Clone,
{
    type Output = ArrayVec<[Line<Self::Point>; 3]>;

    fn into_lines(self) -> Self::Output {
        let Triangle { a, b, c } = self;
        ArrayVec::from(
            [
                Line::new(a.clone(), b.clone()),
                Line::new(b, c.clone()),
                Line::new(c, a),
            ],
        )
    }
}

impl<T> IntoLines for Quad<T>
where
    T: Clone,
{
    type Output = ArrayVec<[Line<Self::Point>; 4]>;

    fn into_lines(self) -> Self::Output {
        let Quad { a, b, c, d } = self;
        ArrayVec::from(
            [
                Line::new(a.clone(), b.clone()),
                Line::new(b, c.clone()),
                Line::new(c, d.clone()),
                Line::new(d, a),
            ],
        )
    }
}

impl<T> IntoLines for Polygon<T>
where
    T: Clone,
{
    type Output = Vec<Line<Self::Point>>;

    fn into_lines(self) -> Self::Output {
        match self {
            Polygon::Triangle(triangle) => triangle.into_lines().into_iter().collect(),
            Polygon::Quad(quad) => quad.into_lines().into_iter().collect(),
        }
    }
}

impl<T> IntoTriangles for Triangle<T>
where
    T: Clone,
{
    type Output = ArrayVec<[Triangle<Self::Point>; 1]>;

    fn into_triangles(self) -> Self::Output {
        ArrayVec::from([self])
    }
}

impl<T> IntoTriangles for Quad<T>
where
    T: Clone,
{
    type Output = ArrayVec<[Triangle<Self::Point>; 2]>;

    fn into_triangles(self) -> Self::Output {
        let Quad { a, b, c, d } = self;
        ArrayVec::from(
            [
                Triangle::new(a.clone(), b, c.clone()),
                Triangle::new(c, d, a),
            ],
        )
    }
}

impl<T> IntoTriangles for Polygon<T>
where
    T: Clone,
{
    type Output = Vec<Triangle<Self::Point>>;

    fn into_triangles(self) -> Self::Output {
        match self {
            Polygon::Triangle(triangle) => triangle.into_triangles().into_iter().collect(),
            Polygon::Quad(quad) => quad.into_triangles().into_iter().collect(),
        }
    }
}

impl<T> IntoSubdivisions for Triangle<T>
where
    T: Clone + Interpolate,
{
    type Output = ArrayVec<[Triangle<Self::Point>; 2]>;

    fn into_subdivisions(self) -> Self::Output {
        let Triangle { a, b, c } = self;
        let ac = a.midpoint(&c);
        ArrayVec::from(
            [
                Triangle::new(b.clone(), ac.clone(), a),
                Triangle::new(c, ac, b),
            ],
        )
    }
}

impl<T> IntoSubdivisions for Quad<T>
where
    T: Clone + Interpolate,
{
    type Output = ArrayVec<[Quad<Self::Point>; 4]>;

    fn into_subdivisions(self) -> Self::Output {
        let Quad { a, b, c, d } = self;
        let ab = a.midpoint(&b);
        let bc = b.midpoint(&c);
        let cd = c.midpoint(&d);
        let da = d.midpoint(&a);
        let ac = a.midpoint(&c); // Diagonal.
        ArrayVec::from(
            [
                Quad::new(a, ab.clone(), ac.clone(), da.clone()),
                Quad::new(ab, b, bc.clone(), ac.clone()),
                Quad::new(ac.clone(), bc, c, cd.clone()),
                Quad::new(da, ac, cd, d),
            ],
        )
    }
}

impl<T> IntoTetrahedrons for Quad<T>
where
    T: Clone + Interpolate,
{
    fn into_tetrahedrons(self) -> ArrayVec<[Triangle<Self::Point>; 4]> {
        let Quad { a, b, c, d } = self;
        let ac = a.midpoint(&c); // Diagonal.
        ArrayVec::from(
            [
                Triangle::new(a.clone(), b.clone(), ac.clone()),
                Triangle::new(b, c.clone(), ac.clone()),
                Triangle::new(c, d.clone(), ac.clone()),
                Triangle::new(d, a, ac),
            ],
        )
    }
}

impl<T> IntoSubdivisions for Polygon<T>
where
    T: Clone + Interpolate,
{
    type Output = Vec<Self>;

    fn into_subdivisions(self) -> Self::Output {
        match self {
            Polygon::Triangle(triangle) => {
                triangle
                    .into_subdivisions()
                    .into_iter()
                    .map(|triangle| triangle.into())
                    .collect()
            }
            Polygon::Quad(quad) => {
                quad.into_subdivisions()
                    .into_iter()
                    .map(|quad| quad.into())
                    .collect()
            }
        }
    }
}

pub trait Points<P>: Sized
where
    P: IntoPoints,
{
    fn points(self) -> Decompose<Self, P, P::Point, P::Output>;
}

impl<I, P> Points<P> for I
where
    I: Iterator<Item = P>,
    P: IntoPoints,
    P::Point: Clone,
{
    fn points(self) -> Decompose<Self, P, P::Point, P::Output> {
        Decompose::new(self, P::into_points)
    }
}

pub trait Lines<P>: Sized
where
    P: IntoLines,
{
    fn lines(self) -> Decompose<Self, P, Line<P::Point>, P::Output>;
}

impl<I, P> Lines<P> for I
where
    I: Iterator<Item = P>,
    P: IntoLines,
    P::Point: Clone,
{
    fn lines(self) -> Decompose<Self, P, Line<P::Point>, P::Output> {
        Decompose::new(self, P::into_lines)
    }
}

pub trait Triangulate<P>: Sized
where
    P: IntoTriangles,
{
    fn triangulate(self) -> Decompose<Self, P, Triangle<P::Point>, P::Output>;
}

impl<I, P> Triangulate<P> for I
where
    I: Iterator<Item = P>,
    P: IntoTriangles,
    P::Point: Clone,
{
    fn triangulate(self) -> Decompose<Self, P, Triangle<P::Point>, P::Output> {
        Decompose::new(self, P::into_triangles)
    }
}

pub trait Subdivide<P>: Sized
where
    P: IntoSubdivisions,
    P::Point: Clone + Interpolate,
{
    fn subdivide(self) -> Decompose<Self, P, P, P::Output>;
}

impl<I, P> Subdivide<P> for I
where
    I: Iterator<Item = P>,
    P: IntoSubdivisions,
    P::Point: Clone + Interpolate,
{
    fn subdivide(self) -> Decompose<Self, P, P, P::Output> {
        Decompose::new(self, P::into_subdivisions)
    }
}

pub trait Tetrahedrons<T>: Sized {
    #[allow(type_complexity)]
    fn tetrahedrons(self) -> Decompose<Self, Quad<T>, Triangle<T>, ArrayVec<[Triangle<T>; 4]>>;
}

impl<I, T> Tetrahedrons<T> for I
where
    I: Iterator<Item = Quad<T>>,
    T: Clone + Interpolate,
{
    #[allow(type_complexity)]
    fn tetrahedrons(self) -> Decompose<Self, Quad<T>, Triangle<T>, ArrayVec<[Triangle<T>; 4]>> {
        Decompose::new(self, Quad::into_tetrahedrons)
    }
}

fn remap<I, P, R, F>(n: usize, primitives: I, f: F) -> Vec<P>
where
    I: IntoIterator<Item = P>,
    P: Primitive,
    P::Point: Clone,
    R: IntoIterator<Item = P>,
    F: Fn(P) -> R,
{
    let mut primitives: Vec<_> = primitives.into_iter().collect();
    for _ in 0..n {
        primitives = primitives.into_iter().flat_map(&f).collect();
    }
    primitives
}
<|endoftext|>


<commit_before>use std::convert::Into;
use std::marker::PhantomData;
use std::mem;

use math;

pub trait Primitive: Sized {
    type Point: Clone;
}

pub trait Polygonal: Primitive {}

pub trait MapPrimitive<T, U>: Primitive<Point = T>
where
    T: Clone,
    U: Clone,
{
    type Output: Primitive<Point = U>;

    fn map_primitive<F>(self, f: F) -> Self::Output
    where
        F: FnMut(T) -> U;
}

pub trait MapPoints<T, U>: Sized
where
    T: Clone,
    U: Clone,
{
    fn map_points<F>(self, f: F) -> Map<Self, T, U, F>
    where
        F: FnMut(T) -> U;
}

pub trait Rotate {
    fn rotate(&mut self, n: isize);
}

impl<I, T, U, P, Q> MapPoints<T, U> for I
where
    I: Iterator<Item = P>,
    P: MapPrimitive<T, U, Output = Q>,
    Q: Primitive<Point = U>,
    T: Clone,
    U: Clone,
{
    fn map_points<F>(self, f: F) -> Map<Self, T, U, F>
    where
        F: FnMut(T) -> U,
    {
        Map::new(self, f)
    }
}

pub struct Map<I, T, U, F> {
    primitives: I,
    f: F,
    phantom: PhantomData<(T, U)>,
}

impl<I, T, U, F> Map<I, T, U, F> {
    fn new(primitives: I, f: F) -> Self {
        Map {
            primitives: primitives,
            f: f,
            phantom: PhantomData,
        }
    }
}

impl<I, T, U, F, P, Q> Iterator for Map<I, T, U, F>
where
    I: Iterator<Item = P>,
    F: FnMut(T) -> U,
    P: MapPrimitive<T, U, Output = Q>,
    Q: Primitive<Point = U>,
    T: Clone,
    U: Clone,
{
    type Item = Q;

    fn next(&mut self) -> Option<Self::Item> {
        self.primitives
            .next()
            .map(|primitive| primitive.map_primitive(&mut self.f))
    }
}

pub struct Line<T> {
    pub a: T,
    pub b: T,
}

impl<T> Line<T> {
    pub fn new(a: T, b: T) -> Self {
        Line { a: a, b: b }
    }

    pub fn converged(value: T) -> Self
    where
        T: Clone,
    {
        Line::new(value.clone(), value)
    }
}

impl<T, U> MapPrimitive<T, U> for Line<T>
where
    T: Clone,
    U: Clone,
{
    type Output = Line<U>;

    fn map_primitive<F>(self, mut f: F) -> Self::Output
    where
        F: FnMut(T) -> U,
    {
        let Line { a, b } = self;
        Line::new(f(a), f(b))
    }
}

impl<T> Primitive for Line<T>
where
    T: Clone,
{
    type Point = T;
}

impl<T> Rotate for Line<T>
where
    T: Clone,
{
    fn rotate(&mut self, n: isize) {
        if n % 2 != 0 {
            mem::swap(&mut self.a, &mut self.b);
        }
    }
}

pub struct Triangle<T> {
    pub a: T,
    pub b: T,
    pub c: T,
}

impl<T> Triangle<T> {
    pub fn new(a: T, b: T, c: T) -> Self {
        Triangle { a: a, b: b, c: c }
    }

    pub fn converged(value: T) -> Self
    where
        T: Clone,
    {
        Triangle::new(value.clone(), value.clone(), value)
    }
}

impl<T> Into<Polygon<T>> for Triangle<T> {
    fn into(self) -> Polygon<T> {
        Polygon::Triangle(self)
    }
}

impl<T, U> MapPrimitive<T, U> for Triangle<T>
where
    T: Clone,
    U: Clone,
{
    type Output = Triangle<U>;

    fn map_primitive<F>(self, mut f: F) -> Self::Output
    where
        F: FnMut(T) -> U,
    {
        let Triangle { a, b, c } = self;
        Triangle::new(f(a), f(b), f(c))
    }
}

impl<T> Primitive for Triangle<T>
where
    T: Clone,
{
    type Point = T;
}

impl<T> Polygonal for Triangle<T>
where
    T: Clone,
{
}

impl<T> Rotate for Triangle<T>
where
    T: Clone,
{
    fn rotate(&mut self, n: isize) {
        let n = math::umod(n, 3);
        if n == 1 {
            mem::swap(&mut self.a, &mut self.b);
            mem::swap(&mut self.b, &mut self.c);
        }
        else if n == 2 {
            mem::swap(&mut self.c, &mut self.b);
            mem::swap(&mut self.b, &mut self.a);
        }
    }
}

pub struct Quad<T> {
    pub a: T,
    pub b: T,
    pub c: T,
    pub d: T,
}

impl<T> Quad<T> {
    pub fn new(a: T, b: T, c: T, d: T) -> Self {
        Quad {
            a: a,
            b: b,
            c: c,
            d: d,
        }
    }

    pub fn converged(value: T) -> Self
    where
        T: Clone,
    {
        Quad::new(value.clone(), value.clone(), value.clone(), value)
    }
}

impl<T> Into<Polygon<T>> for Quad<T> {
    fn into(self) -> Polygon<T> {
        Polygon::Quad(self)
    }
}

impl<T, U> MapPrimitive<T, U> for Quad<T>
where
    T: Clone,
    U: Clone,
{
    type Output = Quad<U>;

    fn map_primitive<F>(self, mut f: F) -> Self::Output
    where
        F: FnMut(T) -> U,
    {
        let Quad { a, b, c, d } = self;
        Quad::new(f(a), f(b), f(c), f(d))
    }
}

impl<T> Primitive for Quad<T>
where
    T: Clone,
{
    type Point = T;
}

impl<T> Polygonal for Quad<T>
where
    T: Clone,
{
}

impl<T> Rotate for Quad<T>
where
    T: Clone,
{
    fn rotate(&mut self, n: isize) {
        let n = math::umod(n, 4);
        if n == 1 {
            mem::swap(&mut self.a, &mut self.b);
            mem::swap(&mut self.b, &mut self.c);
            mem::swap(&mut self.c, &mut self.d);
        }
        else if n == 2 {
            mem::swap(&mut self.a, &mut self.c);
            mem::swap(&mut self.b, &mut self.d);
        }
        else if n == 3 {
            mem::swap(&mut self.d, &mut self.c);
            mem::swap(&mut self.c, &mut self.b);
            mem::swap(&mut self.b, &mut self.a);
        }
    }
}

pub enum Polygon<T> {
    Triangle(Triangle<T>),
    Quad(Quad<T>),
}

impl<T, U> MapPrimitive<T, U> for Polygon<T>
where
    T: Clone,
    U: Clone,
{
    type Output = Polygon<U>;

    fn map_primitive<F>(self, f: F) -> Self::Output
    where
        F: FnMut(T) -> U,
    {
        match self {
            Polygon::Triangle(triangle) => Polygon::Triangle(triangle.map_primitive(f)),
            Polygon::Quad(quad) => Polygon::Quad(quad.map_primitive(f)),
        }
    }
}

impl<T> Primitive for Polygon<T>
where
    T: Clone,
{
    type Point = T;
}

impl<T> Polygonal for Polygon<T>
where
    T: Clone,
{
}

impl<T> Rotate for Polygon<T>
where
    T: Clone,
{
    fn rotate(&mut self, n: isize) {
        match *self {
            Polygon::Triangle(ref mut triangle) => triangle.rotate(n),
            Polygon::Quad(ref mut quad) => quad.rotate(n),
        }
    }
}
<commit_msg>Implement `From` instead of `Into`.<commit_after>use std::convert::From;
use std::marker::PhantomData;
use std::mem;

use math;

pub trait Primitive: Sized {
    type Point: Clone;
}

pub trait Polygonal: Primitive {}

pub trait MapPrimitive<T, U>: Primitive<Point = T>
where
    T: Clone,
    U: Clone,
{
    type Output: Primitive<Point = U>;

    fn map_primitive<F>(self, f: F) -> Self::Output
    where
        F: FnMut(T) -> U;
}

pub trait MapPoints<T, U>: Sized
where
    T: Clone,
    U: Clone,
{
    fn map_points<F>(self, f: F) -> Map<Self, T, U, F>
    where
        F: FnMut(T) -> U;
}

pub trait Rotate {
    fn rotate(&mut self, n: isize);
}

impl<I, T, U, P, Q> MapPoints<T, U> for I
where
    I: Iterator<Item = P>,
    P: MapPrimitive<T, U, Output = Q>,
    Q: Primitive<Point = U>,
    T: Clone,
    U: Clone,
{
    fn map_points<F>(self, f: F) -> Map<Self, T, U, F>
    where
        F: FnMut(T) -> U,
    {
        Map::new(self, f)
    }
}

pub struct Map<I, T, U, F> {
    primitives: I,
    f: F,
    phantom: PhantomData<(T, U)>,
}

impl<I, T, U, F> Map<I, T, U, F> {
    fn new(primitives: I, f: F) -> Self {
        Map {
            primitives: primitives,
            f: f,
            phantom: PhantomData,
        }
    }
}

impl<I, T, U, F, P, Q> Iterator for Map<I, T, U, F>
where
    I: Iterator<Item = P>,
    F: FnMut(T) -> U,
    P: MapPrimitive<T, U, Output = Q>,
    Q: Primitive<Point = U>,
    T: Clone,
    U: Clone,
{
    type Item = Q;

    fn next(&mut self) -> Option<Self::Item> {
        self.primitives
            .next()
            .map(|primitive| primitive.map_primitive(&mut self.f))
    }
}

pub struct Line<T> {
    pub a: T,
    pub b: T,
}

impl<T> Line<T> {
    pub fn new(a: T, b: T) -> Self {
        Line { a: a, b: b }
    }

    pub fn converged(value: T) -> Self
    where
        T: Clone,
    {
        Line::new(value.clone(), value)
    }
}

impl<T, U> MapPrimitive<T, U> for Line<T>
where
    T: Clone,
    U: Clone,
{
    type Output = Line<U>;

    fn map_primitive<F>(self, mut f: F) -> Self::Output
    where
        F: FnMut(T) -> U,
    {
        let Line { a, b } = self;
        Line::new(f(a), f(b))
    }
}

impl<T> Primitive for Line<T>
where
    T: Clone,
{
    type Point = T;
}

impl<T> Rotate for Line<T>
where
    T: Clone,
{
    fn rotate(&mut self, n: isize) {
        if n % 2 != 0 {
            mem::swap(&mut self.a, &mut self.b);
        }
    }
}

pub struct Triangle<T> {
    pub a: T,
    pub b: T,
    pub c: T,
}

impl<T> Triangle<T> {
    pub fn new(a: T, b: T, c: T) -> Self {
        Triangle { a: a, b: b, c: c }
    }

    pub fn converged(value: T) -> Self
    where
        T: Clone,
    {
        Triangle::new(value.clone(), value.clone(), value)
    }
}

impl<T, U> MapPrimitive<T, U> for Triangle<T>
where
    T: Clone,
    U: Clone,
{
    type Output = Triangle<U>;

    fn map_primitive<F>(self, mut f: F) -> Self::Output
    where
        F: FnMut(T) -> U,
    {
        let Triangle { a, b, c } = self;
        Triangle::new(f(a), f(b), f(c))
    }
}

impl<T> Primitive for Triangle<T>
where
    T: Clone,
{
    type Point = T;
}

impl<T> Polygonal for Triangle<T>
where
    T: Clone,
{
}

impl<T> Rotate for Triangle<T>
where
    T: Clone,
{
    fn rotate(&mut self, n: isize) {
        let n = math::umod(n, 3);
        if n == 1 {
            mem::swap(&mut self.a, &mut self.b);
            mem::swap(&mut self.b, &mut self.c);
        }
        else if n == 2 {
            mem::swap(&mut self.c, &mut self.b);
            mem::swap(&mut self.b, &mut self.a);
        }
    }
}

pub struct Quad<T> {
    pub a: T,
    pub b: T,
    pub c: T,
    pub d: T,
}

impl<T> Quad<T> {
    pub fn new(a: T, b: T, c: T, d: T) -> Self {
        Quad {
            a: a,
            b: b,
            c: c,
            d: d,
        }
    }

    pub fn converged(value: T) -> Self
    where
        T: Clone,
    {
        Quad::new(value.clone(), value.clone(), value.clone(), value)
    }
}

impl<T, U> MapPrimitive<T, U> for Quad<T>
where
    T: Clone,
    U: Clone,
{
    type Output = Quad<U>;

    fn map_primitive<F>(self, mut f: F) -> Self::Output
    where
        F: FnMut(T) -> U,
    {
        let Quad { a, b, c, d } = self;
        Quad::new(f(a), f(b), f(c), f(d))
    }
}

impl<T> Primitive for Quad<T>
where
    T: Clone,
{
    type Point = T;
}

impl<T> Polygonal for Quad<T>
where
    T: Clone,
{
}

impl<T> Rotate for Quad<T>
where
    T: Clone,
{
    fn rotate(&mut self, n: isize) {
        let n = math::umod(n, 4);
        if n == 1 {
            mem::swap(&mut self.a, &mut self.b);
            mem::swap(&mut self.b, &mut self.c);
            mem::swap(&mut self.c, &mut self.d);
        }
        else if n == 2 {
            mem::swap(&mut self.a, &mut self.c);
            mem::swap(&mut self.b, &mut self.d);
        }
        else if n == 3 {
            mem::swap(&mut self.d, &mut self.c);
            mem::swap(&mut self.c, &mut self.b);
            mem::swap(&mut self.b, &mut self.a);
        }
    }
}

pub enum Polygon<T> {
    Triangle(Triangle<T>),
    Quad(Quad<T>),
}

impl<T> From<Triangle<T>> for Polygon<T> {
    fn from(triangle: Triangle<T>) -> Self {
        Polygon::Triangle(triangle)
    }
}

impl<T> From<Quad<T>> for Polygon<T> {
    fn from(quad: Quad<T>) -> Self {
        Polygon::Quad(quad)
    }
}

impl<T, U> MapPrimitive<T, U> for Polygon<T>
where
    T: Clone,
    U: Clone,
{
    type Output = Polygon<U>;

    fn map_primitive<F>(self, f: F) -> Self::Output
    where
        F: FnMut(T) -> U,
    {
        match self {
            Polygon::Triangle(triangle) => Polygon::Triangle(triangle.map_primitive(f)),
            Polygon::Quad(quad) => Polygon::Quad(quad.map_primitive(f)),
        }
    }
}

impl<T> Primitive for Polygon<T>
where
    T: Clone,
{
    type Point = T;
}

impl<T> Polygonal for Polygon<T>
where
    T: Clone,
{
}

impl<T> Rotate for Polygon<T>
where
    T: Clone,
{
    fn rotate(&mut self, n: isize) {
        match *self {
            Polygon::Triangle(ref mut triangle) => triangle.rotate(n),
            Polygon::Quad(ref mut quad) => quad.rotate(n),
        }
    }
}
<|endoftext|>


<commit_before>use prometheus::{Histogram, HistogramOpts, HistogramVec, Opts};

/// Prometheus's histograms work by dividing datapoints in buckets, with each bucket containing
/// the count of datapoints equal or greater to the bucket value.
///
/// The buckets used by crates.io are geared towards measuring the response time of our requests,
/// going from 0.5ms to 100ms with a higher resolution and from 100ms to 5 seconds with a slightly
/// lower resolution. This allows us to properly measure download requests (which take around 1ms)
/// and other requests (our 95h is around 10-20ms).
///
/// Histogram buckets are not an exact science, so feel free to tweak the buckets if you see that
/// the histograms are not really accurate. Just avoid adding too many buckets as that increases
/// the number of exported metric series.
const HISTOGRAM_BUCKETS: &[f64] = &[
    0.0005, 0.001, 0.0025, 0.005, 0.01, 0.025, 0.05, 0.1, 0.5, 1.0, 5.0,
];

pub(super) trait MetricFromOpts: Sized {
    fn from_opts(opts: Opts) -> Result<Self, prometheus::Error>;
}

#[macro_export]
macro_rules! metrics {
    (
        $vis:vis struct $name:ident {
            $(
                #[doc = $help:expr]
                $(#[$meta:meta])*
                $metric_vis:vis $metric:ident: $ty:ty $([$($label:expr),* $(,)?])?
            ),* $(,)?
        }
        namespace: $namespace:expr,
    ) => {
        $vis struct $name {
            registry: prometheus::Registry,
            $(
                $(#[$meta])*
                $metric_vis $metric: $ty,
            )*
        }
        impl $name {
            $vis fn new() -> Result<Self, prometheus::Error> {
                use crate::metrics::macros::MetricFromOpts;

                let registry = prometheus::Registry::new();
                $(
                    $(#[$meta])*
                    let $metric = <$ty>::from_opts(
                        prometheus::Opts::new(stringify!($metric), $help)
                            .namespace($namespace)
                            $(.variable_labels(vec![$($label.into()),*]))?
                    )?;
                    $(#[$meta])*
                    registry.register(Box::new($metric.clone()))?;
                )*
                Ok(Self {
                    registry,
                    $(
                        $(#[$meta])*
                        $metric,
                    )*
                })
            }
        }
        impl std::fmt::Debug for $name {
            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                write!(f, "{}", stringify!($name))
            }
        }
    };
}

macro_rules! load_metric_type {
    ($name:ident as single) => {
        use prometheus::$name;
        impl MetricFromOpts for $name {
            fn from_opts(opts: Opts) -> Result<Self, prometheus::Error> {
                $name::with_opts(opts.into())
            }
        }
    };
    ($name:ident as vec) => {
        use prometheus::$name;
        impl MetricFromOpts for $name {
            fn from_opts(opts: Opts) -> Result<Self, prometheus::Error> {
                $name::new(
                    opts.clone().into(),
                    opts.variable_labels
                        .iter()
                        .map(|s| s.as_str())
                        .collect::<Vec<_>>()
                        .as_slice(),
                )
            }
        }
    };
}

load_metric_type!(Counter as single);
load_metric_type!(CounterVec as vec);
load_metric_type!(IntCounter as single);
load_metric_type!(IntCounterVec as vec);
load_metric_type!(Gauge as single);
load_metric_type!(GaugeVec as vec);
load_metric_type!(IntGauge as single);
load_metric_type!(IntGaugeVec as vec);

// Use a custom implementation for histograms to customize the buckets.

impl MetricFromOpts for Histogram {
    fn from_opts(opts: Opts) -> Result<Self, prometheus::Error> {
        Histogram::with_opts(HistogramOpts {
            common_opts: opts,
            buckets: HISTOGRAM_BUCKETS.to_vec(),
        })
    }
}

impl MetricFromOpts for HistogramVec {
    fn from_opts(opts: Opts) -> Result<Self, prometheus::Error> {
        HistogramVec::new(
            HistogramOpts {
                common_opts: opts.clone(),
                buckets: HISTOGRAM_BUCKETS.to_vec(),
            },
            opts.variable_labels
                .iter()
                .map(|s| s.as_str())
                .collect::<Vec<_>>()
                .as_slice(),
        )
    }
}
<commit_msg>metrics::macros: Fix clippy warning<commit_after>use prometheus::{Histogram, HistogramOpts, HistogramVec, Opts};

/// Prometheus's histograms work by dividing datapoints in buckets, with each bucket containing
/// the count of datapoints equal or greater to the bucket value.
///
/// The buckets used by crates.io are geared towards measuring the response time of our requests,
/// going from 0.5ms to 100ms with a higher resolution and from 100ms to 5 seconds with a slightly
/// lower resolution. This allows us to properly measure download requests (which take around 1ms)
/// and other requests (our 95h is around 10-20ms).
///
/// Histogram buckets are not an exact science, so feel free to tweak the buckets if you see that
/// the histograms are not really accurate. Just avoid adding too many buckets as that increases
/// the number of exported metric series.
const HISTOGRAM_BUCKETS: &[f64] = &[
    0.0005, 0.001, 0.0025, 0.005, 0.01, 0.025, 0.05, 0.1, 0.5, 1.0, 5.0,
];

pub(super) trait MetricFromOpts: Sized {
    fn from_opts(opts: Opts) -> Result<Self, prometheus::Error>;
}

#[macro_export]
macro_rules! metrics {
    (
        $vis:vis struct $name:ident {
            $(
                #[doc = $help:expr]
                $(#[$meta:meta])*
                $metric_vis:vis $metric:ident: $ty:ty $([$($label:expr),* $(,)?])?
            ),* $(,)?
        }
        namespace: $namespace:expr,
    ) => {
        $vis struct $name {
            registry: prometheus::Registry,
            $(
                $(#[$meta])*
                $metric_vis $metric: $ty,
            )*
        }
        impl $name {
            $vis fn new() -> Result<Self, prometheus::Error> {
                use $crate::metrics::macros::MetricFromOpts;

                let registry = prometheus::Registry::new();
                $(
                    $(#[$meta])*
                    let $metric = <$ty>::from_opts(
                        prometheus::Opts::new(stringify!($metric), $help)
                            .namespace($namespace)
                            $(.variable_labels(vec![$($label.into()),*]))?
                    )?;
                    $(#[$meta])*
                    registry.register(Box::new($metric.clone()))?;
                )*
                Ok(Self {
                    registry,
                    $(
                        $(#[$meta])*
                        $metric,
                    )*
                })
            }
        }
        impl std::fmt::Debug for $name {
            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                write!(f, "{}", stringify!($name))
            }
        }
    };
}

macro_rules! load_metric_type {
    ($name:ident as single) => {
        use prometheus::$name;
        impl MetricFromOpts for $name {
            fn from_opts(opts: Opts) -> Result<Self, prometheus::Error> {
                $name::with_opts(opts.into())
            }
        }
    };
    ($name:ident as vec) => {
        use prometheus::$name;
        impl MetricFromOpts for $name {
            fn from_opts(opts: Opts) -> Result<Self, prometheus::Error> {
                $name::new(
                    opts.clone().into(),
                    opts.variable_labels
                        .iter()
                        .map(|s| s.as_str())
                        .collect::<Vec<_>>()
                        .as_slice(),
                )
            }
        }
    };
}

load_metric_type!(Counter as single);
load_metric_type!(CounterVec as vec);
load_metric_type!(IntCounter as single);
load_metric_type!(IntCounterVec as vec);
load_metric_type!(Gauge as single);
load_metric_type!(GaugeVec as vec);
load_metric_type!(IntGauge as single);
load_metric_type!(IntGaugeVec as vec);

// Use a custom implementation for histograms to customize the buckets.

impl MetricFromOpts for Histogram {
    fn from_opts(opts: Opts) -> Result<Self, prometheus::Error> {
        Histogram::with_opts(HistogramOpts {
            common_opts: opts,
            buckets: HISTOGRAM_BUCKETS.to_vec(),
        })
    }
}

impl MetricFromOpts for HistogramVec {
    fn from_opts(opts: Opts) -> Result<Self, prometheus::Error> {
        HistogramVec::new(
            HistogramOpts {
                common_opts: opts.clone(),
                buckets: HISTOGRAM_BUCKETS.to_vec(),
            },
            opts.variable_labels
                .iter()
                .map(|s| s.as_str())
                .collect::<Vec<_>>()
                .as_slice(),
        )
    }
}
<|endoftext|>


<commit_before>use crypto::{ symmetriccipher, buffer, aes, blockmodes };
use crypto::buffer::{ ReadBuffer, WriteBuffer, BufferResult };

pub fn decrypt_aes_128_ecb_no_padding(encrypted_data: Vec<u8>, key: Vec<u8>) -> Result<Vec<u8>, symmetriccipher::SymmetricCipherError> {
    let mut decryptor = aes::ecb_decryptor(
        aes::KeySize::KeySize128,
        &key[..],
        blockmodes::NoPadding
    );

    let mut final_result = Vec::<u8>::new();
    let mut read_buffer = buffer::RefReadBuffer::new(&encrypted_data[..]);
    let mut buffer = [0; 4096];
    let mut write_buffer = buffer::RefWriteBuffer::new(&mut buffer);

    loop {
        let result = try!(decryptor.decrypt(&mut read_buffer, &mut write_buffer, true));
        final_result.extend(write_buffer.take_read_buffer().take_remaining().iter().map(|&i| i));
        match result {
            BufferResult::BufferUnderflow => break,
            BufferResult::BufferOverflow => { }
        }
    }

    Ok(final_result)
}<commit_msg>Adding credit<commit_after>use crypto::{ symmetriccipher, buffer, aes, blockmodes };
use crypto::buffer::{ ReadBuffer, WriteBuffer, BufferResult };

pub fn decrypt_aes_128_ecb_no_padding(encrypted_data: Vec<u8>, key: Vec<u8>) -> Result<Vec<u8>, symmetriccipher::SymmetricCipherError> {
    // https://github.com/DaGenix/rust-crypto/blob/master/examples/symmetriccipher.rs
    let mut decryptor = aes::ecb_decryptor(
        aes::KeySize::KeySize128,
        &key[..],
        blockmodes::NoPadding
    );

    let mut final_result = Vec::<u8>::new();
    let mut read_buffer = buffer::RefReadBuffer::new(&encrypted_data[..]);
    let mut buffer = [0; 4096];
    let mut write_buffer = buffer::RefWriteBuffer::new(&mut buffer);

    loop {
        let result = try!(decryptor.decrypt(&mut read_buffer, &mut write_buffer, true));
        final_result.extend(write_buffer.take_read_buffer().take_remaining().iter().map(|&i| i));
        match result {
            BufferResult::BufferUnderflow => break,
            BufferResult::BufferOverflow => { }
        }
    }

    Ok(final_result)
}<|endoftext|>


<commit_before>// Copyright (c) Facebook, Inc. and its affiliates
// SPDX-License-Identifier: MIT OR Apache-2.0

use serde::{Deserialize, Serialize};
use serde_generate::python3;
use serde_reflection::{Registry, Result, Samples, Tracer, TracerConfig};
use std::fs::File;
use std::io::Write;
use std::process::Command;
use tempfile::tempdir;

#[derive(Serialize, Deserialize)]
struct Test {
    a: Vec<u64>,
    b: (u32, u32),
    c: Choice,
}

#[derive(Serialize, Deserialize)]
enum Choice {
    A,
    B(u64),
    C { x: u8 },
}

fn get_local_registry() -> Result<Registry> {
    let mut tracer = Tracer::new(TracerConfig::default());
    let samples = Samples::new();
    tracer.trace_type::<Test>(&samples)?;
    tracer.trace_type::<Choice>(&samples)?;
    Ok(tracer.registry()?)
}

#[test]
fn test_python_bincode_runtime_on_simple_data() {
    let registry = get_local_registry().unwrap();
    let dir = tempdir().unwrap();
    let source_path = dir.path().join("test.py");
    let mut source = File::create(&source_path).unwrap();
    python3::output(&mut source, &registry).unwrap();

    let reference = bincode::serialize(&Test {
        a: vec![4, 6],
        b: (3, 5),
        c: Choice::C { x: 7 },
    })
    .unwrap();
    writeln!(
        source,
        r#"
import bincode

value = Test([4, 6], (3, 5), Choice.C(7))

s = bincode.serialize(value, Test)
assert s == bytes.fromhex("{}")

v, buffer = bincode.deserialize(s, Test)
assert len(buffer) == 0
assert v == value
assert v.c.x == 7

v.b = (3, 0)
t = bincode.serialize(v, Test)
assert len(t) == len(s)
assert t != s
"#,
        hex::encode(&reference),
    )
    .unwrap();

    let python_path = format!(
        "{}:runtime/python",
        std::env::var("PYTHONPATH").unwrap_or(String::new())
    );
    let output = Command::new("python3")
        .arg(source_path)
        .env("PYTHONPATH", python_path)
        .output()
        .unwrap();

    std::io::stdout().write(&output.stdout).unwrap();
    std::io::stderr().write(&output.stderr).unwrap();
    assert_eq!(String::new(), String::from_utf8_lossy(&output.stderr));
    assert!(output.status.success());
}

#[test]
fn test_python_bincode_runtime_on_all_supported_types() {
    let registry = test_utils::get_registry().unwrap();
    let dir = tempdir().unwrap();
    let source_path = dir.path().join("test.py");
    let mut source = File::create(&source_path).unwrap();
    python3::output(&mut source, &registry).unwrap();

    let values = test_utils::get_sample_values();
    let hex_encodings: Vec<_> = values
        .iter()
        .map(|v| format!("'{}'", hex::encode(&bincode::serialize(&v).unwrap())))
        .collect();

    writeln!(
        source,
        r#"
import bincode

encodings = [bytes.fromhex(s) for s in [{}]]

for encoding in encodings:
    v, buffer = bincode.deserialize(encoding, SerdeData)
    assert len(buffer) == 0

    s = bincode.serialize(v, SerdeData)
    assert s == encoding
"#,
        hex_encodings.join(", ")
    )
    .unwrap();

    let python_path = format!(
        "{}:runtime/python",
        std::env::var("PYTHONPATH").unwrap_or(String::new())
    );
    let output = Command::new("python3")
        .arg(source_path)
        .env("PYTHONPATH", python_path)
        .output()
        .unwrap();

    std::io::stdout().write(&output.stdout).unwrap();
    std::io::stderr().write(&output.stderr).unwrap();
    assert_eq!(String::new(), String::from_utf8_lossy(&output.stderr));
    assert!(output.status.success());
}
<commit_msg>[serde generate] e2e runtime test for Rust<commit_after>// Copyright (c) Facebook, Inc. and its affiliates
// SPDX-License-Identifier: MIT OR Apache-2.0

use serde::{Deserialize, Serialize};
use serde_generate::{python3, rust};
use serde_reflection::{Registry, Result, Samples, Tracer, TracerConfig};
use std::fs::File;
use std::io::Write;
use std::process::Command;
use tempfile::tempdir;

#[derive(Serialize, Deserialize)]
struct Test {
    a: Vec<u64>,
    b: (u32, u32),
    c: Choice,
}

#[derive(Serialize, Deserialize)]
enum Choice {
    A,
    B(u64),
    C { x: u8 },
}

fn get_local_registry() -> Result<Registry> {
    let mut tracer = Tracer::new(TracerConfig::default());
    let samples = Samples::new();
    tracer.trace_type::<Test>(&samples)?;
    tracer.trace_type::<Choice>(&samples)?;
    Ok(tracer.registry()?)
}

#[test]
fn test_python_bincode_runtime_on_simple_data() {
    let registry = get_local_registry().unwrap();
    let dir = tempdir().unwrap();
    let source_path = dir.path().join("test.py");
    let mut source = File::create(&source_path).unwrap();
    python3::output(&mut source, &registry).unwrap();

    let reference = bincode::serialize(&Test {
        a: vec![4, 6],
        b: (3, 5),
        c: Choice::C { x: 7 },
    })
    .unwrap();
    writeln!(
        source,
        r#"
import bincode

value = Test([4, 6], (3, 5), Choice.C(7))

s = bincode.serialize(value, Test)
assert s == bytes.fromhex("{}")

v, buffer = bincode.deserialize(s, Test)
assert len(buffer) == 0
assert v == value
assert v.c.x == 7

v.b = (3, 0)
t = bincode.serialize(v, Test)
assert len(t) == len(s)
assert t != s
"#,
        hex::encode(&reference),
    )
    .unwrap();

    let python_path = format!(
        "{}:runtime/python",
        std::env::var("PYTHONPATH").unwrap_or(String::new())
    );
    let output = Command::new("python3")
        .arg(source_path)
        .env("PYTHONPATH", python_path)
        .output()
        .unwrap();

    std::io::stdout().write(&output.stdout).unwrap();
    std::io::stderr().write(&output.stderr).unwrap();
    assert_eq!(String::new(), String::from_utf8_lossy(&output.stderr));
    assert!(output.status.success());
}

#[test]
fn test_python_bincode_runtime_on_all_supported_types() {
    let registry = test_utils::get_registry().unwrap();
    let dir = tempdir().unwrap();
    let source_path = dir.path().join("test.py");
    let mut source = File::create(&source_path).unwrap();
    python3::output(&mut source, &registry).unwrap();

    let values = test_utils::get_sample_values();
    let hex_encodings: Vec<_> = values
        .iter()
        .map(|v| format!("'{}'", hex::encode(&bincode::serialize(&v).unwrap())))
        .collect();

    writeln!(
        source,
        r#"
import bincode

encodings = [bytes.fromhex(s) for s in [{}]]

for encoding in encodings:
    v, buffer = bincode.deserialize(encoding, SerdeData)
    assert len(buffer) == 0

    s = bincode.serialize(v, SerdeData)
    assert s == encoding
"#,
        hex_encodings.join(", ")
    )
    .unwrap();

    let python_path = format!(
        "{}:runtime/python",
        std::env::var("PYTHONPATH").unwrap_or(String::new())
    );
    let output = Command::new("python3")
        .arg(source_path)
        .env("PYTHONPATH", python_path)
        .output()
        .unwrap();

    std::io::stdout().write(&output.stdout).unwrap();
    std::io::stderr().write(&output.stderr).unwrap();
    assert_eq!(String::new(), String::from_utf8_lossy(&output.stderr));
    assert!(output.status.success());
}

// Full test using cargo. This may take a while.
#[test]
fn test_rust_bincode_runtime() {
    let registry = test_utils::get_registry().unwrap();
    let dir = tempdir().unwrap();
    std::fs::write(
        dir.path().join("Cargo.toml"),
        r#"[package]
name = "testing2"
version = "0.1.0"
edition = "2018"

[dependencies]
hex = "0.4.2"
serde = { version = "1.0", features = ["derive"] }
serde_bytes = "0.11"
bincode = "1.2"

[workspace]
"#,
    )
    .unwrap();
    std::fs::create_dir(dir.path().join("src")).unwrap();
    let source_path = dir.path().join("src/main.rs");
    let mut source = File::create(&source_path).unwrap();
    rust::output(&mut source, /* with_derive_macros */ true, &registry).unwrap();

    let values = test_utils::get_sample_values();
    let hex_encodings: Vec<_> = values
        .iter()
        .map(|v| format!("\"{}\"", hex::encode(&bincode::serialize(&v).unwrap())))
        .collect();

    writeln!(
        source,
        r#"
fn main() {{
    let hex_encodings = vec![{}];

    for hex_encoding in hex_encodings {{
        let encoding = hex::decode(hex_encoding).unwrap();
        let value = bincode::deserialize::<SerdeData>(&encoding).unwrap();

        let s = bincode::serialize(&value).unwrap();
        assert_eq!(s, encoding);
    }}
}}
"#,
        hex_encodings.join(", ")
    )
    .unwrap();

    // Use a stable `target` dir to avoid downloading and recompiling crates everytime.
    let target_dir = std::env::current_dir().unwrap().join("../target");
    let output = Command::new("cargo")
        .current_dir(dir.path())
        .arg("run")
        .arg("--target-dir")
        .arg(target_dir)
        .output()
        .unwrap();

    std::io::stdout().write(&output.stdout).unwrap();
    std::io::stderr().write(&output.stderr).unwrap();
    assert!(output.status.success());
}
<|endoftext|>


<commit_before>#![warn(rust_2018_idioms)]
#![cfg(feature = "full")]

use std::io::Read;
use std::io::Result;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpListener;
use tokio::net::TcpStream;

#[tokio::test]
async fn tcp_into_std() -> Result<()> {
    let mut data = [0u8; 12];
    let listener = TcpListener::bind("127.0.0.1:34254").await?;

    let handle = tokio::spawn(async {
        let stream: TcpStream = TcpStream::connect("127.0.0.1:34254").await.unwrap();
        stream
    });

    let (tokio_tcp_stream, _) = listener.accept().await?;
    let mut std_tcp_stream = tokio_tcp_stream.into_std()?;
    std_tcp_stream
        .set_nonblocking(false)
        .expect("set_nonblocking call failed");

    let mut client = handle.await.expect("The task being joined has panicked");
    client.write_all(b"Hello world!").await?;

    std_tcp_stream
        .read_exact(&mut data)
        .expect("std TcpStream read failed!");
    assert_eq!(b"Hello world!", &data);

    // test back to tokio stream
    std_tcp_stream
        .set_nonblocking(true)
        .expect("set_nonblocking call failed");
    let mut tokio_tcp_stream = TcpStream::from_std(std_tcp_stream)?;
    client.write_all(b"Hello tokio!").await?;
    let _size = tokio_tcp_stream.read_exact(&mut data).await?;
    assert_eq!(b"Hello tokio!", &data);

    Ok(())
}
<commit_msg>tcp: assign an unused port (#3817)<commit_after>#![warn(rust_2018_idioms)]
#![cfg(feature = "full")]

use std::io::Read;
use std::io::Result;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpListener;
use tokio::net::TcpStream;

#[tokio::test]
async fn tcp_into_std() -> Result<()> {
    let mut data = [0u8; 12];
    let listener = TcpListener::bind("127.0.0.1:0").await?;
    let addr = listener.local_addr().unwrap().to_string();

    let handle = tokio::spawn(async {
        let stream: TcpStream = TcpStream::connect(addr).await.unwrap();
        stream
    });

    let (tokio_tcp_stream, _) = listener.accept().await?;
    let mut std_tcp_stream = tokio_tcp_stream.into_std()?;
    std_tcp_stream
        .set_nonblocking(false)
        .expect("set_nonblocking call failed");

    let mut client = handle.await.expect("The task being joined has panicked");
    client.write_all(b"Hello world!").await?;

    std_tcp_stream
        .read_exact(&mut data)
        .expect("std TcpStream read failed!");
    assert_eq!(b"Hello world!", &data);

    // test back to tokio stream
    std_tcp_stream
        .set_nonblocking(true)
        .expect("set_nonblocking call failed");
    let mut tokio_tcp_stream = TcpStream::from_std(std_tcp_stream)?;
    client.write_all(b"Hello tokio!").await?;
    let _size = tokio_tcp_stream.read_exact(&mut data).await?;
    assert_eq!(b"Hello tokio!", &data);

    Ok(())
}
<|endoftext|>


<commit_before>use std::thread;
use std::time::Duration;
use time::precise_time_ns;

use bootstrap::{Context, Keyboard, Mouse, MouseMove, Scroll, Window};
pub use bootstrap::{Action, Key, MouseButton};
use camera::{Camera, Freefly};
use transform::Translation;

#[derive(Clone, Copy, Eq, Debug, PartialEq)]
pub struct Unhandled;

/// Class of keyboard handlers.
pub trait KeyboardHandler {
  fn on_key(&mut self, key: Key, action: Action) -> bool;
}

impl KeyboardHandler for Unhandled {
  fn on_key(&mut self, _: Key, _: Action) -> bool { true }
}

/// Class of mouse button handlers.
pub trait MouseButtonHandler {
  fn on_mouse_button(&mut self, button: MouseButton, action: Action) -> bool;
}

impl MouseButtonHandler for Unhandled {
  fn on_mouse_button(&mut self, _: MouseButton, _: Action) -> bool { true }
}

/// Class of mouse move handlers.
pub trait CursorHandler {
  fn on_mouse_move(&mut self, cursor_pos: [f64; 2]) -> bool;
}

impl CursorHandler for Unhandled {
  fn on_mouse_move(&mut self, _: [f64; 2]) -> bool { true }
}

/// Class of scroll handlers.
pub trait ScrollHandler {
  fn on_scroll(&mut self, scroll_dir: [f64; 2]) -> bool;
}

impl ScrollHandler for Unhandled {
  fn on_scroll(&mut self, _: [f64; 2]) -> bool { true }
}

/// All common stuff goes here.
pub struct App {
  /// Some kind of epoch start the application started at.
  start_time: u64,
  /// Keyboard receiver.
  kbd: Keyboard,
  /// Mouse receiver.
  mouse: Mouse,
  /// Cursor receiver.
  cursor: MouseMove,
  /// Scroll receiver.
  scroll: Scroll,
  /// Window.
  window: Window,
}

impl App {
  pub fn init(kbd: Keyboard, mouse: Mouse, cursor: MouseMove, scroll: Scroll, window: Window) -> Self {
    App {
      start_time: precise_time_ns(),
      kbd: kbd,
      mouse: mouse,
      cursor: cursor,
      scroll: scroll,
      window: window
    }
  }

  pub fn time(&self) -> f32 {
    (precise_time_ns() - self.start_time) as f32 * 1e-9
  }

  pub fn dispatch_events<K, MB, MM, S>(&self,
                                       keyboard_handler: &mut K,
                                       mouse_button_handler: &mut MB,
                                       cursor_handler: &mut MM,
                                       scroll_handler: &mut S) -> bool
      where K: KeyboardHandler,
            MB: MouseButtonHandler,
            MM: CursorHandler,
            S: ScrollHandler {
    while let Ok((key, action)) = self.kbd.try_recv() {
      if !keyboard_handler.on_key(key, action) {
        return false;
      }
    }

    while let Ok((button, action)) = self.mouse.try_recv() {
      if !mouse_button_handler.on_mouse_button(button, action) {
        return false;
      }
    }

    while let Ok(xy) = self.cursor.try_recv() {
      if !cursor_handler.on_mouse_move(xy) {
        return false;
      }
    }

    while let Ok(xy) = self.scroll.try_recv() {
      if !scroll_handler.on_scroll(xy) {
        return false;
      }
    }

    true
  }

  pub fn step<R>(&mut self, fps: Option<u32>, mut draw_frame: R) -> bool where R: FnMut(f32) {
    let loop_start_time = precise_time_ns();

    if self.window.should_close() {
      return false;
    }

    let t = self.time();

    draw_frame(t);

    self.window.swap_buffers();

    // wait for next frame according to the wished FPS
    if let Some(fps) = fps {
      let fps = fps as f32;
      let elapsed_time_ms = ((precise_time_ns() - loop_start_time) as f64 * 1e-6) as i64;
      let sleep_time_ms = (1. / fps * 1e3) as i64 - elapsed_time_ms;

      if sleep_time_ms > 0 {
        thread::sleep(Duration::from_millis(sleep_time_ms as u64));
      }
    }

    true
  }
}
<commit_msg>on_mouse_move -> on_cursor_move.<commit_after>use std::thread;
use std::time::Duration;
use time::precise_time_ns;

use bootstrap::{Context, Keyboard, Mouse, MouseMove, Scroll, Window};
pub use bootstrap::{Action, Key, MouseButton};
use camera::{Camera, Freefly};
use transform::Translation;

#[derive(Clone, Copy, Eq, Debug, PartialEq)]
pub struct Unhandled;

/// Class of keyboard handlers.
pub trait KeyboardHandler {
  fn on_key(&mut self, key: Key, action: Action) -> bool;
}

impl KeyboardHandler for Unhandled {
  fn on_key(&mut self, _: Key, _: Action) -> bool { true }
}

/// Class of mouse button handlers.
pub trait MouseButtonHandler {
  fn on_mouse_button(&mut self, button: MouseButton, action: Action) -> bool;
}

impl MouseButtonHandler for Unhandled {
  fn on_mouse_button(&mut self, _: MouseButton, _: Action) -> bool { true }
}

/// Class of mouse move handlers.
pub trait CursorHandler {
  fn on_cursor_move(&mut self, cursor_pos: [f64; 2]) -> bool;
}

impl CursorHandler for Unhandled {
  fn on_cursor_move(&mut self, _: [f64; 2]) -> bool { true }
}

/// Class of scroll handlers.
pub trait ScrollHandler {
  fn on_scroll(&mut self, scroll_dir: [f64; 2]) -> bool;
}

impl ScrollHandler for Unhandled {
  fn on_scroll(&mut self, _: [f64; 2]) -> bool { true }
}

/// All common stuff goes here.
pub struct App {
  /// Some kind of epoch start the application started at.
  start_time: u64,
  /// Keyboard receiver.
  kbd: Keyboard,
  /// Mouse receiver.
  mouse: Mouse,
  /// Cursor receiver.
  cursor: MouseMove,
  /// Scroll receiver.
  scroll: Scroll,
  /// Window.
  window: Window,
}

impl App {
  pub fn init(kbd: Keyboard, mouse: Mouse, cursor: MouseMove, scroll: Scroll, window: Window) -> Self {
    App {
      start_time: precise_time_ns(),
      kbd: kbd,
      mouse: mouse,
      cursor: cursor,
      scroll: scroll,
      window: window
    }
  }

  pub fn time(&self) -> f32 {
    (precise_time_ns() - self.start_time) as f32 * 1e-9
  }

  pub fn dispatch_events<K, MB, MM, S>(&self,
                                       keyboard_handler: &mut K,
                                       mouse_button_handler: &mut MB,
                                       cursor_handler: &mut MM,
                                       scroll_handler: &mut S) -> bool
      where K: KeyboardHandler,
            MB: MouseButtonHandler,
            MM: CursorHandler,
            S: ScrollHandler {
    while let Ok((key, action)) = self.kbd.try_recv() {
      if !keyboard_handler.on_key(key, action) {
        return false;
      }
    }

    while let Ok((button, action)) = self.mouse.try_recv() {
      if !mouse_button_handler.on_mouse_button(button, action) {
        return false;
      }
    }

    while let Ok(xy) = self.cursor.try_recv() {
      if !cursor_handler.on_cursor_move(xy) {
        return false;
      }
    }

    while let Ok(xy) = self.scroll.try_recv() {
      if !scroll_handler.on_scroll(xy) {
        return false;
      }
    }

    true
  }

  pub fn step<R>(&mut self, fps: Option<u32>, mut draw_frame: R) -> bool where R: FnMut(f32) {
    let loop_start_time = precise_time_ns();

    if self.window.should_close() {
      return false;
    }

    let t = self.time();

    draw_frame(t);

    self.window.swap_buffers();

    // wait for next frame according to the wished FPS
    if let Some(fps) = fps {
      let fps = fps as f32;
      let elapsed_time_ms = ((precise_time_ns() - loop_start_time) as f64 * 1e-6) as i64;
      let sleep_time_ms = (1. / fps * 1e3) as i64 - elapsed_time_ms;

      if sleep_time_ms > 0 {
        thread::sleep(Duration::from_millis(sleep_time_ms as u64));
      }
    }

    true
  }
}
<|endoftext|>


<commit_before>extern crate clap;
use clap::{App, ArgMatches};

struct ConfigBase {
    verbosity : bool,
    debugging : bool,
}

pub struct ModuleConfig {
    base : ConfigBase,
    load : bool,
}

impl ModuleConfig {
    pub fn new() -> ModuleConfig {
        ModuleConfig {
            base: ConfigBase {
                verbosity: false,
                debugging: false,
            },
            load: false,
        }
    }
}

pub struct Config {
    base            : ConfigBase,
    module_configs  : Vec<ModuleConfig>,
}

impl Config {
    pub fn new() -> Config {
        Config {
            base: ConfigBase {
                verbosity: false,
                debugging: false,
            },
            module_configs: vec![],
        }
    }
}

pub fn configure(config : &mut Config) {
    let yaml = load_yaml!("../etc/cli.yml");
    let matches = App::from_yaml(yaml).get_matches();

    parse_global_cfg(&matches, &mut config.base);

    if let Some(matches) = matches.subcommand_matches("test") {
        if matches.is_present("verbose") {
            println!("Printing verbosely...");
        } else {
            println!("Printing normally...");
        }
    }
}

fn parse_global_cfg(matches : &ArgMatches<>, config : &mut ConfigBase) {
    config.verbosity = matches.is_present("verbose");
    config.debugging = matches.is_present("debugging");
}

<commit_msg>cli: export data and add helper functions for accessing data<commit_after>extern crate clap;
use clap::{App, ArgMatches};

struct ConfigBase {
    verbosity : bool,
    debugging : bool,
}

pub struct ModuleConfig {
    base : ConfigBase,
    pub load : bool,
}

impl ModuleConfig {
    pub fn new() -> ModuleConfig {
        ModuleConfig {
            base: ConfigBase {
                verbosity: false,
                debugging: false,
            },
            load: false,
        }
    }
}

pub struct Config {
    base            : ConfigBase,
    pub module_configs  : Vec<ModuleConfig>,
}

impl Config {
    pub fn new() -> Config {
        Config {
            base: ConfigBase {
                verbosity: false,
                debugging: false,
            },
            module_configs: vec![],
        }
    }

    pub fn is_verbose(&self) -> bool {
        self.base.verbosity
    }

    pub fn is_debugging(&self) -> bool {
        self.base.debugging
    }
}

pub fn configure(config : &mut Config) {
    let yaml = load_yaml!("../etc/cli.yml");
    let matches = App::from_yaml(yaml).get_matches();

    parse_global_cfg(&matches, &mut config.base);

    if let Some(matches) = matches.subcommand_matches("test") {
        if matches.is_present("verbose") {
            println!("Printing verbosely...");
        } else {
            println!("Printing normally...");
        }
    }
}

fn parse_global_cfg(matches : &ArgMatches<>, config : &mut ConfigBase) {
    config.verbosity = matches.is_present("verbose");
    config.debugging = matches.is_present("debugging");
}

<|endoftext|>


<commit_before>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

use std::option::Option;

use uuid::Uuid;

use kvproto::metapb;
use kvproto::eraftpb::{self, ConfChangeType, MessageType};
use kvproto::raft_cmdpb::RaftCmdRequest;
use kvproto::raft_serverpb::RaftMessage;
use raftstore::{Result, Error};

use super::peer_storage;

pub fn find_peer(region: &metapb::Region, store_id: u64) -> Option<&metapb::Peer> {
    for peer in region.get_peers() {
        if peer.get_store_id() == store_id {
            return Some(peer);
        }
    }

    None
}

pub fn remove_peer(region: &mut metapb::Region, store_id: u64) -> Option<metapb::Peer> {
    region.get_peers()
        .iter()
        .position(|x| x.get_store_id() == store_id)
        .map(|i| region.mut_peers().remove(i))
}

// a helper function to create peer easily.
pub fn new_peer(store_id: u64, peer_id: u64) -> metapb::Peer {
    let mut peer = metapb::Peer::new();
    peer.set_store_id(store_id);
    peer.set_id(peer_id);
    peer
}

pub fn get_uuid_from_req(cmd: &RaftCmdRequest) -> Option<Uuid> {
    Uuid::from_bytes(cmd.get_header().get_uuid()).ok()
}

/// Check if key in region range [`start_key`, `end_key`].
pub fn check_key_in_region_inclusive(key: &[u8], region: &metapb::Region) -> Result<()> {
    let end_key = region.get_end_key();
    let start_key = region.get_start_key();
    if key >= start_key && (end_key.is_empty() || key <= end_key) {
        Ok(())
    } else {
        Err(Error::KeyNotInRegion(key.to_vec(), region.clone()))
    }
}

/// Check if key in region range [`start_key`, `end_key`).
pub fn check_key_in_region(key: &[u8], region: &metapb::Region) -> Result<()> {
    let end_key = region.get_end_key();
    let start_key = region.get_start_key();
    if key >= start_key && (end_key.is_empty() || key < end_key) {
        Ok(())
    } else {
        Err(Error::KeyNotInRegion(key.to_vec(), region.clone()))
    }
}

#[inline]
pub fn is_first_vote_msg(msg: &RaftMessage) -> bool {
    msg.get_message().get_msg_type() == MessageType::MsgRequestVote &&
    msg.get_message().get_term() == peer_storage::RAFT_INIT_LOG_TERM + 1
}

const STR_CONF_CHANGE_ADD_NODE: &'static str = "AddNode";
const STR_CONF_CHANGE_REMOVE_NODE: &'static str = "RemoveNode";

pub fn conf_change_type_str(conf_type: &eraftpb::ConfChangeType) -> &'static str {
    match *conf_type {
        ConfChangeType::AddNode => STR_CONF_CHANGE_ADD_NODE,
        ConfChangeType::RemoveNode => STR_CONF_CHANGE_REMOVE_NODE,
    }
}

// check whether epoch is staler than check_epoch.
pub fn is_epoch_stale(epoch: &metapb::RegionEpoch, check_epoch: &metapb::RegionEpoch) -> bool {
    epoch.get_version() < check_epoch.get_version() ||
    epoch.get_conf_ver() < check_epoch.get_conf_ver()
}

#[cfg(test)]
mod tests {
    use kvproto::metapb;

    use super::*;

    // Tests the util function `check_key_in_region`.
    #[test]
    fn test_check_key_in_region() {
        let test_cases = vec![("", "", "", true, true),
                              ("", "", "6", true, true),
                              ("", "3", "6", false, false),
                              ("4", "3", "6", true, true),
                              ("4", "3", "", true, true),
                              ("2", "3", "6", false, false),
                              ("", "3", "6", false, false),
                              ("", "3", "", false, false),
                              ("6", "3", "6", false, true)];
        for (key, start_key, end_key, is_in_region, is_in_region_inclusive) in test_cases {
            let mut region = metapb::Region::new();
            region.set_start_key(start_key.as_bytes().to_vec());
            region.set_end_key(end_key.as_bytes().to_vec());
            let mut result = check_key_in_region(key.as_bytes(), &region);
            assert_eq!(result.is_ok(), is_in_region);
            result = check_key_in_region_inclusive(key.as_bytes(), &region);
            assert_eq!(result.is_ok(), is_in_region_inclusive)
        }
    }

    #[test]
    fn test_peer() {
        let mut region = metapb::Region::new();
        region.set_id(1);
        region.mut_peers().push(new_peer(1, 1));

        assert!(find_peer(&region, 1).is_some());
        assert!(find_peer(&region, 10).is_none());

        assert!(remove_peer(&mut region, 1).is_some());
        assert!(remove_peer(&mut region, 1).is_none());
        assert!(find_peer(&region, 1).is_none());

    }
}
<commit_msg>raftstore: add util test (#1718)<commit_after>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

use std::option::Option;

use uuid::Uuid;

use kvproto::metapb;
use kvproto::eraftpb::{self, ConfChangeType, MessageType};
use kvproto::raft_cmdpb::RaftCmdRequest;
use kvproto::raft_serverpb::RaftMessage;
use raftstore::{Result, Error};

use super::peer_storage;

pub fn find_peer(region: &metapb::Region, store_id: u64) -> Option<&metapb::Peer> {
    for peer in region.get_peers() {
        if peer.get_store_id() == store_id {
            return Some(peer);
        }
    }

    None
}

pub fn remove_peer(region: &mut metapb::Region, store_id: u64) -> Option<metapb::Peer> {
    region.get_peers()
        .iter()
        .position(|x| x.get_store_id() == store_id)
        .map(|i| region.mut_peers().remove(i))
}

// a helper function to create peer easily.
pub fn new_peer(store_id: u64, peer_id: u64) -> metapb::Peer {
    let mut peer = metapb::Peer::new();
    peer.set_store_id(store_id);
    peer.set_id(peer_id);
    peer
}

pub fn get_uuid_from_req(cmd: &RaftCmdRequest) -> Option<Uuid> {
    Uuid::from_bytes(cmd.get_header().get_uuid()).ok()
}

/// Check if key in region range [`start_key`, `end_key`].
pub fn check_key_in_region_inclusive(key: &[u8], region: &metapb::Region) -> Result<()> {
    let end_key = region.get_end_key();
    let start_key = region.get_start_key();
    if key >= start_key && (end_key.is_empty() || key <= end_key) {
        Ok(())
    } else {
        Err(Error::KeyNotInRegion(key.to_vec(), region.clone()))
    }
}

/// Check if key in region range [`start_key`, `end_key`).
pub fn check_key_in_region(key: &[u8], region: &metapb::Region) -> Result<()> {
    let end_key = region.get_end_key();
    let start_key = region.get_start_key();
    if key >= start_key && (end_key.is_empty() || key < end_key) {
        Ok(())
    } else {
        Err(Error::KeyNotInRegion(key.to_vec(), region.clone()))
    }
}

#[inline]
pub fn is_first_vote_msg(msg: &RaftMessage) -> bool {
    msg.get_message().get_msg_type() == MessageType::MsgRequestVote &&
    msg.get_message().get_term() == peer_storage::RAFT_INIT_LOG_TERM + 1
}

const STR_CONF_CHANGE_ADD_NODE: &'static str = "AddNode";
const STR_CONF_CHANGE_REMOVE_NODE: &'static str = "RemoveNode";

pub fn conf_change_type_str(conf_type: &eraftpb::ConfChangeType) -> &'static str {
    match *conf_type {
        ConfChangeType::AddNode => STR_CONF_CHANGE_ADD_NODE,
        ConfChangeType::RemoveNode => STR_CONF_CHANGE_REMOVE_NODE,
    }
}

// check whether epoch is staler than check_epoch.
pub fn is_epoch_stale(epoch: &metapb::RegionEpoch, check_epoch: &metapb::RegionEpoch) -> bool {
    epoch.get_version() < check_epoch.get_version() ||
    epoch.get_conf_ver() < check_epoch.get_conf_ver()
}

#[cfg(test)]
mod tests {
    use kvproto::metapb;
    use kvproto::raft_serverpb::RaftMessage;
    use kvproto::eraftpb::{Message, ConfChangeType, MessageType};

    use super::*;
    use raftstore::store::peer_storage;

    // Tests the util function `check_key_in_region`.
    #[test]
    fn test_check_key_in_region() {
        let test_cases = vec![("", "", "", true, true),
                              ("", "", "6", true, true),
                              ("", "3", "6", false, false),
                              ("4", "3", "6", true, true),
                              ("4", "3", "", true, true),
                              ("2", "3", "6", false, false),
                              ("", "3", "6", false, false),
                              ("", "3", "", false, false),
                              ("6", "3", "6", false, true)];
        for (key, start_key, end_key, is_in_region, is_in_region_inclusive) in test_cases {
            let mut region = metapb::Region::new();
            region.set_start_key(start_key.as_bytes().to_vec());
            region.set_end_key(end_key.as_bytes().to_vec());
            let mut result = check_key_in_region(key.as_bytes(), &region);
            assert_eq!(result.is_ok(), is_in_region);
            result = check_key_in_region_inclusive(key.as_bytes(), &region);
            assert_eq!(result.is_ok(), is_in_region_inclusive)
        }
    }

    #[test]
    fn test_peer() {
        let mut region = metapb::Region::new();
        region.set_id(1);
        region.mut_peers().push(new_peer(1, 1));

        assert!(find_peer(&region, 1).is_some());
        assert!(find_peer(&region, 10).is_none());

        assert!(remove_peer(&mut region, 1).is_some());
        assert!(remove_peer(&mut region, 1).is_none());
        assert!(find_peer(&region, 1).is_none());

    }

    #[test]
    fn test_first_vote_msg() {
        let tbl = vec![(MessageType::MsgRequestVote, peer_storage::RAFT_INIT_LOG_TERM + 1, true),
                       (MessageType::MsgRequestVote, peer_storage::RAFT_INIT_LOG_TERM, false),
                       (MessageType::MsgHup, peer_storage::RAFT_INIT_LOG_TERM + 1, false)];

        for (msg_type, term, is_vote) in tbl {
            let mut msg = Message::new();
            msg.set_msg_type(msg_type);
            msg.set_term(term);

            let mut m = RaftMessage::new();
            m.set_message(msg);
            assert_eq!(is_first_vote_msg(&m), is_vote);
        }
    }

    #[test]
    fn test_conf_change_type_str() {
        assert_eq!(conf_change_type_str(&ConfChangeType::AddNode),
                   STR_CONF_CHANGE_ADD_NODE);
        assert_eq!(conf_change_type_str(&ConfChangeType::RemoveNode),
                   STR_CONF_CHANGE_REMOVE_NODE);
    }

    #[test]
    fn test_epoch_stale() {
        let mut epoch = metapb::RegionEpoch::new();
        epoch.set_version(10);
        epoch.set_conf_ver(10);

        let tbl = vec![(11, 10, true), (10, 11, true), (10, 10, false), (10, 9, false)];

        for (version, conf_version, is_stale) in tbl {
            let mut check_epoch = metapb::RegionEpoch::new();
            check_epoch.set_version(version);
            check_epoch.set_conf_ver(conf_version);
            assert_eq!(is_epoch_stale(&epoch, &check_epoch), is_stale);
        }
    }
}
<|endoftext|>


<commit_before>use glib::object::Cast;
use glib::translate::ToGlibPtr;
use gtk::{self, BoxExt, ButtonSignals, ContainerExt, DialogExt, ScrolledWindowExt};
use gtk::{WidgetExt, WindowExt};
use gtk_sys;
use pango_sys::PangoWrapMode;
use sysinfo;

pub fn create_process_dialog(process: &sysinfo::Process, window: &gtk::Window,
                             start_time: u64, running_since: u64) {
    let flags = gtk_sys::GTK_DIALOG_DESTROY_WITH_PARENT |
                gtk_sys::GTK_DIALOG_USE_HEADER_BAR;
    let scroll = gtk::ScrolledWindow::new(None, None);
    let close_button = gtk::Button::new_with_label("Close");
    let vertical_layout = gtk::Box::new(gtk::Orientation::Vertical, 0);
    scroll.set_policy(gtk::PolicyType::Automatic, gtk::PolicyType::Automatic);
    let popup = gtk::Dialog::new_with_buttons(Some(&format!("Information about {}", process.name)),
                                              Some(window),
                                              flags,
                                              &[]);
    let area = popup.get_content_area();
    let running_since = if start_time > process.start_time {
        start_time - process.start_time + running_since
    } else {
        start_time + running_since - process.start_time
    };
    let mut text = format!("name: {}\n\
                            pid: {}\n\
                            command: {}\n\
                            executable path: {}\n\
                            current working directory: {}\n\
                            root directory: {}\n\
                            memory usage: {} kB\n\
                            cpu usage: {}%\n\n\
                            Running since {} seconds\n\n\
                            environment:",
                            process.name,
                            process.pid,
                            process.cmd,
                            process.exe,
                            process.cwd,
                            process.root,
                            process.memory,
                            process.cpu_usage,
                            running_since);
    for env in process.environ.iter() {
        text.push_str(&format!("\n{:?}", env));
    }
    let label = gtk::Label::new(Some(&text));
    label.set_selectable(true);
    label.set_line_wrap(true);
    //label.set_line_wrap_mode(gtk::WrapMode::Char);
    unsafe { gtk_sys::gtk_label_set_line_wrap_mode(label.to_glib_none().0, PangoWrapMode::Char) };
    scroll.add(&label);
    vertical_layout.pack_start(&scroll, true, true, 0);
    vertical_layout.pack_start(&close_button, false, true, 0);
    vertical_layout.set_spacing(10);
    area.pack_start(&vertical_layout, true, true, 0);
    popup.set_size_request(500, 700);
    let popup = popup.upcast::<gtk::Window>();
    popup.set_resizable(false);
    popup.show_all();
    close_button.connect_clicked(move |_| {
        popup.destroy();
    });
}
<commit_msg>Improve time display<commit_after>use glib::object::Cast;
use glib::translate::ToGlibPtr;
use gtk::{self, BoxExt, ButtonSignals, ContainerExt, DialogExt, ScrolledWindowExt};
use gtk::{WidgetExt, WindowExt};
use gtk_sys;
use pango_sys::PangoWrapMode;
use sysinfo;

fn fomat_time(t: u64) -> String {
    format!("{}{}{}{}s",
            {
                let days = t / 86400;
                if days > 0 {
                    format!("{}d ", days)
                } else {
                    "".to_owned()
                }
            },
            {
                let hours = t / 3600 % 60;
                if hours > 0 {
                    format!("{}h ", hours)
                } else {
                    "".to_owned()
                }
            },
            {
                let minutes = t / 60 % 60;
                if minutes > 0 {
                    format!("{}m ", minutes)
                } else {
                    "".to_owned()
                }
            },
            t % 60)
}

pub fn create_process_dialog(process: &sysinfo::Process, window: &gtk::Window,
                             start_time: u64, running_since: u64) {
    let flags = gtk_sys::GTK_DIALOG_DESTROY_WITH_PARENT |
                gtk_sys::GTK_DIALOG_USE_HEADER_BAR;
    let scroll = gtk::ScrolledWindow::new(None, None);
    let close_button = gtk::Button::new_with_label("Close");
    let vertical_layout = gtk::Box::new(gtk::Orientation::Vertical, 0);
    scroll.set_policy(gtk::PolicyType::Automatic, gtk::PolicyType::Automatic);
    let popup = gtk::Dialog::new_with_buttons(Some(&format!("Information about {}", process.name)),
                                              Some(window),
                                              flags,
                                              &[]);
    let area = popup.get_content_area();
    let running_since = if start_time > process.start_time {
        start_time - process.start_time + running_since
    } else {
        start_time + running_since - process.start_time
    };
    let mut text = format!("name: {}\n\
                            pid: {}\n\
                            command: {}\n\
                            executable path: {}\n\
                            current working directory: {}\n\
                            root directory: {}\n\
                            memory usage: {} kB\n\
                            cpu usage: {}%\n\n\
                            Running since {}\n\n\
                            environment:",
                            process.name,
                            process.pid,
                            process.cmd,
                            process.exe,
                            process.cwd,
                            process.root,
                            process.memory,
                            process.cpu_usage,
                            fomat_time(running_since));
    for env in process.environ.iter() {
        text.push_str(&format!("\n{:?}", env));
    }
    let label = gtk::Label::new(Some(&text));
    label.set_selectable(true);
    label.set_line_wrap(true);
    //label.set_line_wrap_mode(gtk::WrapMode::Char);
    unsafe { gtk_sys::gtk_label_set_line_wrap_mode(label.to_glib_none().0, PangoWrapMode::Char) };
    scroll.add(&label);
    vertical_layout.pack_start(&scroll, true, true, 0);
    vertical_layout.pack_start(&close_button, false, true, 0);
    vertical_layout.set_spacing(10);
    area.pack_start(&vertical_layout, true, true, 0);
    popup.set_size_request(500, 700);
    let popup = popup.upcast::<gtk::Window>();
    popup.set_resizable(false);
    popup.show_all();
    close_button.connect_clicked(move |_| {
        popup.destroy();
    });
}
<|endoftext|>