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

use num::One;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

use num::One;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


<commit_before>extern crate nalgebra as na;
extern crate ncollide3d;
extern crate nphysics3d;
extern crate nphysics_testbed3d;

use na::{Point3, Vector3};
use ncollide3d::shape::{Ball, Cuboid, ShapeHandle};
use nphysics3d::object::{ColliderDesc, RigidBodyDesc, BodyStatus};
use nphysics3d::world::World;
use nphysics3d::math::Velocity;
use nphysics_testbed3d::Testbed;

fn main() {
    /*
     * World
     */
    let mut world = World::new();
    world.set_gravity(Vector3::new(0.0, -9.81, 0.0));

    /*
     * Ground.
     */
    let ground_size = 50.0;
    let ground_shape =
        ShapeHandle::new(Cuboid::new(Vector3::repeat(ground_size)));

    let co = ColliderDesc::new(ground_shape);
    RigidBodyDesc::new()
        .with_translation(Vector3::y() * -ground_size)
        .with_collider(&co)
        .with_surface_velocity(Velocity::linear(0.0, 0.0, 1.0))
        .with_status(BodyStatus::Kinematic)
        .build(&mut world);

    /*
     * Create the boxes
     */
    let num = 8;
    let rad = 0.1;

    let ball = ShapeHandle::new(Cuboid::new(Vector3::repeat(rad)));
    let collider_desc = ColliderDesc::new(ball)
        .with_density(1.0);

    let mut rb_desc = RigidBodyDesc::new()
        .with_collider(&collider_desc);

    let shift = (rad + collider_desc.margin()) * 2.0 + 0.002;
    let centerx = shift * (num as f32) / 2.0;
    let centery = shift / 2.0;
    let centerz = shift * (num as f32) / 2.0;
    let height = 3.0;

    for i in 0usize..num {
        for j in 0usize..num {
            for k in 0usize..num {
                let x = i as f32 * shift - centerx;
                let y = j as f32 * shift + centery + height;
                let z = k as f32 * shift - centerz;

                // Build the rigid body and its collider.
                rb_desc
                    .set_translation(Vector3::new(x, y, z))
                    .build(&mut world);
            }
        }
    }

    /*
     * Set up the testbed.
     */
    let mut testbed = Testbed::new(world);
    testbed.look_at(Point3::new(-4.0, 1.0, -4.0), Point3::new(0.0, 1.0, 0.0));
    testbed.run();
}
<commit_msg>Add conveyor belt 3D demo.<commit_after>extern crate nalgebra as na;
extern crate ncollide3d;
extern crate nphysics3d;
extern crate nphysics_testbed3d;

use std::f32;
use na::{Isometry3, Point3, Vector3};
use ncollide3d::shape::{Cuboid, ShapeHandle};
use nphysics3d::object::{ColliderDesc, RigidBodyDesc, BodyStatus, BasicMaterial, MaterialHandle};
use nphysics3d::world::World;
use nphysics_testbed3d::Testbed;

fn main() {
    /*
     * World
     */
    let mut world = World::new();
    world.set_gravity(Vector3::new(0.0, -9.81, 0.0));

    /*
     * Conveyor belts. We create 8 belts to form a "circle".
     */
    let conveyor_length = 5.0;
    let conveyor_half_width = 1.0;
    let conveyor_lane_shape =
        ShapeHandle::new(Cuboid::new(Vector3::new(conveyor_length - conveyor_half_width, 0.2, conveyor_half_width)));
    let conveyor_corner_shape =
        ShapeHandle::new(Cuboid::new(Vector3::new(conveyor_half_width, 0.2, conveyor_half_width)));
    let conveyor_shift = conveyor_length;

    let materials =
        [
            BasicMaterial { surface_velocity: Vector3::new(-1.0, 0.0, 0.0), ..BasicMaterial::default() },
            BasicMaterial { surface_velocity: Vector3::new( 1.0, 0.0, 0.0), ..BasicMaterial::default() },
            BasicMaterial { surface_velocity: Vector3::new( 0.0, 0.0, -1.0), ..BasicMaterial::default() },
            BasicMaterial { surface_velocity: Vector3::new( 0.0, 0.0, 1.0), ..BasicMaterial::default() },
            BasicMaterial { surface_velocity: Vector3::new( 1.0, 0.0, -2.0), ..BasicMaterial::default() },
            BasicMaterial { surface_velocity: Vector3::new(-2.0, 0.0, -1.0), ..BasicMaterial::default() },
            BasicMaterial { surface_velocity: Vector3::new(-1.0, 0.0, 2.0), ..BasicMaterial::default() },
            BasicMaterial { surface_velocity: Vector3::new( 2.0, 0.0, 1.0), ..BasicMaterial::default() },
        ];

        ColliderDesc::new(conveyor_lane_shape.clone())
            .with_material(MaterialHandle::new(materials[0]))
            .with_translation(Vector3::new(0.0, -1.0, -conveyor_shift))
            .build(&mut world);

        ColliderDesc::new(conveyor_lane_shape.clone())
            .with_material(MaterialHandle::new(materials[1]))
            .with_translation(Vector3::new(0.0, -1.0, conveyor_shift))
            .build(&mut world);

        ColliderDesc::new(conveyor_lane_shape.clone())
            .with_material(MaterialHandle::new(materials[2]))
            .with_translation(Vector3::new(conveyor_shift, -1.0, 0.0))
            .with_rotation(Vector3::y() * f32::consts::FRAC_PI_2)
            .build(&mut world);

        ColliderDesc::new(conveyor_lane_shape.clone())
            .with_material(MaterialHandle::new(materials[3]))
            .with_translation(Vector3::new(-conveyor_shift, -1.0, 0.0))
            .with_rotation(Vector3::y() * f32::consts::FRAC_PI_2)
            .build(&mut world);

        ColliderDesc::new(conveyor_corner_shape.clone())
            .with_material(MaterialHandle::new(materials[4]))
            .with_translation(Vector3::new(conveyor_shift, -1.0, conveyor_shift))
            .build(&mut world);

        ColliderDesc::new(conveyor_corner_shape.clone())
            .with_material(MaterialHandle::new(materials[5]))
            .with_translation(Vector3::new(conveyor_shift, -1.0, -conveyor_shift))
            .build(&mut world);

        ColliderDesc::new(conveyor_corner_shape.clone())
            .with_material(MaterialHandle::new(materials[6]))
            .with_translation(Vector3::new(-conveyor_shift, -1.0, -conveyor_shift))
            .build(&mut world);

        ColliderDesc::new(conveyor_corner_shape.clone())
            .with_material(MaterialHandle::new(materials[7]))
            .with_translation(Vector3::new(-conveyor_shift, -1.0, conveyor_shift))
            .build(&mut world);

    /*
     * Create some boxes
     */
    let num = 4;
    let rad = 0.1;

    let ball = ShapeHandle::new(Cuboid::new(Vector3::repeat(rad)));
    let collider_desc = ColliderDesc::new(ball)
        .with_density(1.0);

    let mut rb_desc = RigidBodyDesc::new()
        .with_collider(&collider_desc);

    let shift = (rad + collider_desc.margin()) * 2.0 + 0.002;
    let centerx = shift * (num as f32) / 2.0 + conveyor_shift;
    let centery = shift / 2.0;
    let centerz = shift * (num as f32) / 2.0;
    let height = 3.0;

    for i in 0usize..num {
        for j in 0usize..num {
            for k in 0usize..num {
                let x = i as f32 * shift - centerx;
                let y = j as f32 * shift + centery + height;
                let z = k as f32 * shift - centerz;

                // Build the rigid body and its collider.
                rb_desc
                    .set_translation(Vector3::new(x, y, z))
                    .build(&mut world);
            }
        }
    }

    /*
     * Set up the testbed.
     */
    let mut testbed = Testbed::new(world);
    testbed.look_at(Point3::new(-4.0, 1.0, -4.0), Point3::new(0.0, 1.0, 0.0));
    testbed.run();
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate ndarray;

use std::f64;

use ndarray::{
    OwnedArray,
    Ix,
};

pub type V = OwnedArray<f64, Ix>;

pub struct OnlineStats {
    sum_of_weights : f64,
    mean : V,
    m2 : V,
    state : State
}

enum State {Nothing, Mean, Full}
impl OnlineStats {
    pub fn new(width: usize) -> OnlineStats {
        OnlineStats {
            sum_of_weights: 0.,
            mean: V::zeros(width),
            m2:   V::zeros(width),
            state: State::Nothing }
    }

    pub fn next_value(&mut self, data : &V, weight : f64) {
        let temp = weight + self.sum_of_weights;
        let delta = data - &self.mean;
        let r = &delta * (weight / temp);

        self.mean.iadd(&r);

        self.m2.iadd(&(self.sum_of_weights * (r * &delta)));
        self.sum_of_weights = temp;
        self.state = match self.state {
            State::Nothing => State::Mean,
            _ => State::Full
        };
    }

    pub fn mean_and_variance(&self) -> (V, V) {
        //let var = if self.n > 1 {self.M2 / self.sumOfWeights * self.n / (self.n - 1) } else {Float::inf};
        let nans = V::from_elem(self.mean.dim(), f64::NAN);
        match self.state {
            State::Nothing => (nans.clone(), nans),
            State::Mean => (self.mean.clone(), nans),
            State::Full => (self.mean.clone(), &self.m2 / self.sum_of_weights),
        }
    }
}

use ndarray::arr1;

#[test]
fn weighted_stats17(){
    let const_vec = arr1(&[1., 3., 4.]);
    let const_vec2 = arr1(&[1., 1.5, 1.]);
    let const_vec3 = arr1(&[0., 2., 4.]);
    let mut s = OnlineStats::new(3);
    let (m0, v0) = s.mean_and_variance();
    let nans = V::from_elem(const_vec.dim(), f64::NAN);
    assert!(m0[0].is_nan());
    assert!(v0[0].is_nan());
    s.next_value(&const_vec, 1.);
    let (m1, v1) = s.mean_and_variance();
    assert!(v1[0].is_nan());
    assert_eq!(m1, const_vec);
    s.next_value(&const_vec2, 2.);
    let (m2, _) = s.mean_and_variance();
    assert_eq!(m2, arr1(&[1., 2., 2.]));
    s.next_value(&const_vec3, 3.);
    let (m3, _) = s.mean_and_variance();
    assert_eq!(m3, arr1(&[0.5, 2., 3.]));
}
<commit_msg>Remove nans computation from common path.<commit_after>#[macro_use]
extern crate ndarray;

use std::f64;

use ndarray::{
    OwnedArray,
    Ix,
};

pub type V = OwnedArray<f64, Ix>;

pub struct OnlineStats {
    sum_of_weights : f64,
    mean : V,
    m2 : V,
    state : State
}

enum State {Nothing, Mean, Full}
impl OnlineStats {
    pub fn new(width: usize) -> OnlineStats {
        OnlineStats {
            sum_of_weights: 0.,
            mean: V::zeros(width),
            m2:   V::zeros(width),
            state: State::Nothing }
    }

    pub fn next_value(&mut self, data : &V, weight : f64) {
        let temp = weight + self.sum_of_weights;
        let delta = data - &self.mean;
        let r = &delta * (weight / temp);

        self.mean.iadd(&r);

        self.m2.iadd(&(self.sum_of_weights * (r * &delta)));
        self.sum_of_weights = temp;
        self.state = match self.state {
            State::Nothing => State::Mean,
            _ => State::Full
        };
    }

    fn nans(&self) -> V {V::from_elem(self.mean.dim(), f64::NAN)}

    pub fn mean_and_variance(&self) -> (V, V) {
        // With no data, there is no mean. With only one vector, there is no variance.
        match self.state {
            State::Nothing => (self.nans(), self.nans()),
            State::Mean => (self.mean.clone(), self.nans()),
            State::Full => (self.mean.clone(), &self.m2 / self.sum_of_weights),
        }
    }
}

use ndarray::arr1;

#[test]
fn weighted_stats17(){
    let const_vec = arr1(&[1., 3., 4.]);
    let const_vec2 = arr1(&[1., 1.5, 1.]);
    let const_vec3 = arr1(&[0., 2., 4.]);
    let mut s = OnlineStats::new(3);
    let (m0, v0) = s.mean_and_variance();
    let nans = V::from_elem(const_vec.dim(), f64::NAN);
    assert!(m0[0].is_nan());
    assert!(v0[0].is_nan());
    s.next_value(&const_vec, 1.);
    let (m1, v1) = s.mean_and_variance();
    assert!(v1[0].is_nan());
    assert_eq!(m1, const_vec);
    s.next_value(&const_vec2, 2.);
    let (m2, _) = s.mean_and_variance();
    assert_eq!(m2, arr1(&[1., 2., 2.]));
    s.next_value(&const_vec3, 3.);
    let (m3, _) = s.mean_and_variance();
    assert_eq!(m3, arr1(&[0.5, 2., 3.]));
}
<|endoftext|>


<commit_before>#![no_std]

#[macro_use]
pub extern crate typenum;

use core::marker::PhantomData;
use typenum::{Integer, Unsigned};

/**
A type constrained by the `Min` and `Max` parameters.

# Example

```rust
use ranged::typenum::{Z0, P30};
use ranged::Ranged;

let some_val: Ranged<i64, Z0, P30> = Ranged::new(10);
let some_other: Ranged<i64, Z0, P30> = Ranged::new(12);
let new_val = some_val + some_other;
// This will print: "10 + 12 = 22"
println!("{} + {} = {}", some_val, some_other, new_val);
// This will panic in debug mode, but work in release mode:
// let new_negative = some_val - some_other;
```
*/
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct Ranged<T, Min, Max> {
    val: T,
    _marker: PhantomData<(Min, Max)>,
}

pub trait RangedBuilder<Min, Max> where Self: Sized {
    fn new(val: Self) -> Ranged<Self, Min, Max>;
}

use core::fmt;
impl<T, Min, Max> fmt::Display for Ranged<T, Min, Max> where T: fmt::Display {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.val.fmt(f)
    }
}

macro_rules! impl_ranged_builder {
    ($trait:ident; $($t:ident, $fun:ident),*) => (
        $(
            #[cfg(debug_assertions)]
            impl<Min, Max> RangedBuilder<Min, Max> for $t where Min: $trait, Max: $trait {
                #[inline]
                fn new(val: $t) -> Ranged<$t, Min, Max> {
                    if val > Max::$fun() || val < Min::$fun() {
                        panic!("value is out of range");
                    }
                    Ranged { val: val, _marker: PhantomData }
                }
            }
        )*
    );
}

impl_ranged_builder!(Integer; i8, to_i8, i16, to_i16, i32, to_i32, i64, to_i64);
impl_ranged_builder!(Unsigned; u8, to_u8, u16, to_u16, u32, to_u32, u64, to_u64);

#[cfg(not(debug_assertions))]
impl<T, Min, Max> RangedBuilder<Min, Max> for T {
    #[inline]
    fn new(val: T) -> Ranged<T, Min, Max> {
        Ranged { val: val, _marker: PhantomData }
    }
}

impl<T, Min, Max> Ranged<T, Min, Max> where T: RangedBuilder<Min, Max> {
    #[inline]
    pub fn new(val: T) -> Ranged<T, Min, Max> {
        RangedBuilder::new(val)
    }
}

use core::ops::*;

macro_rules! impl_binary_op {
    ($($trait:ident $fun:ident $op:tt),*) => (
        $(
            impl<T, U, Min, Max> $trait<Ranged<U, Min, Max>> for Ranged<T, Min, Max>
                where T: $trait<U>, op!(T $op U): RangedBuilder<Min, Max>
            {
                type Output = Ranged<op!(T $op U), Min, Max>;
                #[inline]
                fn $fun(self, rhs: Ranged<U, Min, Max>) -> Self::Output {
                    Ranged::new(self.val $op rhs.val)
                }
            }
        )*
    );
}

impl_binary_op!(Add add +, Sub sub -, Mul mul *, Div div /, Rem rem %, BitAnd bitand &, BitOr bitor |, BitXor bitxor ^);
<commit_msg>run rustfmt<commit_after>#![no_std]

#[macro_use]
pub extern crate typenum;

use core::marker::PhantomData;
use typenum::{Integer, Unsigned};

/**
A type constrained by the `Min` and `Max` parameters.

# Example

```rust
use ranged::typenum::{Z0, P30};
use ranged::Ranged;

let some_val: Ranged<i64, Z0, P30> = Ranged::new(10);
let some_other: Ranged<i64, Z0, P30> = Ranged::new(12);
let new_val = some_val + some_other;
// This will print: "10 + 12 = 22"
println!("{} + {} = {}", some_val, some_other, new_val);
// This will panic in debug mode, but work in release mode:
// let new_negative = some_val - some_other;
```
*/
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct Ranged<T, Min, Max> {
    val: T,
    _marker: PhantomData<(Min, Max)>,
}

pub trait RangedBuilder<Min, Max>
    where Self: Sized
{
    fn new(val: Self) -> Ranged<Self, Min, Max>;
}

use core::fmt;
impl<T, Min, Max> fmt::Display for Ranged<T, Min, Max>
    where T: fmt::Display
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.val.fmt(f)
    }
}

macro_rules! impl_ranged_builder {
    ($trait:ident; $($t:ident, $fun:ident),*) => (
        $(
            #[cfg(debug_assertions)]
            impl<Min, Max> RangedBuilder<Min, Max> for $t where Min: $trait, Max: $trait {
                #[inline]
                fn new(val: $t) -> Ranged<$t, Min, Max> {
                    if val > Max::$fun() || val < Min::$fun() {
                        panic!("value is out of range");
                    }
                    Ranged { val: val, _marker: PhantomData }
                }
            }
        )*
    );
}

impl_ranged_builder!(Integer; i8, to_i8, i16, to_i16, i32, to_i32, i64, to_i64);
impl_ranged_builder!(Unsigned; u8, to_u8, u16, to_u16, u32, to_u32, u64, to_u64);

#[cfg(not(debug_assertions))]
impl<T, Min, Max> RangedBuilder<Min, Max> for T {
    #[inline]
    fn new(val: T) -> Ranged<T, Min, Max> {
        Ranged {
            val: val,
            _marker: PhantomData,
        }
    }
}

impl<T, Min, Max> Ranged<T, Min, Max>
    where T: RangedBuilder<Min, Max>
{
    #[inline]
    pub fn new(val: T) -> Ranged<T, Min, Max> {
        RangedBuilder::new(val)
    }
}

use core::ops::*;

macro_rules! impl_binary_op {
    ($($trait:ident $fun:ident $op:tt),*) => (
        $(
            impl<T, U, Min, Max> $trait<Ranged<U, Min, Max>> for Ranged<T, Min, Max>
                where T: $trait<U>, op!(T $op U): RangedBuilder<Min, Max>
            {
                type Output = Ranged<op!(T $op U), Min, Max>;
                #[inline]
                fn $fun(self, rhs: Ranged<U, Min, Max>) -> Self::Output {
                    Ranged::new(self.val $op rhs.val)
                }
            }
        )*
    );
}

impl_binary_op!(Add add +, Sub sub -, Mul mul *, Div div /, Rem rem %,
                BitAnd bitand &, BitOr bitor |, BitXor bitxor ^);
<|endoftext|>


<commit_before>// Copyright 2013-2015, The Rust-GNOME Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

/*!

Bindings and wrappers for __GTK__

To implement __GTK+__ inheritance in rust, we implemented gtk superclasses as traits
located in `rgtk::self::traits::*`. The various widgets implement these traits and
live in `rgtk::gtk::widgets::*` and are rexported into `rgtk::gtk::*`.

GTK Inheritance in rgtk
======================

You probably know but __Gtk+__ uses its own GObject system: inherited class and interface.

To respect this design I follow a special design on __rgtk__:

* Interface -> Implement them on a trait with only default methods.
* Class -> Implement the construct on the class impl and other methods on a traits.
* Sub-class -> Implement all the methods on the class.

Exemple for GtkOrientable, GtkBox, GtkButtonBox:

GtkOrientable is an interface with all the methods implemented as default method of the trait self::traits::Orientable.

GtkBox is a class with constructors implemented on the struct `gtk::Box`, and the other method as default methods of the trait `self::traits::Box`. So `gtk::Box` implements `self::traits::Orientable` and `self::traits::Box`.

GtkButtonBox is a sub-class of GtkBox, the struct `gtk::ButtonBox` implements all the methods of GtkButtonBox and the traits `self::traits::Orientable` and `self::traits::Box`.

Finally all the gtk widgets implement the trait self::traits::Widget.
*/

//#![macro_use]

#![allow(dead_code)] // TODO: drop this
#![allow(raw_pointer_derive)]

extern crate libc;

extern crate glib_sys as glib_ffi;
extern crate gdk_sys as gdk_ffi;
extern crate gtk_sys as ffi;
extern crate cairo_sys as cairo_ffi;
extern crate pango_sys as pango_ffi;
extern crate glib;
extern crate gdk;
extern crate cairo;
extern crate pango;

pub use glib::ValuePublic;

// These are/should be inlined
pub use self::rt::{
    init,
    main,
    main_quit,
    main_level,
    main_iteration,
    main_iteration_do,
    get_major_version,
    get_minor_version,
    get_micro_version,
    get_binary_age,
    get_interface_age,
    check_version,
    events_pending
};

/// GTK Widgets for all versions
pub use self::widgets::{
    Widget,
    Window,
    Label,
    Button,
    Box,
    ButtonBox,
    Frame,
    AspectFrame,
    Fixed,
    Separator,
    FontButton,
    ToggleButton,
    CheckButton,
    ColorButton,
    LinkButton,
    Adjustment,
    ScaleButton,
    VolumeButton,
    Grid,
    EntryBuffer,
    Entry,
    Switch,
    Range,
    Scale,
    SpinButton,
    Spinner,
    Image,
    ProgressBar,
    Arrow,
    Calendar,
    Alignment,
    Expander,
    Paned,
    InfoBar,
    Toolbar,
    ToolItem,
    SeparatorToolItem,
    ToolButton,
    ToggleToolButton,
    MenuToolButton,
    Dialog,
    AboutDialog,
    ColorChooserDialog,
    FontChooserDialog,
    MessageDialog,
    NoteBook,
    Overlay,
    Layout,
    FileFilter,
    FileChooserDialog,
    AppInfo,
    AppLaunchContext,
    AppChooserDialog,
    DrawingArea,
    PageSetup,
    PaperSize,
    PrintSettings,
    RecentChooserDialog,
    //PageSetupUnixDialog
    RecentInfo,
    RecentFilter,
    RecentFilterInfo,
    RecentData,
    RecentManager,
    TextView,
    TextBuffer,
    TextTagTable,
    ScrolledWindow,
    RadioButton,
    TreeView,
    TreeViewColumn,
    TreePath,
    TreeIter,
    TreeModel,
    ListStore,
    TreeStore,
    MenuItem,
    SeparatorMenuItem,
    CheckMenuItem,
    ScrollBar,
    Viewport,
    StatusBar,
    CellRendererText,
    CellRendererToggle,
    LockButton,
    EntryCompletion,
    IconView,
    TreeSelection,
    RecentChooserWidget,
    ComboBox,
    //g_type,
    ComboBoxText,
    TextMark,
    TextTag,
    TextAttributes,
    TextIter,
    TextChildAnchor,
    ToolPalette,
    ToolItemGroup,
    SizeGroup,
    AppChooserWidget,
    FileChooserWidget,
    ColorChooserWidget,
    FontChooserWidget,
    EventBox
};

#[cfg(target_os = "linux")]
pub use self::widgets::{Socket};

#[cfg(feature = "gtk_3_6")]
/// GTK Widgets for versions since GTK 3.6
pub use self::widgets::{
    MenuButton,
    LevelBar,
};

#[cfg(feature = "gtk_3_10")]
/// GTK Widgets for versions since GTK 3.10
pub use self::widgets::{
    SearchEntry,
    SearchBar,
    Stack,
    StackSwitcher,
    Revealer,
    HeaderBar,
    ListBox,
    ListBoxRow,
    PlacesSidebar
};

#[cfg(feature = "gtk_3_12")]
/// GTK Widgets for versions since GTK 3.12
pub use self::widgets::{
    FlowBox,
    FlowBoxChild,
    ActionBar,
    Popover
};

/// GTK Enum types
pub use ffi::enums::WindowType;
pub use ffi::enums::TextDirection;
pub use ffi::enums::WindowPosition;
pub use ffi::enums::ButtonBoxStyle;
pub use ffi::enums::Orientation;
pub use ffi::enums::DirectionType;
pub use ffi::enums::CornerType;
pub use ffi::enums::ResizeMode;
pub use ffi::enums::BorderStyle;
pub use ffi::enums::SortType;
pub use ffi::enums::StateFlags;
pub use ffi::enums::DragResult;
pub use ffi::enums::AccelFlags;
pub use ffi::enums::ArrowPlacement;
pub use ffi::enums::ArrowType;
pub use ffi::enums::AttachOptions;
pub use ffi::enums::DeleteType;
pub use ffi::enums::ExpanderStyle;
pub use ffi::enums::IMPreeditStyle;
pub use ffi::enums::IMStatusStyle;
pub use ffi::enums::Justification;
pub use ffi::enums::MovementStep;
pub use ffi::enums::PackType;
pub use ffi::enums::PathPriorityType;
pub use ffi::enums::PathType;
pub use ffi::enums::PolicyType;
pub use ffi::enums::PositionType;
pub use ffi::enums::ReliefStyle;
pub use ffi::enums::ScrollStep;
pub use ffi::enums::ScrollType;
pub use ffi::enums::SelectionMode;
pub use ffi::enums::ShadowType;
pub use ffi::enums::StateType;
pub use ffi::enums::ToolbarStyle;
pub use ffi::enums::JunctionSides;
pub use ffi::enums::RegionFlags;
pub use ffi::enums::IconSize;
pub use ffi::enums::EntryIconPosition;
pub use ffi::enums::InputHints;
pub use ffi::enums::InputPurpose;
pub use ffi::enums::ImageType;
pub use ffi::enums::SpinType;
pub use ffi::enums::SpinButtonUpdatePolicy;
pub use ffi::enums::LevelBarMode;
pub use ffi::enums::CalendarDisplayOptions;
pub use ffi::enums::MessageType;
pub use ffi::enums::License;
pub use ffi::enums::ResponseType;
pub use ffi::enums::DialogFlags;
pub use ffi::enums::FileChooserAction;
pub use ffi::enums::ButtonsType;
pub use ffi::enums::StackTransitionType;
pub use ffi::enums::RevealerTransitionType;
pub use ffi::enums::ScrollablePolicy;
pub use ffi::enums::FileFilterFlags;
pub use ffi::enums::AppInfoCreateFlags;
pub use ffi::enums::SizeRequestMode;
pub use ffi::enums::Align;
pub use ffi::enums::BuilderError;
pub use ffi::enums::PageOrientation;
pub use ffi::enums::Unit;
pub use ffi::enums::NumberUpLayout;
pub use ffi::enums::PrintPages;
pub use ffi::enums::PageSet;
pub use ffi::enums::RecentSortType;
pub use ffi::enums::RecentFilterFlags;
pub use ffi::enums::WidgetHelpType;
pub use ffi::enums::TextWindowType;
pub use ffi::enums::WrapMode;
pub use ffi::enums::TreeViewGridLines;
pub use ffi::enums::TreeViewColumnSizing;
pub use ffi::enums::CellRendererState;
pub use ffi::enums::TreeModelFlags;
pub use ffi::enums::IconViewDropPosition;
pub use ffi::enums::SensitivityType;
pub use ffi::enums::GType;
pub use ffi::enums::TextSearchFlags;
pub use ffi::enums::PlacesOpenFlags;
pub use ffi::enums::ToolPaletteDragTargets;
pub use ffi::enums::DestDefaults;
pub use ffi::enums::SizeGroupMode;

/// Gtk Traits
pub use self::traits::FFIWidget;
pub use self::traits::GObjectTrait;
pub use self::traits::BoxTrait;
pub use self::traits::ActionableTrait;
pub use self::traits::AppChooserTrait;
pub use self::traits::BinTrait;
pub use self::traits::ButtonTrait;
pub use self::traits::ButtonSignals;
pub use self::traits::CellEditableTrait;
pub use self::traits::CellLayoutTrait;
pub use self::traits::CellRendererTrait;
pub use self::traits::CheckMenuItemTrait;
pub use self::traits::ColorChooserTrait;
pub use self::traits::ComboBoxTrait;
pub use self::traits::ContainerTrait;
pub use self::traits::DialogButtons;
pub use self::traits::DialogTrait;
pub use self::traits::EditableTrait;
pub use self::traits::EntryTrait;
pub use self::traits::FileChooserTrait;
pub use self::traits::FontChooserTrait;
pub use self::traits::FrameTrait;
pub use self::traits::LabelTrait;
pub use self::traits::MenuItemTrait;
pub use self::traits::MenuShellTrait;
pub use self::traits::MiscTrait;
pub use self::traits::OrientableTrait;
pub use self::traits::RangeTrait;
pub use self::traits::RecentChooserTrait;
pub use self::traits::ScaleButtonTrait;
pub use self::traits::ScrollableTrait;
pub use self::traits::ScrolledWindowTrait;
pub use self::traits::TextBufferTrait;
pub use self::traits::ToggleButtonTrait;
pub use self::traits::ToggleToolButtonTrait;
pub use self::traits::ToolButtonTrait;
pub use self::traits::ToolButtonSignals;
pub use self::traits::ToolItemTrait;
pub use self::traits::ToolShellTrait;
pub use self::traits::WidgetTrait;
pub use self::traits::WidgetSignals;
pub use self::traits::WindowTrait;

/// GTK various struct
pub use self::types::{
    Tooltip,
};

mod macros;
mod cast;
mod rt;

pub mod traits;
pub mod signal;
pub mod widgets;
pub mod types;
<commit_msg>Remove allow(dead_code) and allow(raw_pointer_derive)<commit_after>// Copyright 2013-2015, The Rust-GNOME Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

/*!

Bindings and wrappers for __GTK__

To implement __GTK+__ inheritance in rust, we implemented gtk superclasses as traits
located in `rgtk::self::traits::*`. The various widgets implement these traits and
live in `rgtk::gtk::widgets::*` and are rexported into `rgtk::gtk::*`.

GTK Inheritance in rgtk
======================

You probably know but __Gtk+__ uses its own GObject system: inherited class and interface.

To respect this design I follow a special design on __rgtk__:

* Interface -> Implement them on a trait with only default methods.
* Class -> Implement the construct on the class impl and other methods on a traits.
* Sub-class -> Implement all the methods on the class.

Exemple for GtkOrientable, GtkBox, GtkButtonBox:

GtkOrientable is an interface with all the methods implemented as default method of the trait self::traits::Orientable.

GtkBox is a class with constructors implemented on the struct `gtk::Box`, and the other method as default methods of the trait `self::traits::Box`. So `gtk::Box` implements `self::traits::Orientable` and `self::traits::Box`.

GtkButtonBox is a sub-class of GtkBox, the struct `gtk::ButtonBox` implements all the methods of GtkButtonBox and the traits `self::traits::Orientable` and `self::traits::Box`.

Finally all the gtk widgets implement the trait self::traits::Widget.
*/

//#![macro_use]

extern crate libc;

extern crate glib_sys as glib_ffi;
extern crate gdk_sys as gdk_ffi;
extern crate gtk_sys as ffi;
extern crate cairo_sys as cairo_ffi;
extern crate pango_sys as pango_ffi;
extern crate glib;
extern crate gdk;
extern crate cairo;
extern crate pango;

pub use glib::ValuePublic;

// These are/should be inlined
pub use self::rt::{
    init,
    main,
    main_quit,
    main_level,
    main_iteration,
    main_iteration_do,
    get_major_version,
    get_minor_version,
    get_micro_version,
    get_binary_age,
    get_interface_age,
    check_version,
    events_pending
};

/// GTK Widgets for all versions
pub use self::widgets::{
    Widget,
    Window,
    Label,
    Button,
    Box,
    ButtonBox,
    Frame,
    AspectFrame,
    Fixed,
    Separator,
    FontButton,
    ToggleButton,
    CheckButton,
    ColorButton,
    LinkButton,
    Adjustment,
    ScaleButton,
    VolumeButton,
    Grid,
    EntryBuffer,
    Entry,
    Switch,
    Range,
    Scale,
    SpinButton,
    Spinner,
    Image,
    ProgressBar,
    Arrow,
    Calendar,
    Alignment,
    Expander,
    Paned,
    InfoBar,
    Toolbar,
    ToolItem,
    SeparatorToolItem,
    ToolButton,
    ToggleToolButton,
    MenuToolButton,
    Dialog,
    AboutDialog,
    ColorChooserDialog,
    FontChooserDialog,
    MessageDialog,
    NoteBook,
    Overlay,
    Layout,
    FileFilter,
    FileChooserDialog,
    AppInfo,
    AppLaunchContext,
    AppChooserDialog,
    DrawingArea,
    PageSetup,
    PaperSize,
    PrintSettings,
    RecentChooserDialog,
    //PageSetupUnixDialog
    RecentInfo,
    RecentFilter,
    RecentFilterInfo,
    RecentData,
    RecentManager,
    TextView,
    TextBuffer,
    TextTagTable,
    ScrolledWindow,
    RadioButton,
    TreeView,
    TreeViewColumn,
    TreePath,
    TreeIter,
    TreeModel,
    ListStore,
    TreeStore,
    MenuItem,
    SeparatorMenuItem,
    CheckMenuItem,
    ScrollBar,
    Viewport,
    StatusBar,
    CellRendererText,
    CellRendererToggle,
    LockButton,
    EntryCompletion,
    IconView,
    TreeSelection,
    RecentChooserWidget,
    ComboBox,
    //g_type,
    ComboBoxText,
    TextMark,
    TextTag,
    TextAttributes,
    TextIter,
    TextChildAnchor,
    ToolPalette,
    ToolItemGroup,
    SizeGroup,
    AppChooserWidget,
    FileChooserWidget,
    ColorChooserWidget,
    FontChooserWidget,
    EventBox
};

#[cfg(target_os = "linux")]
pub use self::widgets::{Socket};

#[cfg(feature = "gtk_3_6")]
/// GTK Widgets for versions since GTK 3.6
pub use self::widgets::{
    MenuButton,
    LevelBar,
};

#[cfg(feature = "gtk_3_10")]
/// GTK Widgets for versions since GTK 3.10
pub use self::widgets::{
    SearchEntry,
    SearchBar,
    Stack,
    StackSwitcher,
    Revealer,
    HeaderBar,
    ListBox,
    ListBoxRow,
    PlacesSidebar
};

#[cfg(feature = "gtk_3_12")]
/// GTK Widgets for versions since GTK 3.12
pub use self::widgets::{
    FlowBox,
    FlowBoxChild,
    ActionBar,
    Popover
};

/// GTK Enum types
pub use ffi::enums::WindowType;
pub use ffi::enums::TextDirection;
pub use ffi::enums::WindowPosition;
pub use ffi::enums::ButtonBoxStyle;
pub use ffi::enums::Orientation;
pub use ffi::enums::DirectionType;
pub use ffi::enums::CornerType;
pub use ffi::enums::ResizeMode;
pub use ffi::enums::BorderStyle;
pub use ffi::enums::SortType;
pub use ffi::enums::StateFlags;
pub use ffi::enums::DragResult;
pub use ffi::enums::AccelFlags;
pub use ffi::enums::ArrowPlacement;
pub use ffi::enums::ArrowType;
pub use ffi::enums::AttachOptions;
pub use ffi::enums::DeleteType;
pub use ffi::enums::ExpanderStyle;
pub use ffi::enums::IMPreeditStyle;
pub use ffi::enums::IMStatusStyle;
pub use ffi::enums::Justification;
pub use ffi::enums::MovementStep;
pub use ffi::enums::PackType;
pub use ffi::enums::PathPriorityType;
pub use ffi::enums::PathType;
pub use ffi::enums::PolicyType;
pub use ffi::enums::PositionType;
pub use ffi::enums::ReliefStyle;
pub use ffi::enums::ScrollStep;
pub use ffi::enums::ScrollType;
pub use ffi::enums::SelectionMode;
pub use ffi::enums::ShadowType;
pub use ffi::enums::StateType;
pub use ffi::enums::ToolbarStyle;
pub use ffi::enums::JunctionSides;
pub use ffi::enums::RegionFlags;
pub use ffi::enums::IconSize;
pub use ffi::enums::EntryIconPosition;
pub use ffi::enums::InputHints;
pub use ffi::enums::InputPurpose;
pub use ffi::enums::ImageType;
pub use ffi::enums::SpinType;
pub use ffi::enums::SpinButtonUpdatePolicy;
pub use ffi::enums::LevelBarMode;
pub use ffi::enums::CalendarDisplayOptions;
pub use ffi::enums::MessageType;
pub use ffi::enums::License;
pub use ffi::enums::ResponseType;
pub use ffi::enums::DialogFlags;
pub use ffi::enums::FileChooserAction;
pub use ffi::enums::ButtonsType;
pub use ffi::enums::StackTransitionType;
pub use ffi::enums::RevealerTransitionType;
pub use ffi::enums::ScrollablePolicy;
pub use ffi::enums::FileFilterFlags;
pub use ffi::enums::AppInfoCreateFlags;
pub use ffi::enums::SizeRequestMode;
pub use ffi::enums::Align;
pub use ffi::enums::BuilderError;
pub use ffi::enums::PageOrientation;
pub use ffi::enums::Unit;
pub use ffi::enums::NumberUpLayout;
pub use ffi::enums::PrintPages;
pub use ffi::enums::PageSet;
pub use ffi::enums::RecentSortType;
pub use ffi::enums::RecentFilterFlags;
pub use ffi::enums::WidgetHelpType;
pub use ffi::enums::TextWindowType;
pub use ffi::enums::WrapMode;
pub use ffi::enums::TreeViewGridLines;
pub use ffi::enums::TreeViewColumnSizing;
pub use ffi::enums::CellRendererState;
pub use ffi::enums::TreeModelFlags;
pub use ffi::enums::IconViewDropPosition;
pub use ffi::enums::SensitivityType;
pub use ffi::enums::GType;
pub use ffi::enums::TextSearchFlags;
pub use ffi::enums::PlacesOpenFlags;
pub use ffi::enums::ToolPaletteDragTargets;
pub use ffi::enums::DestDefaults;
pub use ffi::enums::SizeGroupMode;

/// Gtk Traits
pub use self::traits::FFIWidget;
pub use self::traits::GObjectTrait;
pub use self::traits::BoxTrait;
pub use self::traits::ActionableTrait;
pub use self::traits::AppChooserTrait;
pub use self::traits::BinTrait;
pub use self::traits::ButtonTrait;
pub use self::traits::ButtonSignals;
pub use self::traits::CellEditableTrait;
pub use self::traits::CellLayoutTrait;
pub use self::traits::CellRendererTrait;
pub use self::traits::CheckMenuItemTrait;
pub use self::traits::ColorChooserTrait;
pub use self::traits::ComboBoxTrait;
pub use self::traits::ContainerTrait;
pub use self::traits::DialogButtons;
pub use self::traits::DialogTrait;
pub use self::traits::EditableTrait;
pub use self::traits::EntryTrait;
pub use self::traits::FileChooserTrait;
pub use self::traits::FontChooserTrait;
pub use self::traits::FrameTrait;
pub use self::traits::LabelTrait;
pub use self::traits::MenuItemTrait;
pub use self::traits::MenuShellTrait;
pub use self::traits::MiscTrait;
pub use self::traits::OrientableTrait;
pub use self::traits::RangeTrait;
pub use self::traits::RecentChooserTrait;
pub use self::traits::ScaleButtonTrait;
pub use self::traits::ScrollableTrait;
pub use self::traits::ScrolledWindowTrait;
pub use self::traits::TextBufferTrait;
pub use self::traits::ToggleButtonTrait;
pub use self::traits::ToggleToolButtonTrait;
pub use self::traits::ToolButtonTrait;
pub use self::traits::ToolButtonSignals;
pub use self::traits::ToolItemTrait;
pub use self::traits::ToolShellTrait;
pub use self::traits::WidgetTrait;
pub use self::traits::WidgetSignals;
pub use self::traits::WindowTrait;

/// GTK various struct
pub use self::types::{
    Tooltip,
};

mod macros;
mod cast;
mod rt;

pub mod traits;
pub mod signal;
pub mod widgets;
pub mod types;
<|endoftext|>


<commit_before>/*!
Simple persistent generic HashMap/Key-value store.

Basic usage:

```
extern crate kv_cab;

use kv_cab::{ KV, Value };

fn main() {
    let mut test_store = KV::<String, Value>::new("./db.cab").unwrap();

    let _ = test_store.insert("key".to_string(), Value::String("value".to_string()));
    println!("{:?}", test_store.get("key".to_string()));
    let _ = test_store.remove("key".to_string());
}
```

Usage with user defined Key and Value types:

```
extern crate kv_cab;
extern crate rustc_serialize;

use kv_cab::KV;

#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash)]
enum MyKey {
    String(String),
    Int(i32),
}

#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
enum MyValue {
    String(String),
    Int(i32),
}

fn main() {
    let mut test_store = KV::<MyKey, MyValue>::new("./db.cab").unwrap();

    let _ = test_store.insert(MyKey::Int(1i32), MyValue::String("value".to_string()));
    println!("{:?}", test_store.get(MyKey::Int(1i32)));
    let _ = test_store.remove(MyKey::Int(1i32));
}
```

*/

extern crate bincode;
extern crate rustc_serialize;
#[macro_use]
extern crate log;
extern crate fs2;

use std::collections::HashMap;
use std::fs::{ File, OpenOptions };
use std::io::prelude::*;
use std::io::SeekFrom;
use std::hash::Hash;

use bincode::SizeLimit;
use bincode::rustc_serialize::{ encode, decode };

use rustc_serialize::{ Encodable, Decodable };

use fs2::FileExt;

/// The maximum number of retries the cab will make
const MAX_RETRIES:i32 = 10;

/// Definition of a macro for retrying an operation
macro_rules! retry {
    ($i:ident, $b:block) => (
        for $i in 0..MAX_RETRIES {
            if $i != 0 {
                std::thread::park_timeout(std::time::Duration::new(0u64, 1000u32));
            }

            $b
        }
    )
}

/// Macro for what to do on last retry
macro_rules! last_retry {
    ($i:ident, $b:stmt) => (
        if $i >= MAX_RETRIES - 1 {
            $b;
        }
    )
}

/// A default value type to use with KV
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
pub enum Value {
    String(String),
    Int(i32),
    Float(f32),
    Map(HashMap<String, Value>),
}

/// Type alias for results from KV
type KVResult = Result<bool, KVError>;

/// Errors that KV might have
#[derive(Debug, PartialEq)]
pub enum KVError {
    /// Could not decode the cab from disk
    CouldntDecode,
    /// Couldn't encode the hashmap for writing to disk
    CouldntEncode,
    /// Could not write to the cab on disk
    CouldntWrite,
    /// Failed to read the cab from disk
    FailedToRead,
    /// Could not flush the data to disk
    CouldntFlush,
    /// Could not open the file from disk
    CouldntOpen,
    /// Could not load the file from disk
    CouldntLoad,
    /// Failed to write lock the cab
    CouldntWriteLock,
    /// Failed to read lock the cab
    CouldntReadLock,
    /// Failed to unlock the cab
    CouldntUnlock,
    /// Failed to set SeekFrom::Start
    CouldntSeekToStart,
}

/// The type that represents the key-value store
pub struct KV<K,V> {
    cab: HashMap<K, V>,
    file: File,
}

impl<K: Clone + Encodable + Decodable + Eq + Hash, V: Clone + Encodable + Decodable> KV<K,V> {
    /// Creates a new instance of the KV store
    pub fn new(p:&'static str) -> Result<KV<K,V>, KVError> {
        // create the KV instance
        let mut store = KV {
            cab: HashMap::new(),
            file: KV::<K, V>::retry_get_file(p).unwrap(),
        };

        match store.load_from_persist(false) {
            Ok(f) => trace!("{}", f),
            Err(e) => {
                return Err(e);
            },
        };

        Ok(store)
    }

    /// Retry to get a reference to the cab file at path p and create if doesn't exist
    fn retry_get_file(p:&'static str) -> Result<File, KVError> {
        retry!(i, {
            match OpenOptions::new().read(true).write(true).create(true).open(p) {
                Ok(f) => { return Ok(f); },
                Err(e) => {
                    error!("{}", e);
                    last_retry!(i, return Err(KVError::CouldntOpen));
                    continue;
                }
            };
        });

        Err(KVError::CouldntOpen)
    }

    /// Inserta a key, value pair into the key-value store
    pub fn insert(&mut self, key: K, value: V) -> KVResult {
        // check that can write to the cab
        if let Err(e) = self.file.lock_exclusive() {
            error!("{}", e);
            return Err(KVError::CouldntWriteLock);
        }
        // make sure mem version up to date
        if let Err(e) = self.load_from_persist(true) {
            return Err(e);
        }
        // insert into the HashMap
        self.cab.insert(key, value);
        // persist
        self.write_to_persist()
    }

    /// Get the value from a key
    pub fn get(&mut self, key: K) -> Result<Option<V>, KVError> {
        // make sure mem version up to date
        if let Err(e) = self.load_from_persist(false) {
            return Err(e);
        }
        // get the value from the cab
        match self.cab.get(&key) {
            Some(v) => Ok(Some((*v).clone())),
            None => Ok(None),
        }
    }

    /// Removes a key and associated value from the key-value Store
    pub fn remove(&mut self, key: K) -> KVResult {
        // check that can write to the cab
        if let Err(e) = self.file.lock_exclusive() {
            error!("{}", e);
            return Err(KVError::CouldntWriteLock);
        }
        // make sure mem version up to date
        if let Err(e) = self.load_from_persist(true) {
            return Err(e);
        }
        // remove from the HashMap
        self.cab.remove(&key);
        // persist
        self.write_to_persist()
    }

    /// get all the keys contained in the KV Store
    pub fn keys(&mut self) -> Result<Vec<K>, KVError> {
        // make sure mem version up to date
        if let Err(e) = self.load_from_persist(false) {
            return Err(e);
        }
        // create a vec from the cabs keys
        Ok(self.cab.keys().map(|k| k.clone()).collect())
    }

    /// Writes the key-value Store to file
    fn write_to_persist(&mut self) -> KVResult {
        // attempt to write to the cab
        retry!(i, {
            // check that can write to the cab
            if let Err(e) = self.file.lock_exclusive() {
                error!("{}", e);
                last_retry!(i, return Err(KVError::CouldntWriteLock));
                continue;
            }

            // encode the cab as a u8 vec
            let byte_vec: Vec<u8> = match encode(&mut self.cab, SizeLimit::Infinite) {
                Ok(bv) => bv,
                Err(e) => {
                    error!("encode: {}", e);
                    return Err(KVError::CouldntEncode);
                },
            };

            // seek to the start
            if let Err(e) = self.file.seek(SeekFrom::Start(0)) {
                error!("{}", e);
                last_retry!(i, return Err(KVError::CouldntSeekToStart));
                continue;
            }

            // write the bytes to it
            if let Err(e) = self.file.write_all(byte_vec.as_slice()) {
                error!("file.write_all/retry: {}", e);
                last_retry!(i, return Err(KVError::CouldntWrite));
                continue;
            }

            // flush to disk
            if let Err(e) = self.file.flush() {
                error!("{}", e);
                last_retry!(i, return Err(KVError::CouldntFlush));
                continue;
            }

            // unlock the file after write has completed
            if let Err(e) = self.file.unlock() {
                error!("{}", e);
                last_retry!(i, return Err(KVError::CouldntUnlock));
                continue;
            }
            return Ok(true);
        });

        Err(KVError::CouldntWrite)
    }

    /// Loads key-value store from file
    fn load_from_persist(&mut self, already_locked:bool) -> KVResult {
        retry!(i, {
            // byte vec to read into
            let mut byte_vec = Vec::new();

            // wait/lock the cab and read the bytes
            if !already_locked {
                if let Err(e) = self.file.lock_shared() {
                    error!("{}", e);
                    return Err(KVError::CouldntReadLock);
                }
            }

            // seek to the start
            if let Err(e) = self.file.seek(SeekFrom::Start(0)) {
                error!("{}", e);
                last_retry!(i, return Err(KVError::CouldntSeekToStart));
                continue;
            }

            // read the file into the buffer
            match self.file.read_to_end(&mut byte_vec) {
                Ok(count) => {
                    // don't attempt to decode as empty
                    if count == 0 {
                        if !already_locked {
                            if let Err(e) = self.file.unlock() {
                                error!("{}", e);
                                last_retry!(i, return Err(KVError::CouldntUnlock));
                            }
                        }
                        return Ok(true);
                    }
                },
                Err(e) => {
                    error!("{}", e);
                    return Err(KVError::FailedToRead);
                },
            }

            // decode u8 vec back into HashMap
            match decode(byte_vec.as_slice()) {
                Ok(f) => {
                    // assign read HashMap back to self
                    self.cab = f;
                    if !already_locked {
                        if let Err(e) = self.file.unlock() {
                            error!("{}", e);
                            last_retry!(i, return Err(KVError::CouldntUnlock));
                        }
                    }
                    return Ok(true);
                },
                Err(e) => {
                    error!("{}", e);
                    last_retry!(i, return Err(KVError::CouldntDecode));
                    continue;
                },
            };
        });

        Err(KVError::CouldntLoad)
    }
}
<commit_msg>Added error for missing docs and fixed remaining that were missing<commit_after>/*!
Simple persistent generic HashMap/Key-value store.

Basic usage:

```
extern crate kv_cab;

use kv_cab::{ KV, Value };

fn main() {
    let mut test_store = KV::<String, Value>::new("./db.cab").unwrap();

    let _ = test_store.insert("key".to_string(), Value::String("value".to_string()));
    println!("{:?}", test_store.get("key".to_string()));
    let _ = test_store.remove("key".to_string());
}
```

Usage with user defined Key and Value types:

```
extern crate kv_cab;
extern crate rustc_serialize;

use kv_cab::KV;

#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash)]
enum MyKey {
    String(String),
    Int(i32),
}

#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
enum MyValue {
    String(String),
    Int(i32),
}

fn main() {
    let mut test_store = KV::<MyKey, MyValue>::new("./db.cab").unwrap();

    let _ = test_store.insert(MyKey::Int(1i32), MyValue::String("value".to_string()));
    println!("{:?}", test_store.get(MyKey::Int(1i32)));
    let _ = test_store.remove(MyKey::Int(1i32));
}
```

*/

#![deny(missing_docs)]

extern crate bincode;
extern crate rustc_serialize;
#[macro_use]
extern crate log;
extern crate fs2;

use std::collections::HashMap;
use std::fs::{ File, OpenOptions };
use std::io::prelude::*;
use std::io::SeekFrom;
use std::hash::Hash;

use bincode::SizeLimit;
use bincode::rustc_serialize::{ encode, decode };

use rustc_serialize::{ Encodable, Decodable };

use fs2::FileExt;

/// The maximum number of retries the cab will make
const MAX_RETRIES:i32 = 10;

/// Definition of a macro for retrying an operation
macro_rules! retry {
    ($i:ident, $b:block) => (
        for $i in 0..MAX_RETRIES {
            if $i != 0 {
                std::thread::park_timeout(std::time::Duration::new(0u64, 1000u32));
            }

            $b
        }
    )
}

/// Macro for what to do on last retry
macro_rules! last_retry {
    ($i:ident, $b:stmt) => (
        if $i >= MAX_RETRIES - 1 {
            $b;
        }
    )
}

/// A default value type to use with KV
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
pub enum Value {
    /// Cab type for strings
    String(String),
    /// Cab type for intergers
    Int(i32),
    /// Cab type for floats
    Float(f32),
    /// Cab type for a sub map
    Map(HashMap<String, Value>),
}

/// Type alias for results from KV
type KVResult = Result<bool, KVError>;

/// Errors that KV might have
#[derive(Debug, PartialEq)]
pub enum KVError {
    /// Could not decode the cab from disk
    CouldntDecode,
    /// Couldn't encode the hashmap for writing to disk
    CouldntEncode,
    /// Could not write to the cab on disk
    CouldntWrite,
    /// Failed to read the cab from disk
    FailedToRead,
    /// Could not flush the data to disk
    CouldntFlush,
    /// Could not open the file from disk
    CouldntOpen,
    /// Could not load the file from disk
    CouldntLoad,
    /// Failed to write lock the cab
    CouldntWriteLock,
    /// Failed to read lock the cab
    CouldntReadLock,
    /// Failed to unlock the cab
    CouldntUnlock,
    /// Failed to set SeekFrom::Start
    CouldntSeekToStart,
}

/// The type that represents the key-value store
pub struct KV<K,V> {
    cab: HashMap<K, V>,
    file: File,
}

impl<K: Clone + Encodable + Decodable + Eq + Hash, V: Clone + Encodable + Decodable> KV<K,V> {
    /// Creates a new instance of the KV store
    pub fn new(p:&'static str) -> Result<KV<K,V>, KVError> {
        // create the KV instance
        let mut store = KV {
            cab: HashMap::new(),
            file: KV::<K, V>::retry_get_file(p).unwrap(),
        };

        match store.load_from_persist(false) {
            Ok(f) => trace!("{}", f),
            Err(e) => {
                return Err(e);
            },
        };

        Ok(store)
    }

    /// Retry to get a reference to the cab file at path p and create if doesn't exist
    fn retry_get_file(p:&'static str) -> Result<File, KVError> {
        retry!(i, {
            match OpenOptions::new().read(true).write(true).create(true).open(p) {
                Ok(f) => { return Ok(f); },
                Err(e) => {
                    error!("{}", e);
                    last_retry!(i, return Err(KVError::CouldntOpen));
                    continue;
                }
            };
        });

        Err(KVError::CouldntOpen)
    }

    /// Inserta a key, value pair into the key-value store
    pub fn insert(&mut self, key: K, value: V) -> KVResult {
        // check that can write to the cab
        if let Err(e) = self.file.lock_exclusive() {
            error!("{}", e);
            return Err(KVError::CouldntWriteLock);
        }
        // make sure mem version up to date
        if let Err(e) = self.load_from_persist(true) {
            return Err(e);
        }
        // insert into the HashMap
        self.cab.insert(key, value);
        // persist
        self.write_to_persist()
    }

    /// Get the value from a key
    pub fn get(&mut self, key: K) -> Result<Option<V>, KVError> {
        // make sure mem version up to date
        if let Err(e) = self.load_from_persist(false) {
            return Err(e);
        }
        // get the value from the cab
        match self.cab.get(&key) {
            Some(v) => Ok(Some((*v).clone())),
            None => Ok(None),
        }
    }

    /// Removes a key and associated value from the key-value Store
    pub fn remove(&mut self, key: K) -> KVResult {
        // check that can write to the cab
        if let Err(e) = self.file.lock_exclusive() {
            error!("{}", e);
            return Err(KVError::CouldntWriteLock);
        }
        // make sure mem version up to date
        if let Err(e) = self.load_from_persist(true) {
            return Err(e);
        }
        // remove from the HashMap
        self.cab.remove(&key);
        // persist
        self.write_to_persist()
    }

    /// get all the keys contained in the KV Store
    pub fn keys(&mut self) -> Result<Vec<K>, KVError> {
        // make sure mem version up to date
        if let Err(e) = self.load_from_persist(false) {
            return Err(e);
        }
        // create a vec from the cabs keys
        Ok(self.cab.keys().map(|k| k.clone()).collect())
    }

    /// Writes the key-value Store to file
    fn write_to_persist(&mut self) -> KVResult {
        // attempt to write to the cab
        retry!(i, {
            // check that can write to the cab
            if let Err(e) = self.file.lock_exclusive() {
                error!("{}", e);
                last_retry!(i, return Err(KVError::CouldntWriteLock));
                continue;
            }

            // encode the cab as a u8 vec
            let byte_vec: Vec<u8> = match encode(&mut self.cab, SizeLimit::Infinite) {
                Ok(bv) => bv,
                Err(e) => {
                    error!("encode: {}", e);
                    return Err(KVError::CouldntEncode);
                },
            };

            // seek to the start
            if let Err(e) = self.file.seek(SeekFrom::Start(0)) {
                error!("{}", e);
                last_retry!(i, return Err(KVError::CouldntSeekToStart));
                continue;
            }

            // write the bytes to it
            if let Err(e) = self.file.write_all(byte_vec.as_slice()) {
                error!("file.write_all/retry: {}", e);
                last_retry!(i, return Err(KVError::CouldntWrite));
                continue;
            }

            // flush to disk
            if let Err(e) = self.file.flush() {
                error!("{}", e);
                last_retry!(i, return Err(KVError::CouldntFlush));
                continue;
            }

            // unlock the file after write has completed
            if let Err(e) = self.file.unlock() {
                error!("{}", e);
                last_retry!(i, return Err(KVError::CouldntUnlock));
                continue;
            }
            return Ok(true);
        });

        Err(KVError::CouldntWrite)
    }

    /// Loads key-value store from file
    fn load_from_persist(&mut self, already_locked:bool) -> KVResult {
        retry!(i, {
            // byte vec to read into
            let mut byte_vec = Vec::new();

            // wait/lock the cab and read the bytes
            if !already_locked {
                if let Err(e) = self.file.lock_shared() {
                    error!("{}", e);
                    return Err(KVError::CouldntReadLock);
                }
            }

            // seek to the start
            if let Err(e) = self.file.seek(SeekFrom::Start(0)) {
                error!("{}", e);
                last_retry!(i, return Err(KVError::CouldntSeekToStart));
                continue;
            }

            // read the file into the buffer
            match self.file.read_to_end(&mut byte_vec) {
                Ok(count) => {
                    // don't attempt to decode as empty
                    if count == 0 {
                        if !already_locked {
                            if let Err(e) = self.file.unlock() {
                                error!("{}", e);
                                last_retry!(i, return Err(KVError::CouldntUnlock));
                            }
                        }
                        return Ok(true);
                    }
                },
                Err(e) => {
                    error!("{}", e);
                    return Err(KVError::FailedToRead);
                },
            }

            // decode u8 vec back into HashMap
            match decode(byte_vec.as_slice()) {
                Ok(f) => {
                    // assign read HashMap back to self
                    self.cab = f;
                    if !already_locked {
                        if let Err(e) = self.file.unlock() {
                            error!("{}", e);
                            last_retry!(i, return Err(KVError::CouldntUnlock));
                        }
                    }
                    return Ok(true);
                },
                Err(e) => {
                    error!("{}", e);
                    last_retry!(i, return Err(KVError::CouldntDecode));
                    continue;
                },
            };
        });

        Err(KVError::CouldntLoad)
    }
}
<|endoftext|>


<commit_before>//! A simple _asynchronous_ HTTP client library built on cURL
//! that looks like jQuery AJAX or python's request.
//!
//! This crate tries to reduce the boilerplate code one has to write
//! for asynchronous HTTP in Rust. It does this by being much more
//! opinionated as e.g. `hyper` and relying on the brand new
//! `tokio_curl`-crate and `futures-rs`.
//!
//! # Quick Start
//! Asynchronously send an HTTP request on the specified loop:
//!
//! ```rust
//! # extern crate tokio_core;
//! # extern crate tokio_request;
//! # extern crate url;
//! use tokio_core::reactor::Core;
//! use tokio_request::str::get;
//!
//! # fn main() {
//! let mut evloop = Core::new().unwrap();
//! let future = get("https://httpbin.org/get")
//!                 .header("User-Agent", "tokio-request")
//!                 .param("Hello", "This is Rust")
//!                 .param("Hello2", "This is also from Rust")
//!                 .send(evloop.handle());
//! let result = evloop.run(future).expect("HTTP Request failed!");
//! # assert!(result.is_success());
//! println!(
//!     "Site answered with status code {} and body\n{}",
//!     result.status_code(),
//!     result.body_str().unwrap_or("<No response body>")
//! );
//! # }
//! ```
//!
//! POST some JSON to an API:
//!
//! ```rust
//! # #![feature(plugin)]
//! # extern crate tokio_core;
//! # extern crate tokio_request;
//! # extern crate url;
//! # #[cfg(feature = "rustc-serialization")]
//! # extern crate rustc_serialize;
//! # #[cfg(feature = "serde-serialization")]
//! # extern crate serde;
//! # #[cfg(feature = "serde-serialization")]
//! # extern crate serde_json;
//! use tokio_core::reactor::Core;
//! use tokio_request::str::post;
//! #
//! # #[cfg(feature = "rustc-serialization")]
//! # #[derive(RustcEncodable)]
//! # struct Data {
//! #     a: u32,
//! #     b: u32
//! # }
//! #
//! # #[cfg(feature = "serde-serialization")]
//! # #[derive(Serialize)]
//! # struct Data {
//! #     a: u32,
//! #     b: u32
//! # }
//!
//! # fn main() {
//! let mut evloop = Core::new().unwrap();
//! let future = post("https://httpbin.org/post")
//!                 .json(&Data { a: 10, b: 15 })
//!                 .send(evloop.handle());
//! let result = evloop.run(future).expect("HTTP Request failed!");
//! # assert!(result.is_success());
//! println!(
//!     "Site answered with status code {} and body\n{}",
//!     result.status_code(),
//!     result.body_str().unwrap_or("<No response body>")
//! );
//! # }
//! ```
//!
//! # Caveats
//! Right now the focus for this library is on interacting with REST
//! APIs that talk JSON, so this library is buffering the entire response
//! into memory. This means it is not recommended for downloading large
//! files from the internet. Streaming request / response bodies will be
//! added at a later stage when implementation and API details have been
//! figured out.

#![deny(missing_docs)]
#![feature(receiver_try_iter)]

extern crate curl;
extern crate futures;
extern crate mime;
extern crate tokio_core;
extern crate tokio_curl;
extern crate url;

#[cfg(feature = "rustc-serialization")]
extern crate rustc_serialize;

mod request;
mod response;

use std::fmt::{Display, Formatter, Result as FmtResult};
pub use self::request::*;
pub use self::response::*;
use url::Url;

/// Issue a GET-Request to the specified URL.
pub fn get(url: &Url) -> Request {
    request(url, Method::Get)
}

/// Issue a DELETE-Request to the specified URL.
pub fn delete(url: &Url) -> Request {
    request(url, Method::Delete)
}

/// Issue a POST-Request to the specified URL.
pub fn post(url: &Url) -> Request {
    request(url, Method::Post)
}

/// Issue a PUT-Request to the specified URL.
pub fn put(url: &Url) -> Request {
    request(url, Method::Put)
}

/// Issue a request with the specified method to the specified URL.
pub fn request(url: &Url, method: Method) -> Request {
    Request::new(url, method)
}

/// A submodule which allows the request builder functions to be
/// used with string slices instead of URLs for convenience.
pub mod str {
    use ::{Method, Request};
    use url::Url;

    /// Issue a GET-Request to the specified URL.
    pub fn get(url: &str) -> Request {
        super::get(&parse_url(url))
    }

    /// Issue a DELETE-Request to the specified URL.
    pub fn delete(url: &str) -> Request {
        super::delete(&parse_url(url))
    }

    /// Issue a POST-Request to the specified URL.
    pub fn post(url: &str) -> Request {
        super::post(&parse_url(url))
    }

    /// Issue a PUT-Request to the specified URL.
    pub fn put(url: &str) -> Request {
        super::put(&parse_url(url))
    }

    /// Issue a request with the specified method to the specified URL.
    pub fn request(url: &str, method: Method) -> Request {
        super::request(&parse_url(url), method)
    }

    fn parse_url(url: &str) -> Url {
        Url::parse(url).unwrap()
    }

    #[cfg(test)]
    mod tests {
        macro_rules! generate_http_tests {
            ($name:ident) => {
                #[test]
                fn $name() {
                    use super::$name;
                    use tokio_core::reactor::Core;

                    let mut evloop = Core::new().unwrap();
                    let request = $name(&format!("https://httpbin.org/{}", stringify!($name)))
                                     .header("User-Agent", "tokio-request")
                                     .param("Hello", "This is Rust")
                                     .param("Hello2", "This is also from Rust");
                    println!("{:?}", request);
                    let future = request.send(evloop.handle());
                    let result = evloop.run(future).expect("HTTP Request failed!");
                    println!("{:?}", result);
                    assert!(result.is_success());
                    assert!(result.body().len() > 0);
                    assert!(result.headers().len() > 0);
                }
            }
        }

        generate_http_tests!(get);
        generate_http_tests!(post);
        generate_http_tests!(put);
        generate_http_tests!(delete);

        #[test]
        #[cfg(feature = "rustc-serialization")]
        fn test_json() {
            use super::get;
            use tokio_core::reactor::Core;

            let mut evloop = Core::new().unwrap();
            let request = get("https://httpbin.org/get")
                             .header("User-Agent", "tokio-request")
                             .param("Hello", "This is Rust")
                             .param("Hello2", "This is also from Rust");
            println!("{:?}", request);
            let future = request.send(evloop.handle());
            let result = evloop.run(future).expect("HTTP Request failed!");
            println!("{:?}", result);
            assert!(result.is_success());
            assert!(result.body().len() > 0);
            assert!(result.headers().len() > 0);
            result.json_value().unwrap();
        }
    }
}

/// Represents an HTTP method.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Method {
    /// GET
    Get,
    /// POST
    Post,
    /// PUT
    Put,
    /// DELETE
    Delete,
    /// HEAD
    Head,
    /// TRACE
    Trace,
    /// CONNECT
    Connect,
    /// PATCH
    Patch,
    /// OPTIONS
    Options,
    /// A custom HTTP header.
    Custom(String)
}

impl AsRef<str> for Method {
    fn as_ref(&self) -> &str {
        match *self {
            Method::Connect => "CONNECT",
            Method::Custom(ref m) => m.as_ref(),
            Method::Delete => "DELETE",
            Method::Get => "GET",
            Method::Head => "HEAD",
            Method::Options => "OPTIONS",
            Method::Patch => "PATCH",
            Method::Post => "POST",
            Method::Put => "PUT",
            Method::Trace => "TRACE"
        }
    }
}

impl Default for Method {
    fn default() -> Self {
        Method::Get
    }
}

impl Display for Method {
    fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
        fmt.write_str(self.as_ref())
    }
}<commit_msg>Automatically test json serialization when rustc_serialize is available<commit_after>//! A simple _asynchronous_ HTTP client library built on cURL
//! that looks like jQuery AJAX or python's request.
//!
//! This crate tries to reduce the boilerplate code one has to write
//! for asynchronous HTTP in Rust. It does this by being much more
//! opinionated as e.g. `hyper` and relying on the brand new
//! `tokio_curl`-crate and `futures-rs`.
//!
//! # Quick Start
//! Asynchronously send an HTTP request on the specified loop:
//!
//! ```rust
//! # extern crate tokio_core;
//! # extern crate tokio_request;
//! # extern crate url;
//! use tokio_core::reactor::Core;
//! use tokio_request::str::get;
//!
//! # fn main() {
//! let mut evloop = Core::new().unwrap();
//! let future = get("https://httpbin.org/get")
//!                 .header("User-Agent", "tokio-request")
//!                 .param("Hello", "This is Rust")
//!                 .param("Hello2", "This is also from Rust")
//!                 .send(evloop.handle());
//! let result = evloop.run(future).expect("HTTP Request failed!");
//! # assert!(result.is_success());
//! println!(
//!     "Site answered with status code {} and body\n{}",
//!     result.status_code(),
//!     result.body_str().unwrap_or("<No response body>")
//! );
//! # }
//! ```
//!
//! POST some JSON to an API:
//!
//! ```rust
//! # #![feature(plugin)]
//! # extern crate tokio_core;
//! # extern crate tokio_request;
//! # extern crate url;
//! # #[cfg(feature = "rustc-serialization")]
//! # extern crate rustc_serialize;
//! # #[cfg(feature = "serde-serialization")]
//! # extern crate serde;
//! # #[cfg(feature = "serde-serialization")]
//! # extern crate serde_json;
//! use tokio_core::reactor::Core;
//! use tokio_request::str::post;
//! #
//! # #[cfg(feature = "rustc-serialization")]
//! # #[derive(RustcEncodable)]
//! # struct Data {
//! #     a: u32,
//! #     b: u32
//! # }
//! #
//! # #[cfg(feature = "serde-serialization")]
//! # #[derive(Serialize)]
//! # struct Data {
//! #     a: u32,
//! #     b: u32
//! # }
//!
//! # fn main() {
//! let mut evloop = Core::new().unwrap();
//! let future = post("https://httpbin.org/post")
//!                 .json(&Data { a: 10, b: 15 })
//!                 .send(evloop.handle());
//! let result = evloop.run(future).expect("HTTP Request failed!");
//! # assert!(result.is_success());
//! println!(
//!     "Site answered with status code {} and body\n{}",
//!     result.status_code(),
//!     result.body_str().unwrap_or("<No response body>")
//! );
//! # }
//! ```
//!
//! # Caveats
//! Right now the focus for this library is on interacting with REST
//! APIs that talk JSON, so this library is buffering the entire response
//! into memory. This means it is not recommended for downloading large
//! files from the internet. Streaming request / response bodies will be
//! added at a later stage when implementation and API details have been
//! figured out.

#![deny(missing_docs)]
#![feature(receiver_try_iter)]

extern crate curl;
extern crate futures;
extern crate mime;
extern crate tokio_core;
extern crate tokio_curl;
extern crate url;

#[cfg(feature = "rustc-serialization")]
extern crate rustc_serialize;

mod request;
mod response;

use std::fmt::{Display, Formatter, Result as FmtResult};
pub use self::request::*;
pub use self::response::*;
use url::Url;

/// Issue a GET-Request to the specified URL.
pub fn get(url: &Url) -> Request {
    request(url, Method::Get)
}

/// Issue a DELETE-Request to the specified URL.
pub fn delete(url: &Url) -> Request {
    request(url, Method::Delete)
}

/// Issue a POST-Request to the specified URL.
pub fn post(url: &Url) -> Request {
    request(url, Method::Post)
}

/// Issue a PUT-Request to the specified URL.
pub fn put(url: &Url) -> Request {
    request(url, Method::Put)
}

/// Issue a request with the specified method to the specified URL.
pub fn request(url: &Url, method: Method) -> Request {
    Request::new(url, method)
}

/// A submodule which allows the request builder functions to be
/// used with string slices instead of URLs for convenience.
pub mod str {
    use ::{Method, Request};
    use url::Url;

    /// Issue a GET-Request to the specified URL.
    pub fn get(url: &str) -> Request {
        super::get(&parse_url(url))
    }

    /// Issue a DELETE-Request to the specified URL.
    pub fn delete(url: &str) -> Request {
        super::delete(&parse_url(url))
    }

    /// Issue a POST-Request to the specified URL.
    pub fn post(url: &str) -> Request {
        super::post(&parse_url(url))
    }

    /// Issue a PUT-Request to the specified URL.
    pub fn put(url: &str) -> Request {
        super::put(&parse_url(url))
    }

    /// Issue a request with the specified method to the specified URL.
    pub fn request(url: &str, method: Method) -> Request {
        super::request(&parse_url(url), method)
    }

    fn parse_url(url: &str) -> Url {
        Url::parse(url).unwrap()
    }
}

/// Represents an HTTP method.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Method {
    /// GET
    Get,
    /// POST
    Post,
    /// PUT
    Put,
    /// DELETE
    Delete,
    /// HEAD
    Head,
    /// TRACE
    Trace,
    /// CONNECT
    Connect,
    /// PATCH
    Patch,
    /// OPTIONS
    Options,
    /// A custom HTTP header.
    Custom(String)
}

impl AsRef<str> for Method {
    fn as_ref(&self) -> &str {
        match *self {
            Method::Connect => "CONNECT",
            Method::Custom(ref m) => m.as_ref(),
            Method::Delete => "DELETE",
            Method::Get => "GET",
            Method::Head => "HEAD",
            Method::Options => "OPTIONS",
            Method::Patch => "PATCH",
            Method::Post => "POST",
            Method::Put => "PUT",
            Method::Trace => "TRACE"
        }
    }
}

impl Default for Method {
    fn default() -> Self {
        Method::Get
    }
}

impl Display for Method {
    fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
        fmt.write_str(self.as_ref())
    }
}

#[cfg(test)]
mod tests {
    macro_rules! generate_http_tests {
        ($name:ident) => {
            #[test]
            fn $name() {
                use super::str::$name;
                use tokio_core::reactor::Core;

                let mut evloop = Core::new().unwrap();
                let request = $name(&format!("https://httpbin.org/{}", stringify!($name)))
                                    .header("User-Agent", "tokio-request")
                                    .param("Hello", "This is Rust")
                                    .param("Hello2", "This is also from Rust");
                let future = request.send(evloop.handle());
                let result = evloop.run(future).expect("HTTP Request failed!");

                println!("{:?}", result);

                assert!(result.is_success());
                assert!(result.body().len() > 0);
                assert!(result.headers().len() > 0);

                if cfg!(feature = "rustc-serialization") {
                    result.json_value().unwrap();
                }
            }
        }
    }

    generate_http_tests!(get);
    generate_http_tests!(post);
    generate_http_tests!(put);
    generate_http_tests!(delete);
}<|endoftext|>