<commit_before>use num::{self, Float, Num, NumCast};

use ordered::{HashConjugate, NotNan};

#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Duplet<T>(pub T, pub T);

#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Triplet<T>(pub T, pub T, pub T);

pub trait Unit: Copy + Num {
    fn unit_radius() -> (Self, Self);
    fn unit_width() -> (Self, Self);
}

// TODO: https://github.com/reem/rust-ordered-float/pull/31
//       Once `NotNan` implements numeric traits, implement `Unit` for `NotNan`
//       and allow it to be used as vertex geometry in generators.
macro_rules! unit {
    (integer => $($t:ty),*) => {$(
        impl Unit for $t {
            fn unit_radius() -> (Self, Self) {
                use num::{One, Zero};
                (Self::zero(), Self::one() + Self::one())
            }

            fn unit_width() -> (Self, Self) {
                use num::{One, Zero};
                (Self::zero(), Self::one())
            }
        }
    )*};
    (real => $($t:ty),*) => {$(
        impl Unit for $t {
            fn unit_radius() -> (Self, Self) {
                use num::One;
                (-Self::one(), Self::one())
            }

            fn unit_width() -> (Self, Self) {
                use num::One;
                let half = Self::one() / (Self::one() + Self::one());
                (-half, half)
            }
        }
    )*};
}
unit!(integer => i8, i16, i32, i64, u8, u16, u32, u64);
unit!(real => f32, f64);

pub trait Interpolate<T = Self>: Sized {
    type Output;

    fn lerp(self, other: T, f: f64) -> Self::Output;

    fn midpoint(self, other: T) -> Self::Output {
        self.lerp(other, 0.5)
    }
}

impl<T> Interpolate for Duplet<T>
where
    T: Copy + Num + NumCast,
{
    type Output = Self;

    fn lerp(self, other: Self, f: f64) -> Self::Output {
        Duplet(lerp(self.0, other.0, f), lerp(self.1, other.1, f))
    }
}

impl<T> Interpolate for Triplet<T>
where
    T: Copy + Num + NumCast,
{
    type Output = Self;

    fn lerp(self, other: Self, f: f64) -> Self::Output {
        Triplet(
            lerp(self.0, other.0, f),
            lerp(self.1, other.1, f),
            lerp(self.2, other.2, f),
        )
    }
}

fn lerp<T>(a: T, b: T, f: f64) -> T
where
    T: Num + NumCast,
{
    let f = num::clamp(f, 0.0, 1.0);
    let af = <f64 as NumCast>::from(a).unwrap() * (1.0 - f);
    let bf = <f64 as NumCast>::from(b).unwrap() * f;
    <T as NumCast>::from(af + bf).unwrap()
}

impl<T> HashConjugate for Duplet<T>
where
    T: Float + Unit,
{
    type Hash = Duplet<NotNan<T>>;

    fn into_hash(self) -> Self::Hash {
        Duplet(NotNan::new(self.0).unwrap(), NotNan::new(self.1).unwrap())
    }

    fn from_hash(hash: Self::Hash) -> Self {
        Duplet((hash.0).into_inner(), (hash.1).into_inner())
    }
}

impl<T> HashConjugate for Triplet<T>
where
    T: Float + Unit,
{
    type Hash = Triplet<NotNan<T>>;

    fn into_hash(self) -> Self::Hash {
        Triplet(
            NotNan::new(self.0).unwrap(),
            NotNan::new(self.1).unwrap(),
            NotNan::new(self.2).unwrap(),
        )
    }

    fn from_hash(hash: Self::Hash) -> Self {
        Triplet(
            (hash.0).into_inner(),
            (hash.1).into_inner(),
            (hash.2).into_inner(),
        )
    }
}

#[cfg(feature = "geometry-nalgebra")]
mod feature {
    use nalgebra::{Point2, Point3, Scalar, Vector2, Vector3};

    use super::*;

    impl<T> From<Point2<T>> for Duplet<T>
    where
        T: Scalar,
    {
        fn from(other: Point2<T>) -> Self {
            Duplet(other.x, other.y)
        }
    }

    impl<T> From<Vector2<T>> for Duplet<T>
    where
        T: Scalar,
    {
        fn from(other: Vector2<T>) -> Self {
            Duplet(other.x, other.y)
        }
    }

    impl<T> Into<Point2<T>> for Duplet<T>
    where
        T: Scalar,
    {
        fn into(self) -> Point2<T> {
            Point2::new(self.0, self.1)
        }
    }

    impl<T> Into<Vector2<T>> for Duplet<T>
    where
        T: Scalar,
    {
        fn into(self) -> Vector2<T> {
            Vector2::new(self.0, self.1)
        }
    }

    impl<T> From<Point3<T>> for Triplet<T>
    where
        T: Scalar,
    {
        fn from(other: Point3<T>) -> Self {
            Triplet(other.x, other.y, other.z)
        }
    }

    impl<T> From<Vector3<T>> for Triplet<T>
    where
        T: Scalar,
    {
        fn from(other: Vector3<T>) -> Self {
            Triplet(other.x, other.y, other.z)
        }
    }

    impl<T> Into<Point3<T>> for Triplet<T>
    where
        T: Scalar,
    {
        fn into(self) -> Point3<T> {
            Point3::new(self.0, self.1, self.2)
        }
    }

    impl<T> Into<Vector3<T>> for Triplet<T>
    where
        T: Scalar,
    {
        fn into(self) -> Vector3<T> {
            Vector3::new(self.0, self.1, self.2)
        }
    }

    impl<T> Interpolate for Point2<T>
    where
        T: NumCast + Scalar + Unit,
    {
        type Output = Self;

        fn lerp(self, other: Self, f: f64) -> Self::Output {
            Point2::new(lerp(self.x, other.x, f), lerp(self.y, other.y, f))
        }
    }

    impl<T> Interpolate for Point3<T>
    where
        T: NumCast + Scalar + Unit,
    {
        type Output = Self;

        fn lerp(self, other: Self, f: f64) -> Self::Output {
            Point3::new(
                lerp(self.x, other.x, f),
                lerp(self.y, other.y, f),
                lerp(self.z, other.z, f),
            )
        }
    }

    impl<T> Interpolate for Vector2<T>
    where
        T: NumCast + Scalar + Unit,
    {
        type Output = Self;

        fn lerp(self, other: Self, f: f64) -> Self::Output {
            Vector2::new(lerp(self.x, other.x, f), lerp(self.y, other.y, f))
        }
    }

    impl<T> Interpolate for Vector3<T>
    where
        T: NumCast + Scalar + Unit,
    {
        type Output = Self;

        fn lerp(self, other: Self, f: f64) -> Self::Output {
            Vector3::new(
                lerp(self.x, other.x, f),
                lerp(self.y, other.y, f),
                lerp(self.z, other.z, f),
            )
        }
    }

    impl<T> HashConjugate for Point2<T>
    where
        T: Float + Scalar + Unit,
    {
        type Hash = Duplet<NotNan<T>>;

        fn into_hash(self) -> Self::Hash {
            Duplet(NotNan::new(self.x).unwrap(), NotNan::new(self.y).unwrap())
        }

        fn from_hash(hash: Self::Hash) -> Self {
            Point2::new((hash.0).into_inner(), (hash.1).into_inner())
        }
    }

    impl<T> HashConjugate for Point3<T>
    where
        T: Float + Scalar + Unit,
    {
        type Hash = Triplet<NotNan<T>>;

        fn into_hash(self) -> Self::Hash {
            Triplet(
                NotNan::new(self.x).unwrap(),
                NotNan::new(self.y).unwrap(),
                NotNan::new(self.z).unwrap(),
            )
        }

        fn from_hash(hash: Self::Hash) -> Self {
            Point3::new(
                (hash.0).into_inner(),
                (hash.1).into_inner(),
                (hash.2).into_inner(),
            )
        }
    }

    impl<T> HashConjugate for Vector2<T>
    where
        T: Float + Scalar + Unit,
    {
        type Hash = Duplet<NotNan<T>>;

        fn into_hash(self) -> Self::Hash {
            Duplet(NotNan::new(self.x).unwrap(), NotNan::new(self.y).unwrap())
        }

        fn from_hash(hash: Self::Hash) -> Self {
            Vector2::new((hash.0).into_inner(), (hash.1).into_inner())
        }
    }

    impl<T> HashConjugate for Vector3<T>
    where
        T: Float + Scalar + Unit,
    {
        type Hash = Triplet<NotNan<T>>;

        fn into_hash(self) -> Self::Hash {
            Triplet(
                NotNan::new(self.x).unwrap(),
                NotNan::new(self.y).unwrap(),
                NotNan::new(self.z).unwrap(),
            )
        }

        fn from_hash(hash: Self::Hash) -> Self {
            Vector3::new(
                (hash.0).into_inner(),
                (hash.1).into_inner(),
                (hash.2).into_inner(),
            )
        }
    }
}

#[cfg(not(feature = "geometry-nalgebra"))]
mod feature {}

pub use self::feature::*;
<commit_msg>Use point and vector types as hash conjugates.<commit_after>use num::{self, Float, Num, NumCast};

use ordered::{HashConjugate, NotNan};

#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Duplet<T>(pub T, pub T);

#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Triplet<T>(pub T, pub T, pub T);

pub trait Unit: Copy + Num {
    fn unit_radius() -> (Self, Self);
    fn unit_width() -> (Self, Self);
}

// TODO: https://github.com/reem/rust-ordered-float/pull/31
//       Once `NotNan` implements numeric traits, implement `Unit` for `NotNan`
//       and allow it to be used as vertex geometry in generators.
macro_rules! unit {
    (integer => $($t:ty),*) => {$(
        impl Unit for $t {
            fn unit_radius() -> (Self, Self) {
                use num::{One, Zero};
                (Self::zero(), Self::one() + Self::one())
            }

            fn unit_width() -> (Self, Self) {
                use num::{One, Zero};
                (Self::zero(), Self::one())
            }
        }
    )*};
    (real => $($t:ty),*) => {$(
        impl Unit for $t {
            fn unit_radius() -> (Self, Self) {
                use num::One;
                (-Self::one(), Self::one())
            }

            fn unit_width() -> (Self, Self) {
                use num::One;
                let half = Self::one() / (Self::one() + Self::one());
                (-half, half)
            }
        }
    )*};
}
unit!(integer => i8, i16, i32, i64, u8, u16, u32, u64);
unit!(real => f32, f64);

pub trait Interpolate<T = Self>: Sized {
    type Output;

    fn lerp(self, other: T, f: f64) -> Self::Output;

    fn midpoint(self, other: T) -> Self::Output {
        self.lerp(other, 0.5)
    }
}

impl<T> Interpolate for Duplet<T>
where
    T: Copy + Num + NumCast,
{
    type Output = Self;

    fn lerp(self, other: Self, f: f64) -> Self::Output {
        Duplet(lerp(self.0, other.0, f), lerp(self.1, other.1, f))
    }
}

impl<T> Interpolate for Triplet<T>
where
    T: Copy + Num + NumCast,
{
    type Output = Self;

    fn lerp(self, other: Self, f: f64) -> Self::Output {
        Triplet(
            lerp(self.0, other.0, f),
            lerp(self.1, other.1, f),
            lerp(self.2, other.2, f),
        )
    }
}

fn lerp<T>(a: T, b: T, f: f64) -> T
where
    T: Num + NumCast,
{
    let f = num::clamp(f, 0.0, 1.0);
    let af = <f64 as NumCast>::from(a).unwrap() * (1.0 - f);
    let bf = <f64 as NumCast>::from(b).unwrap() * f;
    <T as NumCast>::from(af + bf).unwrap()
}

impl<T> HashConjugate for Duplet<T>
where
    T: Float + Unit,
{
    type Hash = Duplet<NotNan<T>>;

    fn into_hash(self) -> Self::Hash {
        Duplet(NotNan::new(self.0).unwrap(), NotNan::new(self.1).unwrap())
    }

    fn from_hash(hash: Self::Hash) -> Self {
        Duplet((hash.0).into_inner(), (hash.1).into_inner())
    }
}

impl<T> HashConjugate for Triplet<T>
where
    T: Float + Unit,
{
    type Hash = Triplet<NotNan<T>>;

    fn into_hash(self) -> Self::Hash {
        Triplet(
            NotNan::new(self.0).unwrap(),
            NotNan::new(self.1).unwrap(),
            NotNan::new(self.2).unwrap(),
        )
    }

    fn from_hash(hash: Self::Hash) -> Self {
        Triplet(
            (hash.0).into_inner(),
            (hash.1).into_inner(),
            (hash.2).into_inner(),
        )
    }
}

#[cfg(feature = "geometry-nalgebra")]
mod feature {
    use nalgebra::{Point2, Point3, Scalar, Vector2, Vector3};

    use super::*;

    impl<T> From<Point2<T>> for Duplet<T>
    where
        T: Scalar,
    {
        fn from(other: Point2<T>) -> Self {
            Duplet(other.x, other.y)
        }
    }

    impl<T> From<Vector2<T>> for Duplet<T>
    where
        T: Scalar,
    {
        fn from(other: Vector2<T>) -> Self {
            Duplet(other.x, other.y)
        }
    }

    impl<T> Into<Point2<T>> for Duplet<T>
    where
        T: Scalar,
    {
        fn into(self) -> Point2<T> {
            Point2::new(self.0, self.1)
        }
    }

    impl<T> Into<Vector2<T>> for Duplet<T>
    where
        T: Scalar,
    {
        fn into(self) -> Vector2<T> {
            Vector2::new(self.0, self.1)
        }
    }

    impl<T> From<Point3<T>> for Triplet<T>
    where
        T: Scalar,
    {
        fn from(other: Point3<T>) -> Self {
            Triplet(other.x, other.y, other.z)
        }
    }

    impl<T> From<Vector3<T>> for Triplet<T>
    where
        T: Scalar,
    {
        fn from(other: Vector3<T>) -> Self {
            Triplet(other.x, other.y, other.z)
        }
    }

    impl<T> Into<Point3<T>> for Triplet<T>
    where
        T: Scalar,
    {
        fn into(self) -> Point3<T> {
            Point3::new(self.0, self.1, self.2)
        }
    }

    impl<T> Into<Vector3<T>> for Triplet<T>
    where
        T: Scalar,
    {
        fn into(self) -> Vector3<T> {
            Vector3::new(self.0, self.1, self.2)
        }
    }

    impl<T> Interpolate for Point2<T>
    where
        T: NumCast + Scalar + Unit,
    {
        type Output = Self;

        fn lerp(self, other: Self, f: f64) -> Self::Output {
            Point2::new(lerp(self.x, other.x, f), lerp(self.y, other.y, f))
        }
    }

    impl<T> Interpolate for Point3<T>
    where
        T: NumCast + Scalar + Unit,
    {
        type Output = Self;

        fn lerp(self, other: Self, f: f64) -> Self::Output {
            Point3::new(
                lerp(self.x, other.x, f),
                lerp(self.y, other.y, f),
                lerp(self.z, other.z, f),
            )
        }
    }

    impl<T> Interpolate for Vector2<T>
    where
        T: NumCast + Scalar + Unit,
    {
        type Output = Self;

        fn lerp(self, other: Self, f: f64) -> Self::Output {
            Vector2::new(lerp(self.x, other.x, f), lerp(self.y, other.y, f))
        }
    }

    impl<T> Interpolate for Vector3<T>
    where
        T: NumCast + Scalar + Unit,
    {
        type Output = Self;

        fn lerp(self, other: Self, f: f64) -> Self::Output {
            Vector3::new(
                lerp(self.x, other.x, f),
                lerp(self.y, other.y, f),
                lerp(self.z, other.z, f),
            )
        }
    }

    impl<T> HashConjugate for Point2<T>
    where
        T: Float + Scalar + Unit,
    {
        type Hash = Point2<NotNan<T>>;

        fn into_hash(self) -> Self::Hash {
            Point2::new(NotNan::new(self.x).unwrap(), NotNan::new(self.y).unwrap())
        }

        fn from_hash(hash: Self::Hash) -> Self {
            Point2::new(hash.x.into_inner(), hash.y.into_inner())
        }
    }

    impl<T> HashConjugate for Point3<T>
    where
        T: Float + Scalar + Unit,
    {
        type Hash = Point3<NotNan<T>>;

        fn into_hash(self) -> Self::Hash {
            Point3::new(
                NotNan::new(self.x).unwrap(),
                NotNan::new(self.y).unwrap(),
                NotNan::new(self.z).unwrap(),
            )
        }

        fn from_hash(hash: Self::Hash) -> Self {
            Point3::new(
                hash.x.into_inner(),
                hash.y.into_inner(),
                hash.z.into_inner(),
            )
        }
    }

    impl<T> HashConjugate for Vector2<T>
    where
        T: Float + Scalar + Unit,
    {
        type Hash = Vector2<NotNan<T>>;

        fn into_hash(self) -> Self::Hash {
            Vector2::new(NotNan::new(self.x).unwrap(), NotNan::new(self.y).unwrap())
        }

        fn from_hash(hash: Self::Hash) -> Self {
            Vector2::new(hash.x.into_inner(), hash.y.into_inner())
        }
    }

    impl<T> HashConjugate for Vector3<T>
    where
        T: Float + Scalar + Unit,
    {
        type Hash = Vector3<NotNan<T>>;

        fn into_hash(self) -> Self::Hash {
            Vector3::new(
                NotNan::new(self.x).unwrap(),
                NotNan::new(self.y).unwrap(),
                NotNan::new(self.z).unwrap(),
            )
        }

        fn from_hash(hash: Self::Hash) -> Self {
            Vector3::new(
                hash.x.into_inner(),
                hash.y.into_inner(),
                hash.z.into_inner(),
            )
        }
    }
}

#[cfg(not(feature = "geometry-nalgebra"))]
mod feature {}

pub use self::feature::*;
<|endoftext|>


<commit_before>pub struct Rule {

}<commit_msg>implement rules config<commit_after>use super::{device::DeviceId, integration::IntegrationId, rules_engine::Action};
use serde::Deserialize;
use std::collections::HashMap;

pub type RoutineId = String;

/// button sensors, motion sensors
#[derive(Clone, Deserialize, Debug)]
#[serde(untagged)]
pub enum SensorRuleState {
    OnOffSensor {
        value: bool,
    },
    DimmerSwitch {
        on: Option<bool>,
        up: Option<bool>,
        down: Option<bool>,
        off: Option<bool>,
    },
    Unknown,
}

#[derive(Clone, Deserialize, Debug)]
pub struct Rule {
    integration_id: IntegrationId,
    device_id: DeviceId,
    state: SensorRuleState,
}

pub type RulesConfig = Vec<Rule>;
pub type ActionsConfig = Vec<Action>;

#[derive(Clone, Deserialize, Debug)]
pub struct RoutineConfig {
    pub name: String,
    pub rules: RulesConfig,
    pub actions: ActionsConfig,
}

pub type RoutinesConfig = HashMap<RoutineId, RoutineConfig>;
<|endoftext|>


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

use scale_factor::ScaleFactor;

use std::num::{cast, Zero};

/// A one-dimensional distance, with value represented by `T` and unit of measurement `Unit`.
///
/// `T` can be any numerical type, for example a primitive type like uint64 or f32.
///
/// `Unit` is not used in the representation of a Length value. It is used only at compile-time
/// to ensure that a Length stored with one unit is converted explicitly before being used in an
/// expression that requires a different unit.  It may be a type without values, such as an empty
/// enum.
///
/// You can multiply a Length by a `scale_factor::ScaleFactor` to convert it from one unit to
/// another.  See the ScaleFactor docs for an example.
#[deriving(Decodable, Encodable, Show)]
pub struct Length<Unit, T>(pub T);

// *length
impl<Unit, T> Deref<T> for Length<Unit, T> {
    fn deref<'a>(&'a self) -> &'a T {
        match *self {
            Length(ref x) => x
        }
    }
}

// length + length
impl<U, T: Add<T, T>> Add<Length<U, T>, Length<U, T>> for Length<U, T> {
    fn add(&self, other: &Length<U, T>) -> Length<U, T> {
        Length(**self + **other)
    }
}

// length - length
impl<U, T: Sub<T, T>> Sub<Length<U, T>, Length<U, T>> for Length<U, T> {
    fn sub(&self, other: &Length<U, T>) -> Length<U, T> {
        Length(**self - **other)
    }
}

// length * scaleFactor
impl<Src, Dst, T: Mul<f32, T>> Mul<ScaleFactor<Src, Dst>, Length<Dst, T>> for Length<Src, T> {
    #[inline]
    fn mul(&self, scale: &ScaleFactor<Src, Dst>) -> Length<Dst, T> {
        Length(**self * **scale)
    }
}

// length / scaleFactor
impl<Src, Dst, T: Div<f32, T>> Div<ScaleFactor<Src, Dst>, Length<Src, T>> for Length<Dst, T> {
    #[inline]
    fn div(&self, scale: &ScaleFactor<Src, Dst>) -> Length<Src, T> {
        Length(**self / **scale)
    }
}

impl<Unit, T0: NumCast + Clone, T1: NumCast + Clone> Length<Unit, T0> {
    /// Cast from one numeric representation to another, preserving the units.
    pub fn cast(&self) -> Option<Length<Unit, T1>> {
        cast((**self).clone()).map(|x| Length(x))
    }
}

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

impl<Unit, T: Clone> Clone for Length<Unit, T> {
    fn clone(&self) -> Length<Unit, T> {
        Length((**self).clone())
    }
}

impl<Unit, T: Eq> Eq for Length<Unit, T> {
    fn eq(&self, other: &Length<Unit, T>) -> bool { (**self).eq(&**other) }
}

impl<Unit, T: Ord> Ord for Length<Unit, T> {
    fn lt(&self, other: &Length<Unit, T>) -> bool { (**self).lt(&**other) }
    fn le(&self, other: &Length<Unit, T>) -> bool { (**self).le(&**other) }
    fn gt(&self, other: &Length<Unit, T>) -> bool { (**self).gt(&**other) }
    fn ge(&self, other: &Length<Unit, T>) -> bool { (**self).ge(&**other) }
}

impl<Unit, T: TotalEq> TotalEq for Length<Unit, T> {}

impl<Unit, T: TotalOrd> TotalOrd for Length<Unit, T> {
    fn cmp(&self, other: &Length<Unit, T>) -> Ordering { (**self).cmp(&**other) }
}

impl<Unit, T: Zero> Zero for Length<Unit, T> {
    fn zero() -> Length<Unit, T> {
        Length(Zero::zero())
    }

    fn is_zero(&self) -> bool {
        (**self).is_zero()
    }
}

#[cfg(test)]
mod tests {
    use super::Length;
    use scale_factor::ScaleFactor;
    use std::num::Zero;

    #[deriving(Show)]
    enum Inch {}
    #[deriving(Show)]
    enum Mm {}

    #[test]
    fn test_length() {
        let mm_per_inch: ScaleFactor<Inch, Mm> = ScaleFactor(25.4);

        let one_foot: Length<Inch, f32> = Length(12.0);
        let two_feet = one_foot + one_foot;
        let zero_feet = one_foot - one_foot;

        assert_eq!(*one_foot, 12.0);
        assert_eq!(*two_feet, 24.0);
        assert!(zero_feet.is_zero());

        assert!(one_foot == one_foot);
        assert!(two_feet != one_foot);

        assert!(zero_feet <  one_foot);
        assert!(zero_feet <= one_foot);
        assert!(two_feet  >  one_foot);
        assert!(two_feet  >= one_foot);

        assert!(  two_feet <= two_feet);
        assert!(  two_feet >= two_feet);
        assert!(!(two_feet >  two_feet));
        assert!(!(two_feet <  two_feet));

        let one_foot_in_mm: Length<Mm, f32> = one_foot * mm_per_inch;

        assert_eq!(*one_foot_in_mm, 304.8);

        let back_to_inches: Length<Inch, f32> = one_foot_in_mm / mm_per_inch;
        assert_eq!(one_foot, back_to_inches);

        let int_foot: Length<Inch, int> = one_foot.cast().unwrap();
        assert_eq!(*int_foot, 12);
    }
}
<commit_msg>Minor copy-editing of doc comments<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 one-dimensional length, tagged with its units.

use scale_factor::ScaleFactor;

use std::num::{cast, Zero};

/// A one-dimensional distance, with value represented by `T` and unit of measurement `Unit`.
///
/// `T` can be any numeric type, for example a primitive type like u64 or f32.
///
/// `Unit` is not used in the representation of a Length value. It is used only at compile time
/// to ensure that a Length stored with one unit is converted explicitly before being used in an
/// expression that requires a different unit.  It may be a type without values, such as an empty
/// enum.
///
/// You can multiply a Length by a `scale_factor::ScaleFactor` to convert it from one unit to
/// another.  See the ScaleFactor docs for an example.
#[deriving(Decodable, Encodable, Show)]
pub struct Length<Unit, T>(pub T);

// *length
impl<Unit, T> Deref<T> for Length<Unit, T> {
    fn deref<'a>(&'a self) -> &'a T {
        match *self {
            Length(ref x) => x
        }
    }
}

// length + length
impl<U, T: Add<T, T>> Add<Length<U, T>, Length<U, T>> for Length<U, T> {
    fn add(&self, other: &Length<U, T>) -> Length<U, T> {
        Length(**self + **other)
    }
}

// length - length
impl<U, T: Sub<T, T>> Sub<Length<U, T>, Length<U, T>> for Length<U, T> {
    fn sub(&self, other: &Length<U, T>) -> Length<U, T> {
        Length(**self - **other)
    }
}

// length * scaleFactor
impl<Src, Dst, T: Mul<f32, T>> Mul<ScaleFactor<Src, Dst>, Length<Dst, T>> for Length<Src, T> {
    #[inline]
    fn mul(&self, scale: &ScaleFactor<Src, Dst>) -> Length<Dst, T> {
        Length(**self * **scale)
    }
}

// length / scaleFactor
impl<Src, Dst, T: Div<f32, T>> Div<ScaleFactor<Src, Dst>, Length<Src, T>> for Length<Dst, T> {
    #[inline]
    fn div(&self, scale: &ScaleFactor<Src, Dst>) -> Length<Src, T> {
        Length(**self / **scale)
    }
}

impl<Unit, T0: NumCast + Clone, T1: NumCast + Clone> Length<Unit, T0> {
    /// Cast from one numeric representation to another, preserving the units.
    pub fn cast(&self) -> Option<Length<Unit, T1>> {
        cast((**self).clone()).map(|x| Length(x))
    }
}

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

impl<Unit, T: Clone> Clone for Length<Unit, T> {
    fn clone(&self) -> Length<Unit, T> {
        Length((**self).clone())
    }
}

impl<Unit, T: Eq> Eq for Length<Unit, T> {
    fn eq(&self, other: &Length<Unit, T>) -> bool { (**self).eq(&**other) }
}

impl<Unit, T: Ord> Ord for Length<Unit, T> {
    fn lt(&self, other: &Length<Unit, T>) -> bool { (**self).lt(&**other) }
    fn le(&self, other: &Length<Unit, T>) -> bool { (**self).le(&**other) }
    fn gt(&self, other: &Length<Unit, T>) -> bool { (**self).gt(&**other) }
    fn ge(&self, other: &Length<Unit, T>) -> bool { (**self).ge(&**other) }
}

impl<Unit, T: TotalEq> TotalEq for Length<Unit, T> {}

impl<Unit, T: TotalOrd> TotalOrd for Length<Unit, T> {
    fn cmp(&self, other: &Length<Unit, T>) -> Ordering { (**self).cmp(&**other) }
}

impl<Unit, T: Zero> Zero for Length<Unit, T> {
    fn zero() -> Length<Unit, T> {
        Length(Zero::zero())
    }

    fn is_zero(&self) -> bool {
        (**self).is_zero()
    }
}

#[cfg(test)]
mod tests {
    use super::Length;
    use scale_factor::ScaleFactor;
    use std::num::Zero;

    #[deriving(Show)]
    enum Inch {}
    #[deriving(Show)]
    enum Mm {}

    #[test]
    fn test_length() {
        let mm_per_inch: ScaleFactor<Inch, Mm> = ScaleFactor(25.4);

        let one_foot: Length<Inch, f32> = Length(12.0);
        let two_feet = one_foot + one_foot;
        let zero_feet = one_foot - one_foot;

        assert_eq!(*one_foot, 12.0);
        assert_eq!(*two_feet, 24.0);
        assert!(zero_feet.is_zero());

        assert!(one_foot == one_foot);
        assert!(two_feet != one_foot);

        assert!(zero_feet <  one_foot);
        assert!(zero_feet <= one_foot);
        assert!(two_feet  >  one_foot);
        assert!(two_feet  >= one_foot);

        assert!(  two_feet <= two_feet);
        assert!(  two_feet >= two_feet);
        assert!(!(two_feet >  two_feet));
        assert!(!(two_feet <  two_feet));

        let one_foot_in_mm: Length<Mm, f32> = one_foot * mm_per_inch;

        assert_eq!(*one_foot_in_mm, 304.8);

        let back_to_inches: Length<Inch, f32> = one_foot_in_mm / mm_per_inch;
        assert_eq!(one_foot, back_to_inches);

        let int_foot: Length<Inch, int> = one_foot.cast().unwrap();
        assert_eq!(*int_foot, 12);
    }
}
<|endoftext|>


<commit_before>//! Yet another index-based arena.

use std::{
    fmt,
    marker::PhantomData,
    ops::{Index, IndexMut},
    iter::FromIterator,
};

pub mod map;

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct RawId(u32);

impl From<RawId> for u32 {
    fn from(raw: RawId) -> u32 {
        raw.0
    }
}

impl From<u32> for RawId {
    fn from(id: u32) -> RawId {
        RawId(id)
    }
}

impl fmt::Debug for RawId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl fmt::Display for RawId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

#[derive(Clone, PartialEq, Eq)]
pub struct Arena<ID: ArenaId, T> {
    data: Vec<T>,
    _ty: PhantomData<ID>,
}

impl<ID: ArenaId, T: fmt::Debug> fmt::Debug for Arena<ID, T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Arena").field("len", &self.len()).field("data", &self.data).finish()
    }
}

#[macro_export]
macro_rules! impl_arena_id {
    ($name:ident) => {
        impl $crate::ArenaId for $name {
            fn from_raw(raw: $crate::RawId) -> Self {
                $name(raw)
            }
            fn into_raw(self) -> $crate::RawId {
                self.0
            }
        }
    };
}

pub trait ArenaId {
    fn from_raw(raw: RawId) -> Self;
    fn into_raw(self) -> RawId;
}

impl<ID: ArenaId, T> Arena<ID, T> {
    pub fn len(&self) -> usize {
        self.data.len()
    }
    pub fn alloc(&mut self, value: T) -> ID {
        let id = RawId(self.data.len() as u32);
        self.data.push(value);
        ID::from_raw(id)
    }
    pub fn iter(&self) -> impl Iterator<Item = (ID, &T)> {
        self.data.iter().enumerate().map(|(idx, value)| (ID::from_raw(RawId(idx as u32)), value))
    }
}

impl<ID: ArenaId, T> Default for Arena<ID, T> {
    fn default() -> Arena<ID, T> {
        Arena { data: Vec::new(), _ty: PhantomData }
    }
}

impl<ID: ArenaId, T> Index<ID> for Arena<ID, T> {
    type Output = T;
    fn index(&self, idx: ID) -> &T {
        let idx = idx.into_raw().0 as usize;
        &self.data[idx]
    }
}

impl<ID: ArenaId, T> IndexMut<ID> for Arena<ID, T> {
    fn index_mut(&mut self, idx: ID) -> &mut T {
        let idx = idx.into_raw().0 as usize;
        &mut self.data[idx]
    }
}

impl<ID: ArenaId, T> FromIterator<T> for Arena<ID, T> {
    fn from_iter<I>(iter: I) -> Self
    where
        I: IntoIterator<Item = T>,
    {
        Arena { data: Vec::from_iter(iter), _ty: PhantomData }
    }
}
<commit_msg>Add is_empty to Arena<commit_after>//! Yet another index-based arena.

use std::{
    fmt,
    marker::PhantomData,
    ops::{Index, IndexMut},
    iter::FromIterator,
};

pub mod map;

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct RawId(u32);

impl From<RawId> for u32 {
    fn from(raw: RawId) -> u32 {
        raw.0
    }
}

impl From<u32> for RawId {
    fn from(id: u32) -> RawId {
        RawId(id)
    }
}

impl fmt::Debug for RawId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl fmt::Display for RawId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

#[derive(Clone, PartialEq, Eq)]
pub struct Arena<ID: ArenaId, T> {
    data: Vec<T>,
    _ty: PhantomData<ID>,
}

impl<ID: ArenaId, T: fmt::Debug> fmt::Debug for Arena<ID, T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Arena").field("len", &self.len()).field("data", &self.data).finish()
    }
}

#[macro_export]
macro_rules! impl_arena_id {
    ($name:ident) => {
        impl $crate::ArenaId for $name {
            fn from_raw(raw: $crate::RawId) -> Self {
                $name(raw)
            }
            fn into_raw(self) -> $crate::RawId {
                self.0
            }
        }
    };
}

pub trait ArenaId {
    fn from_raw(raw: RawId) -> Self;
    fn into_raw(self) -> RawId;
}

impl<ID: ArenaId, T> Arena<ID, T> {
    pub fn len(&self) -> usize {
        self.data.len()
    }
    pub fn is_empty(&self) -> bool {
        self.data.is_empty()
    }
    pub fn alloc(&mut self, value: T) -> ID {
        let id = RawId(self.data.len() as u32);
        self.data.push(value);
        ID::from_raw(id)
    }
    pub fn iter(&self) -> impl Iterator<Item = (ID, &T)> {
        self.data.iter().enumerate().map(|(idx, value)| (ID::from_raw(RawId(idx as u32)), value))
    }
}

impl<ID: ArenaId, T> Default for Arena<ID, T> {
    fn default() -> Arena<ID, T> {
        Arena { data: Vec::new(), _ty: PhantomData }
    }
}

impl<ID: ArenaId, T> Index<ID> for Arena<ID, T> {
    type Output = T;
    fn index(&self, idx: ID) -> &T {
        let idx = idx.into_raw().0 as usize;
        &self.data[idx]
    }
}

impl<ID: ArenaId, T> IndexMut<ID> for Arena<ID, T> {
    fn index_mut(&mut self, idx: ID) -> &mut T {
        let idx = idx.into_raw().0 as usize;
        &mut self.data[idx]
    }
}

impl<ID: ArenaId, T> FromIterator<T> for Arena<ID, T> {
    fn from_iter<I>(iter: I) -> Self
    where
        I: IntoIterator<Item = T>,
    {
        Arena { data: Vec::from_iter(iter), _ty: PhantomData }
    }
}
<|endoftext|>


<commit_before>// Copyright 2015-2016, The Gtk-rs 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>

use std::mem;
use std::slice;
use libc::c_void;

#[cfg(feature = "use_glib")]
use glib::translate::*;
use ffi;
use ::enums::{
    Content,
    Status,
    SurfaceType,
};

#[derive(Debug)]
pub struct Surface(*mut ffi::cairo_surface_t, bool);

impl Surface {
    pub unsafe fn from_raw_none(ptr: *mut ffi::cairo_surface_t) -> Surface {
        assert!(!ptr.is_null());
        ffi::cairo_surface_reference(ptr);
        Surface(ptr, false)
    }

    pub unsafe fn from_raw_borrow(ptr: *mut ffi::cairo_surface_t) -> Surface {
        assert!(!ptr.is_null());
        Surface(ptr, true)
    }

    pub unsafe fn from_raw_full(ptr: *mut ffi::cairo_surface_t) -> Surface {
        assert!(!ptr.is_null());
        Surface(ptr, false)
    }

    pub fn to_raw_none(&self) -> *mut ffi::cairo_surface_t {
        self.0
    }

    pub fn create_similar(&self, content: Content, width: i32, height: i32) -> Surface {
        unsafe {
            Self::from_raw_full(ffi::cairo_surface_create_similar(self.0,
                                                                  content.into(),
                                                                  width,
                                                                  height))
        }
    }

    pub fn get_mime_data(&self, mime_type: &str) -> Option<Vec<u8>> {
        let mut data_ptr: *mut u8 = ptr::null_mut();
        let mut length = 0u64;
        unsafe {
            ffi::cairo_surface_get_mime_data(
                self.to_raw_none(),
                mime_type.to_glib_none().0,
                &mut data_ptr,
                &mut length,
            );
            if !data_ptr.is_null() && length != 0 {
                Some(slice::from_raw_parts(
                    data_ptr as *const u8,
                    length as usize,
                ).to_vec())
            } else {
                None
            }
        }
    }

    pub fn set_mime_data<T: AsRef<[u8]> + Send + 'static>(&self,
                                                          mime_type: &str,
                                                          slice: T) -> Result<(), Status> {
        let b = Box::new(slice);
        let (size, data) = {
            let slice = (*b).as_ref();
            (slice.len(), slice.as_ptr())
        };

        let user_data = Box::into_raw(b);

        let status = unsafe {
            ffi::cairo_surface_set_mime_data(
                self.to_raw_none(),
                mime_type.to_glib_none().0,
                data,
                size as u64,
                Some(unbox::<T>),
                user_data as *mut _)
        };

        match Status::from(status) {
            Status::Success => Ok(()),
            x => Err(x),
        }
    }

    pub fn supports_mime_type(&self, mime_type: &str) -> bool {
        unsafe {
            ffi::cairo_surface_supports_mime_type(self.0, mime_type.to_glib_none().0).as_bool()
        }
    }
}

#[cfg(feature = "use_glib")]
impl<'a> ToGlibPtr<'a, *mut ffi::cairo_surface_t> for Surface {
    type Storage = &'a Surface;

    #[inline]
    fn to_glib_none(&'a self) -> Stash<'a, *mut ffi::cairo_surface_t, Self> {
        Stash(self.to_raw_none(), self)
    }

    #[inline]
    fn to_glib_full(&self) -> *mut ffi::cairo_surface_t {
        unsafe {
            ffi::cairo_surface_reference(self.to_raw_none())
        }
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrNone<*mut ffi::cairo_surface_t> for Surface {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut ffi::cairo_surface_t) -> Surface {
        Self::from_raw_none(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrBorrow<*mut ffi::cairo_surface_t> for Surface {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut ffi::cairo_surface_t) -> Surface {
        Self::from_raw_borrow(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrFull<*mut ffi::cairo_surface_t> for Surface {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut ffi::cairo_surface_t) -> Surface {
        Self::from_raw_full(ptr)
    }
}

#[cfg(feature = "use_glib")]
gvalue_impl!(Surface, ffi::cairo_surface_t, ffi::gobject::cairo_gobject_surface_get_type);

impl AsRef<Surface> for Surface {
    fn as_ref(&self) -> &Surface {
        self
    }
}

impl Clone for Surface {
    fn clone(&self) -> Surface {
        unsafe { Self::from_raw_none(self.0) }
    }
}

impl Drop for Surface {
    fn drop(&mut self) {
        if !self.1 {
            unsafe { ffi::cairo_surface_destroy(self.0); }
        }
    }
}

pub trait SurfaceExt {
    fn flush(&self);
    fn finish(&self);
    fn get_type(&self) -> SurfaceType;
    fn status(&self) -> Status;
}

impl<O: AsRef<Surface>> SurfaceExt for O {
    fn flush(&self) {
        unsafe { ffi::cairo_surface_flush(self.as_ref().0); }
    }

    fn finish(&self) {
        unsafe { ffi::cairo_surface_finish(self.as_ref().0); }
    }

    fn get_type(&self) -> SurfaceType {
        unsafe { SurfaceType::from(ffi::cairo_surface_get_type(self.as_ref().0)) }
    }

    fn status(&self) -> Status {
        unsafe { Status::from(ffi::cairo_surface_status(self.as_ref().0)) }
    }
}

pub(crate) trait SurfacePriv {
    unsafe fn set_user_data<K, T>(&self, key: &K, data: Box<T>) -> Result<(), Status>;
}

impl<O: AsRef<Surface>> SurfacePriv for O {
    unsafe fn set_user_data<K, T>(&self, key: &K, data: Box<T>) -> Result<(), Status> {
        let ptr: *mut T = Box::into_raw(data);

        assert_eq!(mem::size_of::<*mut c_void>(), mem::size_of_val(&ptr));

        let status = ffi::cairo_surface_set_user_data(self.as_ref().0, key as *const _ as *mut _,
            ptr as *mut c_void, Some(unbox::<T>));
        match Status::from(status) {
            Status::Success => Ok(()),
            x => Err(x),
        }
    }
}

unsafe extern "C" fn unbox<T>(data: *mut c_void) {
    let data: Box<T> = Box::from_raw(data as *mut T);
    drop(data);
}

#[cfg(test)]
mod tests {
    use Format;
    use ImageSurface;
    use constants::MIME_TYPE_PNG;

    #[test]
    fn mime_data() {
        let surface = ImageSurface::create(Format::ARgb32, 500, 500).unwrap();
        let data = surface.get_mime_data(MIME_TYPE_PNG);
        /* Initially the data for any mime type has to be none */
        assert!(data.is_none());

        assert!(surface.set_mime_data(MIME_TYPE_PNG, &[1u8, 10u8]).is_ok());
        let data = surface.get_mime_data(MIME_TYPE_PNG).unwrap();
        assert_eq!(data, &[1u8, 10u8]);
    }
}
<commit_msg>surface: fix indentation<commit_after>// Copyright 2015-2016, The Gtk-rs 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>

use std::mem;
use std::slice;
use libc::c_void;

#[cfg(feature = "use_glib")]
use glib::translate::*;
use ffi;
use ::enums::{
    Content,
    Status,
    SurfaceType,
};

#[derive(Debug)]
pub struct Surface(*mut ffi::cairo_surface_t, bool);

impl Surface {
    pub unsafe fn from_raw_none(ptr: *mut ffi::cairo_surface_t) -> Surface {
        assert!(!ptr.is_null());
        ffi::cairo_surface_reference(ptr);
        Surface(ptr, false)
    }

    pub unsafe fn from_raw_borrow(ptr: *mut ffi::cairo_surface_t) -> Surface {
        assert!(!ptr.is_null());
        Surface(ptr, true)
    }

    pub unsafe fn from_raw_full(ptr: *mut ffi::cairo_surface_t) -> Surface {
        assert!(!ptr.is_null());
        Surface(ptr, false)
    }

    pub fn to_raw_none(&self) -> *mut ffi::cairo_surface_t {
        self.0
    }

    pub fn create_similar(&self, content: Content, width: i32, height: i32) -> Surface {
        unsafe {
            Self::from_raw_full(ffi::cairo_surface_create_similar(self.0,
                                                                  content.into(),
                                                                  width,
                                                                  height))
        }
    }

    pub fn get_mime_data(&self, mime_type: &str) -> Option<Vec<u8>> {
        let mut data_ptr: *mut u8 = ptr::null_mut();
        let mut length = 0u64;
        unsafe {
            ffi::cairo_surface_get_mime_data(
                self.to_raw_none(),
                mime_type.to_glib_none().0,
                &mut data_ptr,
                &mut length,
            );
            if !data_ptr.is_null() && length != 0 {
                Some(slice::from_raw_parts(
                    data_ptr as *const u8,
                    length as usize,
                ).to_vec())
            } else {
                None
            }
        }
    }

    pub fn set_mime_data<T: AsRef<[u8]> + Send + 'static>(
        &self,
        mime_type: &str,
        slice: T) -> Result<(), Status> {
        let b = Box::new(slice);
        let (size, data) = {
            let slice = (*b).as_ref();
            (slice.len(), slice.as_ptr())
        };

        let user_data = Box::into_raw(b);

        let status = unsafe {
                ffi::cairo_surface_set_mime_data(self.to_raw_none(),
                mime_type.to_glib_none().0,
                data,
                size as u64,
                Some(unbox::<T>),
                user_data as *mut _,
            )
        };

        match Status::from(status) {
            Status::Success => Ok(()),
            x => Err(x),
        }
    }

    pub fn supports_mime_type(&self, mime_type: &str) -> bool {
        unsafe {
            ffi::cairo_surface_supports_mime_type(self.0, mime_type.to_glib_none().0).as_bool()
        }
    }
}

#[cfg(feature = "use_glib")]
impl<'a> ToGlibPtr<'a, *mut ffi::cairo_surface_t> for Surface {
    type Storage = &'a Surface;

    #[inline]
    fn to_glib_none(&'a self) -> Stash<'a, *mut ffi::cairo_surface_t, Self> {
        Stash(self.to_raw_none(), self)
    }

    #[inline]
    fn to_glib_full(&self) -> *mut ffi::cairo_surface_t {
        unsafe {
            ffi::cairo_surface_reference(self.to_raw_none())
        }
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrNone<*mut ffi::cairo_surface_t> for Surface {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut ffi::cairo_surface_t) -> Surface {
        Self::from_raw_none(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrBorrow<*mut ffi::cairo_surface_t> for Surface {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut ffi::cairo_surface_t) -> Surface {
        Self::from_raw_borrow(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrFull<*mut ffi::cairo_surface_t> for Surface {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut ffi::cairo_surface_t) -> Surface {
        Self::from_raw_full(ptr)
    }
}

#[cfg(feature = "use_glib")]
gvalue_impl!(Surface, ffi::cairo_surface_t, ffi::gobject::cairo_gobject_surface_get_type);

impl AsRef<Surface> for Surface {
    fn as_ref(&self) -> &Surface {
        self
    }
}

impl Clone for Surface {
    fn clone(&self) -> Surface {
        unsafe { Self::from_raw_none(self.0) }
    }
}

impl Drop for Surface {
    fn drop(&mut self) {
        if !self.1 {
            unsafe { ffi::cairo_surface_destroy(self.0); }
        }
    }
}

pub trait SurfaceExt {
    fn flush(&self);
    fn finish(&self);
    fn get_type(&self) -> SurfaceType;
    fn status(&self) -> Status;
}

impl<O: AsRef<Surface>> SurfaceExt for O {
    fn flush(&self) {
        unsafe { ffi::cairo_surface_flush(self.as_ref().0); }
    }

    fn finish(&self) {
        unsafe { ffi::cairo_surface_finish(self.as_ref().0); }
    }

    fn get_type(&self) -> SurfaceType {
        unsafe { SurfaceType::from(ffi::cairo_surface_get_type(self.as_ref().0)) }
    }

    fn status(&self) -> Status {
        unsafe { Status::from(ffi::cairo_surface_status(self.as_ref().0)) }
    }
}

pub(crate) trait SurfacePriv {
    unsafe fn set_user_data<K, T>(&self, key: &K, data: Box<T>) -> Result<(), Status>;
}

impl<O: AsRef<Surface>> SurfacePriv for O {
    unsafe fn set_user_data<K, T>(&self, key: &K, data: Box<T>) -> Result<(), Status> {
        let ptr: *mut T = Box::into_raw(data);

        assert_eq!(mem::size_of::<*mut c_void>(), mem::size_of_val(&ptr));

        let status = ffi::cairo_surface_set_user_data(self.as_ref().0, key as *const _ as *mut _,
            ptr as *mut c_void, Some(unbox::<T>));
        match Status::from(status) {
            Status::Success => Ok(()),
            x => Err(x),
        }
    }
}

unsafe extern "C" fn unbox<T>(data: *mut c_void) {
    let data: Box<T> = Box::from_raw(data as *mut T);
    drop(data);
}

#[cfg(test)]
mod tests {
    use Format;
    use ImageSurface;
    use constants::MIME_TYPE_PNG;

    #[test]
    fn mime_data() {
        let surface = ImageSurface::create(Format::ARgb32, 500, 500).unwrap();
        let data = surface.get_mime_data(MIME_TYPE_PNG);
        /* Initially the data for any mime type has to be none */
        assert!(data.is_none());

        assert!(surface.set_mime_data(MIME_TYPE_PNG, &[1u8, 10u8]).is_ok());
        let data = surface.get_mime_data(MIME_TYPE_PNG).unwrap();
        assert_eq!(data, &[1u8, 10u8]);
    }
}
<|endoftext|>


<commit_before>use std::any::{Any, AnyMutRefExt, AnyRefExt};
use std::intrinsics::TypeId;
use std::collections::HashMap;

pub struct TypeMap {
    data: HashMap<TypeId, Box<Any + 'static>>
}

impl TypeMap {
    pub fn new() -> TypeMap {
        TypeMap { data: HashMap::new() }
    }

    pub fn find<T: 'static>(&self) -> Option<&T> {
        self.data.find(&TypeId::of::<T>()).and_then(|a| a.downcast_ref())
    }

    pub fn find_mut<T: 'static>(&mut self) -> Option<&mut T> {
        self.data.find_mut(&TypeId::of::<T>()).and_then(|a| a.downcast_mut())
    }

    pub fn insert<T: 'static>(&mut self, val: T) -> bool {
        self.data.insert(TypeId::of::<T>(), box val as Box<Any>)
    }

    pub fn remove<T: 'static>(&mut self) -> bool {
        self.data.remove(&TypeId::of::<T>())
    }

    pub fn contains<T: 'static>(&mut self) -> bool {
        self.data.contains_key(&TypeId::of::<T>())
    }
}

<commit_msg>Add a `pop` method to `TypeMap`<commit_after>use std::any::{Any, AnyMutRefExt, AnyRefExt};
use std::boxed::BoxAny;
use std::intrinsics::TypeId;
use std::collections::HashMap;

pub struct TypeMap {
    data: HashMap<TypeId, Box<Any + 'static>>
}

impl TypeMap {
    pub fn new() -> TypeMap {
        TypeMap { data: HashMap::new() }
    }

    pub fn find<T: 'static>(&self) -> Option<&T> {
        self.data.find(&TypeId::of::<T>()).and_then(|a| a.downcast_ref())
    }

    pub fn find_mut<T: 'static>(&mut self) -> Option<&mut T> {
        self.data.find_mut(&TypeId::of::<T>()).and_then(|a| a.downcast_mut())
    }

    pub fn insert<T: 'static>(&mut self, val: T) -> bool {
        self.data.insert(TypeId::of::<T>(), box val as Box<Any>)
    }

    pub fn remove<T: 'static>(&mut self) -> bool {
        self.data.remove(&TypeId::of::<T>())
    }

    pub fn contains<T: 'static>(&mut self) -> bool {
        self.data.contains_key(&TypeId::of::<T>())
    }

    pub fn pop<T: 'static>(&mut self) -> Option<T> {
        let data = match self.data.pop(&TypeId::of::<T>()) {
            Some(data) => data,
            None => return None,
        };
        Some(*data.downcast::<T>().unwrap())
    }
}

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

    #[test]
    fn smoke() {
        let mut m = TypeMap::new();
        assert!(m.insert(1i));
        assert_eq!(*m.find::<int>().unwrap(), 1);
        assert_eq!(*m.find_mut::<int>().unwrap(), 1);
        assert!(!m.insert(2i));
        assert!(m.remove::<int>());
        assert!(!m.contains::<int>());
        assert!(m.insert(4i));
        assert_eq!(m.pop::<int>().unwrap(), 4);
    }
}

<|endoftext|>


<commit_before>// Copyright 2013-2016, The Gtk-rs 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>

//! `Variant` binding and helper traits.
//!
//! [`Variant`](struct.Variant.html) is an immutable dynamically-typed generic
//! container. Its type and value are defined at construction and never change.
//!
//! `Variant` types are described by [`VariantType`](../struct.VariantType.html)
//! "type strings".
//!
//! Although `GVariant` supports arbitrarily complex types, this binding is
//! currently limited to the basic ones: `bool`, `u8`, `i16`, `u16`, `i32`,
//! `u32`, `i64`, `u64`, `f64` and `&str`/`String`.
//!
//! # Examples
//!
//! ```
//! use glib::prelude::*; // or `use gtk::prelude::*;`
//! use glib::Variant;
//!
//! // Using the `ToVariant` trait.
//! let num = 10.to_variant();
//!
//! // `is` tests the type of the value.
//! assert!(num.is::<i32>());
//!
//! // `get` tries to extract the value.
//! assert_eq!(num.get::<i32>(), Some(10));
//! assert_eq!(num.get::<u32>(), None);
//!
//! // `Variant` implements `From`
//! let hello = Variant::from("Hello!");
//!
//! // `get_str` tries to borrow a string slice.
//! assert_eq!(hello.get_str(), Some("Hello!"));
//! assert_eq!(num.get_str(), None);
//! ```

use bytes::Bytes;
use glib_sys;
use gobject_sys;
use gstring::GString;
use std::borrow::Cow;
use std::cmp::{Eq, Ordering, PartialEq, PartialOrd};
use std::fmt;
use std::hash::{Hash, Hasher};
use std::slice;
use std::str;
use translate::*;
use value;
use StaticType;
use Type;
use Value;
use VariantTy;

glib_wrapper! {
    /// A generic immutable value capable of carrying various types.
    ///
    /// See the [module documentation](index.html) for more details.
    pub struct Variant(Shared<glib_sys::GVariant>);

    match fn {
        ref => |ptr| glib_sys::g_variant_ref_sink(ptr),
        unref => |ptr| glib_sys::g_variant_unref(ptr),
    }
}

impl StaticType for Variant {
    fn static_type() -> Type {
        Type::Variant
    }
}

#[doc(hidden)]
impl<'a> value::FromValueOptional<'a> for Variant {
    unsafe fn from_value_optional(value: &Value) -> Option<Self> {
        from_glib_full(gobject_sys::g_value_dup_variant(
            ToGlibPtr::to_glib_none(value).0,
        ))
    }
}

#[doc(hidden)]
impl value::SetValue for Variant {
    unsafe fn set_value(value: &mut Value, this: &Self) {
        gobject_sys::g_value_set_variant(
            ToGlibPtrMut::to_glib_none_mut(value).0,
            ToGlibPtr::<*mut glib_sys::GVariant>::to_glib_none(this).0,
        )
    }
}

#[doc(hidden)]
impl value::SetValueOptional for Variant {
    unsafe fn set_value_optional(value: &mut Value, this: Option<&Self>) {
        gobject_sys::g_value_set_variant(
            ToGlibPtrMut::to_glib_none_mut(value).0,
            ToGlibPtr::<*mut glib_sys::GVariant>::to_glib_none(&this).0,
        )
    }
}

impl Variant {
    /// Returns the type of the value.
    pub fn type_(&self) -> &VariantTy {
        unsafe { VariantTy::from_ptr(glib_sys::g_variant_get_type(self.to_glib_none().0)) }
    }

    /// Returns `true` if the type of the value corresponds to `T`.
    #[inline]
    pub fn is<T: StaticVariantType>(&self) -> bool {
        self.type_() == T::static_variant_type()
    }

    /// Tries to extract a value of type `T`.
    ///
    /// Returns `Some` if `T` matches the variant's type.
    #[inline]
    pub fn get<T: FromVariant>(&self) -> Option<T> {
        T::from_variant(self)
    }

    /// Tries to extract a `&str`.
    ///
    /// Returns `Some` if the variant has a string type (`s`, `o` or `g` type
    /// strings).
    pub fn get_str(&self) -> Option<&str> {
        unsafe {
            match self.type_().to_str() {
                "s" | "o" | "g" => {
                    let mut len = 0;
                    let ptr = glib_sys::g_variant_get_string(self.to_glib_none().0, &mut len);
                    let ret = str::from_utf8_unchecked(slice::from_raw_parts(
                        ptr as *const u8,
                        len as usize,
                    ));
                    Some(ret)
                }
                _ => None,
            }
        }
    }

    /// Constructs a new serialised-mode GVariant instance.
    pub fn new_from_bytes<T: StaticVariantType>(bytes: &Bytes) -> Self {
        unsafe {
            from_glib_none(glib_sys::g_variant_new_from_bytes(
                T::static_variant_type().as_ptr() as *const _,
                bytes.to_glib_none().0,
                false.to_glib(),
            ))
        }
    }

    /// Same as `new_from_bytes`, except checks on the passed data are skipped, which makes it a
    /// potentially unsafe function. You should not use this function on data from external sources.
    pub unsafe fn new_from_bytes_trusted<T: StaticVariantType>(bytes: &Bytes) -> Self {
        from_glib_none(glib_sys::g_variant_new_from_bytes(
            T::static_variant_type().as_ptr() as *const _,
            bytes.to_glib_none().0,
            true.to_glib(),
        ))
    }

    /// Returns the serialised form of a GVariant instance.
    pub fn get_data_as_bytes(&self) -> Bytes {
        unsafe { from_glib_full(glib_sys::g_variant_get_data_as_bytes(self.to_glib_none().0)) }
    }
}

unsafe impl Send for Variant {}
unsafe impl Sync for Variant {}

impl fmt::Debug for Variant {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Variant")
            .field("ptr", &self.to_glib_none().0)
            .field("type", &self.type_())
            .field("value", &self.to_string())
            .finish()
    }
}

impl fmt::Display for Variant {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let serialized: GString = unsafe {
            from_glib_full(glib_sys::g_variant_print(
                self.to_glib_none().0,
                false.to_glib(),
            ))
        };
        f.write_str(&serialized)
    }
}

impl PartialEq for Variant {
    fn eq(&self, other: &Self) -> bool {
        unsafe {
            from_glib(glib_sys::g_variant_equal(
                self.to_glib_none().0 as *const _,
                other.to_glib_none().0 as *const _,
            ))
        }
    }
}

impl Eq for Variant {}

impl PartialOrd for Variant {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        unsafe {
            if glib_sys::g_variant_classify(self.to_glib_none().0)
                != glib_sys::g_variant_classify(other.to_glib_none().0)
            {
                return None;
            }

            if glib_sys::g_variant_is_container(self.to_glib_none().0) != glib_sys::GFALSE {
                return None;
            }

            let res = glib_sys::g_variant_compare(
                self.to_glib_none().0 as *const _,
                other.to_glib_none().0 as *const _,
            );
            if res < 0 {
                Some(Ordering::Less)
            } else if res > 0 {
                Some(Ordering::Equal)
            } else {
                Some(Ordering::Greater)
            }
        }
    }
}

impl Hash for Variant {
    fn hash<H: Hasher>(&self, state: &mut H) {
        unsafe { state.write_u32(glib_sys::g_variant_hash(self.to_glib_none().0 as *const _)) }
    }
}

/// Converts to `Variant`.
pub trait ToVariant {
    /// Returns a `Variant` clone of `self`.
    fn to_variant(&self) -> Variant;
}

/// Extracts a value.
pub trait FromVariant: Sized + StaticVariantType {
    /// Tries to extract a value.
    ///
    /// Returns `Some` if the variant's type matches `Self`.
    fn from_variant(variant: &Variant) -> Option<Self>;
}

/// Returns `VariantType` of `Self`.
pub trait StaticVariantType {
    /// Returns the `VariantType` corresponding to `Self`.
    fn static_variant_type() -> Cow<'static, VariantTy>;
}

impl<'a, T: ?Sized + ToVariant> ToVariant for &'a T {
    fn to_variant(&self) -> Variant {
        <T as ToVariant>::to_variant(self)
    }
}

impl<'a, T: ?Sized + StaticVariantType> StaticVariantType for &'a T {
    fn static_variant_type() -> Cow<'static, VariantTy> {
        <T as StaticVariantType>::static_variant_type()
    }
}

macro_rules! impl_numeric {
    ($name:ty, $type_str:expr, $new_fn:ident, $get_fn:ident) => {
        impl StaticVariantType for $name {
            fn static_variant_type() -> Cow<'static, VariantTy> {
                unsafe { VariantTy::from_str_unchecked($type_str).into() }
            }
        }

        impl ToVariant for $name {
            fn to_variant(&self) -> Variant {
                unsafe { from_glib_none(glib_sys::$new_fn(*self)) }
            }
        }

        impl FromVariant for $name {
            fn from_variant(variant: &Variant) -> Option<Self> {
                unsafe {
                    if variant.is::<Self>() {
                        Some(glib_sys::$get_fn(variant.to_glib_none().0))
                    } else {
                        None
                    }
                }
            }
        }
    };
}

impl_numeric!(u8, "y", g_variant_new_byte, g_variant_get_byte);
impl_numeric!(i16, "n", g_variant_new_int16, g_variant_get_int16);
impl_numeric!(u16, "q", g_variant_new_uint16, g_variant_get_uint16);
impl_numeric!(i32, "i", g_variant_new_int32, g_variant_get_int32);
impl_numeric!(u32, "u", g_variant_new_uint32, g_variant_get_uint32);
impl_numeric!(i64, "x", g_variant_new_int64, g_variant_get_int64);
impl_numeric!(u64, "t", g_variant_new_uint64, g_variant_get_uint64);
impl_numeric!(f64, "d", g_variant_new_double, g_variant_get_double);

impl StaticVariantType for bool {
    fn static_variant_type() -> Cow<'static, VariantTy> {
        unsafe { VariantTy::from_str_unchecked("b").into() }
    }
}

impl ToVariant for bool {
    fn to_variant(&self) -> Variant {
        unsafe { from_glib_none(glib_sys::g_variant_new_boolean(self.to_glib())) }
    }
}

impl FromVariant for bool {
    fn from_variant(variant: &Variant) -> Option<Self> {
        unsafe {
            if variant.is::<Self>() {
                Some(from_glib(glib_sys::g_variant_get_boolean(
                    variant.to_glib_none().0,
                )))
            } else {
                None
            }
        }
    }
}

impl StaticVariantType for String {
    fn static_variant_type() -> Cow<'static, VariantTy> {
        unsafe { VariantTy::from_str_unchecked("s").into() }
    }
}

impl ToVariant for String {
    fn to_variant(&self) -> Variant {
        self[..].to_variant()
    }
}

impl FromVariant for String {
    fn from_variant(variant: &Variant) -> Option<Self> {
        variant.get_str().map(String::from)
    }
}

impl StaticVariantType for str {
    fn static_variant_type() -> Cow<'static, VariantTy> {
        unsafe { VariantTy::from_str_unchecked("s").into() }
    }
}

impl ToVariant for str {
    fn to_variant(&self) -> Variant {
        unsafe { from_glib_none(glib_sys::g_variant_new_take_string(self.to_glib_full())) }
    }
}

impl<T: ToVariant> From<T> for Variant {
    fn from(value: T) -> Variant {
        value.to_variant()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::collections::HashSet;

    macro_rules! unsigned {
        ($name:ident, $ty:ident) => {
            #[test]
            fn $name() {
                let mut n = $ty::max_value();
                while n > 0 {
                    let v = Variant::from(n);
                    assert_eq!(v.get(), Some(n));
                    n /= 2;
                }
            }
        };
    }

    macro_rules! signed {
        ($name:ident, $ty:ident) => {
            #[test]
            fn $name() {
                let mut n = $ty::max_value();
                while n > 0 {
                    let v = Variant::from(n);
                    assert_eq!(v.get(), Some(n));
                    let v = Variant::from(-n);
                    assert_eq!(v.get(), Some(-n));
                    n /= 2;
                }
            }
        };
    }

    unsigned!(test_u8, u8);
    unsigned!(test_u16, u16);
    unsigned!(test_u32, u32);
    unsigned!(test_u64, u64);
    signed!(test_i16, i16);
    signed!(test_i32, i32);
    signed!(test_i64, i64);

    #[test]
    fn test_str() {
        let s = "this is a test";
        let v = Variant::from(s);
        assert_eq!(v.get_str(), Some(s));
    }

    #[test]
    fn test_string() {
        let s = String::from("this is a test");
        let v = Variant::from(s.clone());
        assert_eq!(v.get(), Some(s.clone()));
    }

    #[test]
    fn test_eq() {
        let v1 = Variant::from("this is a test");
        let v2 = Variant::from("this is a test");
        let v3 = Variant::from("test");
        assert_eq!(v1, v2);
        assert!(v1 != v3);
    }

    #[test]
    fn test_hash() {
        let v1 = Variant::from("this is a test");
        let v2 = Variant::from("this is a test");
        let v3 = Variant::from("test");
        let mut set = HashSet::new();
        set.insert(v1);
        assert!(set.contains(&v2));
        assert!(!set.contains(&v3));
    }
}
<commit_msg>variant: fix PartialOrd implementation<commit_after>// Copyright 2013-2016, The Gtk-rs 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>

//! `Variant` binding and helper traits.
//!
//! [`Variant`](struct.Variant.html) is an immutable dynamically-typed generic
//! container. Its type and value are defined at construction and never change.
//!
//! `Variant` types are described by [`VariantType`](../struct.VariantType.html)
//! "type strings".
//!
//! Although `GVariant` supports arbitrarily complex types, this binding is
//! currently limited to the basic ones: `bool`, `u8`, `i16`, `u16`, `i32`,
//! `u32`, `i64`, `u64`, `f64` and `&str`/`String`.
//!
//! # Examples
//!
//! ```
//! use glib::prelude::*; // or `use gtk::prelude::*;`
//! use glib::Variant;
//!
//! // Using the `ToVariant` trait.
//! let num = 10.to_variant();
//!
//! // `is` tests the type of the value.
//! assert!(num.is::<i32>());
//!
//! // `get` tries to extract the value.
//! assert_eq!(num.get::<i32>(), Some(10));
//! assert_eq!(num.get::<u32>(), None);
//!
//! // `Variant` implements `From`
//! let hello = Variant::from("Hello!");
//!
//! // `get_str` tries to borrow a string slice.
//! assert_eq!(hello.get_str(), Some("Hello!"));
//! assert_eq!(num.get_str(), None);
//! ```

use bytes::Bytes;
use glib_sys;
use gobject_sys;
use gstring::GString;
use std::borrow::Cow;
use std::cmp::{Eq, Ordering, PartialEq, PartialOrd};
use std::fmt;
use std::hash::{Hash, Hasher};
use std::slice;
use std::str;
use translate::*;
use value;
use StaticType;
use Type;
use Value;
use VariantTy;

glib_wrapper! {
    /// A generic immutable value capable of carrying various types.
    ///
    /// See the [module documentation](index.html) for more details.
    pub struct Variant(Shared<glib_sys::GVariant>);

    match fn {
        ref => |ptr| glib_sys::g_variant_ref_sink(ptr),
        unref => |ptr| glib_sys::g_variant_unref(ptr),
    }
}

impl StaticType for Variant {
    fn static_type() -> Type {
        Type::Variant
    }
}

#[doc(hidden)]
impl<'a> value::FromValueOptional<'a> for Variant {
    unsafe fn from_value_optional(value: &Value) -> Option<Self> {
        from_glib_full(gobject_sys::g_value_dup_variant(
            ToGlibPtr::to_glib_none(value).0,
        ))
    }
}

#[doc(hidden)]
impl value::SetValue for Variant {
    unsafe fn set_value(value: &mut Value, this: &Self) {
        gobject_sys::g_value_set_variant(
            ToGlibPtrMut::to_glib_none_mut(value).0,
            ToGlibPtr::<*mut glib_sys::GVariant>::to_glib_none(this).0,
        )
    }
}

#[doc(hidden)]
impl value::SetValueOptional for Variant {
    unsafe fn set_value_optional(value: &mut Value, this: Option<&Self>) {
        gobject_sys::g_value_set_variant(
            ToGlibPtrMut::to_glib_none_mut(value).0,
            ToGlibPtr::<*mut glib_sys::GVariant>::to_glib_none(&this).0,
        )
    }
}

impl Variant {
    /// Returns the type of the value.
    pub fn type_(&self) -> &VariantTy {
        unsafe { VariantTy::from_ptr(glib_sys::g_variant_get_type(self.to_glib_none().0)) }
    }

    /// Returns `true` if the type of the value corresponds to `T`.
    #[inline]
    pub fn is<T: StaticVariantType>(&self) -> bool {
        self.type_() == T::static_variant_type()
    }

    /// Tries to extract a value of type `T`.
    ///
    /// Returns `Some` if `T` matches the variant's type.
    #[inline]
    pub fn get<T: FromVariant>(&self) -> Option<T> {
        T::from_variant(self)
    }

    /// Tries to extract a `&str`.
    ///
    /// Returns `Some` if the variant has a string type (`s`, `o` or `g` type
    /// strings).
    pub fn get_str(&self) -> Option<&str> {
        unsafe {
            match self.type_().to_str() {
                "s" | "o" | "g" => {
                    let mut len = 0;
                    let ptr = glib_sys::g_variant_get_string(self.to_glib_none().0, &mut len);
                    let ret = str::from_utf8_unchecked(slice::from_raw_parts(
                        ptr as *const u8,
                        len as usize,
                    ));
                    Some(ret)
                }
                _ => None,
            }
        }
    }

    /// Constructs a new serialised-mode GVariant instance.
    pub fn new_from_bytes<T: StaticVariantType>(bytes: &Bytes) -> Self {
        unsafe {
            from_glib_none(glib_sys::g_variant_new_from_bytes(
                T::static_variant_type().as_ptr() as *const _,
                bytes.to_glib_none().0,
                false.to_glib(),
            ))
        }
    }

    /// Same as `new_from_bytes`, except checks on the passed data are skipped, which makes it a
    /// potentially unsafe function. You should not use this function on data from external sources.
    pub unsafe fn new_from_bytes_trusted<T: StaticVariantType>(bytes: &Bytes) -> Self {
        from_glib_none(glib_sys::g_variant_new_from_bytes(
            T::static_variant_type().as_ptr() as *const _,
            bytes.to_glib_none().0,
            true.to_glib(),
        ))
    }

    /// Returns the serialised form of a GVariant instance.
    pub fn get_data_as_bytes(&self) -> Bytes {
        unsafe { from_glib_full(glib_sys::g_variant_get_data_as_bytes(self.to_glib_none().0)) }
    }
}

unsafe impl Send for Variant {}
unsafe impl Sync for Variant {}

impl fmt::Debug for Variant {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Variant")
            .field("ptr", &self.to_glib_none().0)
            .field("type", &self.type_())
            .field("value", &self.to_string())
            .finish()
    }
}

impl fmt::Display for Variant {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let serialized: GString = unsafe {
            from_glib_full(glib_sys::g_variant_print(
                self.to_glib_none().0,
                false.to_glib(),
            ))
        };
        f.write_str(&serialized)
    }
}

impl PartialEq for Variant {
    fn eq(&self, other: &Self) -> bool {
        unsafe {
            from_glib(glib_sys::g_variant_equal(
                self.to_glib_none().0 as *const _,
                other.to_glib_none().0 as *const _,
            ))
        }
    }
}

impl Eq for Variant {}

impl PartialOrd for Variant {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        unsafe {
            if glib_sys::g_variant_classify(self.to_glib_none().0)
                != glib_sys::g_variant_classify(other.to_glib_none().0)
            {
                return None;
            }

            if glib_sys::g_variant_is_container(self.to_glib_none().0) != glib_sys::GFALSE {
                return None;
            }

            let res = glib_sys::g_variant_compare(
                self.to_glib_none().0 as *const _,
                other.to_glib_none().0 as *const _,
            );

            Some(res.cmp(&0))
        }
    }
}

impl Hash for Variant {
    fn hash<H: Hasher>(&self, state: &mut H) {
        unsafe { state.write_u32(glib_sys::g_variant_hash(self.to_glib_none().0 as *const _)) }
    }
}

/// Converts to `Variant`.
pub trait ToVariant {
    /// Returns a `Variant` clone of `self`.
    fn to_variant(&self) -> Variant;
}

/// Extracts a value.
pub trait FromVariant: Sized + StaticVariantType {
    /// Tries to extract a value.
    ///
    /// Returns `Some` if the variant's type matches `Self`.
    fn from_variant(variant: &Variant) -> Option<Self>;
}

/// Returns `VariantType` of `Self`.
pub trait StaticVariantType {
    /// Returns the `VariantType` corresponding to `Self`.
    fn static_variant_type() -> Cow<'static, VariantTy>;
}

impl<'a, T: ?Sized + ToVariant> ToVariant for &'a T {
    fn to_variant(&self) -> Variant {
        <T as ToVariant>::to_variant(self)
    }
}

impl<'a, T: ?Sized + StaticVariantType> StaticVariantType for &'a T {
    fn static_variant_type() -> Cow<'static, VariantTy> {
        <T as StaticVariantType>::static_variant_type()
    }
}

macro_rules! impl_numeric {
    ($name:ty, $type_str:expr, $new_fn:ident, $get_fn:ident) => {
        impl StaticVariantType for $name {
            fn static_variant_type() -> Cow<'static, VariantTy> {
                unsafe { VariantTy::from_str_unchecked($type_str).into() }
            }
        }

        impl ToVariant for $name {
            fn to_variant(&self) -> Variant {
                unsafe { from_glib_none(glib_sys::$new_fn(*self)) }
            }
        }

        impl FromVariant for $name {
            fn from_variant(variant: &Variant) -> Option<Self> {
                unsafe {
                    if variant.is::<Self>() {
                        Some(glib_sys::$get_fn(variant.to_glib_none().0))
                    } else {
                        None
                    }
                }
            }
        }
    };
}

impl_numeric!(u8, "y", g_variant_new_byte, g_variant_get_byte);
impl_numeric!(i16, "n", g_variant_new_int16, g_variant_get_int16);
impl_numeric!(u16, "q", g_variant_new_uint16, g_variant_get_uint16);
impl_numeric!(i32, "i", g_variant_new_int32, g_variant_get_int32);
impl_numeric!(u32, "u", g_variant_new_uint32, g_variant_get_uint32);
impl_numeric!(i64, "x", g_variant_new_int64, g_variant_get_int64);
impl_numeric!(u64, "t", g_variant_new_uint64, g_variant_get_uint64);
impl_numeric!(f64, "d", g_variant_new_double, g_variant_get_double);

impl StaticVariantType for bool {
    fn static_variant_type() -> Cow<'static, VariantTy> {
        unsafe { VariantTy::from_str_unchecked("b").into() }
    }
}

impl ToVariant for bool {
    fn to_variant(&self) -> Variant {
        unsafe { from_glib_none(glib_sys::g_variant_new_boolean(self.to_glib())) }
    }
}

impl FromVariant for bool {
    fn from_variant(variant: &Variant) -> Option<Self> {
        unsafe {
            if variant.is::<Self>() {
                Some(from_glib(glib_sys::g_variant_get_boolean(
                    variant.to_glib_none().0,
                )))
            } else {
                None
            }
        }
    }
}

impl StaticVariantType for String {
    fn static_variant_type() -> Cow<'static, VariantTy> {
        unsafe { VariantTy::from_str_unchecked("s").into() }
    }
}

impl ToVariant for String {
    fn to_variant(&self) -> Variant {
        self[..].to_variant()
    }
}

impl FromVariant for String {
    fn from_variant(variant: &Variant) -> Option<Self> {
        variant.get_str().map(String::from)
    }
}

impl StaticVariantType for str {
    fn static_variant_type() -> Cow<'static, VariantTy> {
        unsafe { VariantTy::from_str_unchecked("s").into() }
    }
}

impl ToVariant for str {
    fn to_variant(&self) -> Variant {
        unsafe { from_glib_none(glib_sys::g_variant_new_take_string(self.to_glib_full())) }
    }
}

impl<T: ToVariant> From<T> for Variant {
    fn from(value: T) -> Variant {
        value.to_variant()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::collections::HashSet;

    macro_rules! unsigned {
        ($name:ident, $ty:ident) => {
            #[test]
            fn $name() {
                let mut n = $ty::max_value();
                while n > 0 {
                    let v = Variant::from(n);
                    assert_eq!(v.get(), Some(n));
                    n /= 2;
                }
            }
        };
    }

    macro_rules! signed {
        ($name:ident, $ty:ident) => {
            #[test]
            fn $name() {
                let mut n = $ty::max_value();
                while n > 0 {
                    let v = Variant::from(n);
                    assert_eq!(v.get(), Some(n));
                    let v = Variant::from(-n);
                    assert_eq!(v.get(), Some(-n));
                    n /= 2;
                }
            }
        };
    }

    unsigned!(test_u8, u8);
    unsigned!(test_u16, u16);
    unsigned!(test_u32, u32);
    unsigned!(test_u64, u64);
    signed!(test_i16, i16);
    signed!(test_i32, i32);
    signed!(test_i64, i64);

    #[test]
    fn test_str() {
        let s = "this is a test";
        let v = Variant::from(s);
        assert_eq!(v.get_str(), Some(s));
    }

    #[test]
    fn test_string() {
        let s = String::from("this is a test");
        let v = Variant::from(s.clone());
        assert_eq!(v.get(), Some(s.clone()));
    }

    #[test]
    fn test_eq() {
        let v1 = Variant::from("this is a test");
        let v2 = Variant::from("this is a test");
        let v3 = Variant::from("test");
        assert_eq!(v1, v2);
        assert!(v1 != v3);
    }

    #[test]
    fn test_hash() {
        let v1 = Variant::from("this is a test");
        let v2 = Variant::from("this is a test");
        let v3 = Variant::from("test");
        let mut set = HashSet::new();
        set.insert(v1);
        assert!(set.contains(&v2));
        assert!(!set.contains(&v3));
    }
}
<|endoftext|>


<commit_before>
//! Various methods for computing with vectors.

use {Matrix2d, Ray, Vec2d, Rectangle, RoundRectangle};

/// Multiplies two matrices.
#[inline(always)]
pub fn multiply(m: &[f64, ..6], b: &[f64, ..6]) -> Matrix2d {
    [m[0]*b[0]+m[1]*b[3]+m[2]*0.0,  m[0]*b[1]+m[1]*b[4]+m[2]*0.0,  m[0]*b[2]+m[1]*b[5]+m[2]*1.0,
     m[3]*b[0]+m[4]*b[3]+m[5]*0.0,  m[3]*b[1]+m[4]*b[4]+m[5]*0.0,  m[3]*b[2]+m[4]*b[5]+m[5]*1.0]
}

/// Creates a translation matrix.
#[inline(always)]
pub fn translate(x: f64, y: f64) -> Matrix2d {
    [1.0, 0.0, x,
     0.0, 1.0, y]
}

/// Creates a rotation matrix.
#[inline(always)]
pub fn rotate_radians(angle: f64) -> Matrix2d {
    let c = angle.cos();
    let s = angle.sin();
    [c, s, 0.0,
    -s, c, 0.0]
}

/// Create a scale matrix.
#[inline(always)]
pub fn scale(sx: f64, sy: f64) -> Matrix2d {
    [sx, 0.0, 0.0,
     0.0, sy, 0.0]
}

/// Create a shear matrix.
#[inline(always)]
pub fn shear(sx: f64, sy: f64) -> Matrix2d {
    [1.0, sx, 0.0,
     sy, 1.0, 0.0]
}

/// Compute the shortest vector from point to ray.
/// A ray stores starting point and directional vector.
#[inline(always)]
pub fn separation(ray: Ray, x: f64, y: f64) -> Vec2d {
    // Get the directional vector.
    let (dir_x, dir_y) = (ray[2], ray[3]);
    // Get displacement vector from point.
    let (dx, dy) = (ray[0] - x, ray[1] - y);
    // Compute the component of position in ray direction.
    let dot = dir_x * x + dir_y * y;
    // The directional vector multiplied with the dot gives us a parallel vector.
    // When we subtract this from the displacement we get a vector normal to the ray.
    // This is the shortest vector from the point to the ray.
    [dx - dot * dir_x, dy - dot * dir_y]
}

/// Returns the least separation out of four.
/// Each seperation can be computed using `separation` function.
/// The separation returned can be used to solve collision of rectangles.
#[inline(always)]
pub fn least_separation_4(sep1: Vec2d, sep2: Vec2d, sep3: Vec2d, sep4: Vec2d) -> Vec2d {
    let dot1 = sep1[0] * sep1[0] + sep1[1] * sep1[1];
    let dot2 = sep2[0] * sep2[0] + sep2[1] * sep2[1];
    let dot3 = sep3[0] * sep3[0] + sep3[1] * sep3[1];
    let dot4 = sep4[0] * sep4[0] + sep4[1] * sep4[1];
    // Search for the smallest dot product.
    if dot1 < dot2 {
        if dot3 < dot4 {
            if dot1 < dot3 { sep1 } else { sep3 }
        } else {
            if dot1 < dot4 { sep1 } else { sep4 }
        }
    } else {
        if dot3 < dot4 {
            if dot2 < dot3 { sep2 } else { sep3 }
        } else {
            if dot2 < dot4 { sep2 } else { sep4 }
        }
    }
}

/// Shrinks a rectangle by a factor on all sides.
#[inline(always)]
pub fn margin_rectangle(rect: &Rectangle, m: f64) -> Rectangle {
    [rect[0] + m, rect[1] + m, rect[2] - 2.0 * m, rect[3] - 2.0 * m]
}

/// Shrinks a rectangle by a factor on all sides.
#[inline(always)]
pub fn margin_round_rectangle(rect: &RoundRectangle, m: f64) -> RoundRectangle {
    [rect[0] + m, rect[1] + m, rect[2] - 2.0 * m, rect[3] - 2.0 * m, rect[4]]
}

/// Computes a relative rectangle using the rectangle as a tile.
#[inline(always)]
pub fn relative_rectangle(rect: &Rectangle, x: f64, y: f64) -> Rectangle {
    [rect[0] + x * rect[2], rect[1] + y * rect[3], rect[2], rect[3]]
}

/// Computes a relative round rectangle using the round rectangle as a tile.
#[inline(always)]
pub fn relative_round_rectangle(rect: &RoundRectangle, x: f64, y: f64) -> RoundRectangle {
    [rect[0] + x * rect[2], rect[1] + y * rect[3], rect[2], rect[3], rect[4]]
}

<commit_msg>Fixed bug in margin<commit_after>
//! Various methods for computing with vectors.

use {Matrix2d, Ray, Vec2d, Rectangle, RoundRectangle};

/// Multiplies two matrices.
#[inline(always)]
pub fn multiply(m: &[f64, ..6], b: &[f64, ..6]) -> Matrix2d {
    [m[0]*b[0]+m[1]*b[3]+m[2]*0.0,  m[0]*b[1]+m[1]*b[4]+m[2]*0.0,  m[0]*b[2]+m[1]*b[5]+m[2]*1.0,
     m[3]*b[0]+m[4]*b[3]+m[5]*0.0,  m[3]*b[1]+m[4]*b[4]+m[5]*0.0,  m[3]*b[2]+m[4]*b[5]+m[5]*1.0]
}

/// Creates a translation matrix.
#[inline(always)]
pub fn translate(x: f64, y: f64) -> Matrix2d {
    [1.0, 0.0, x,
     0.0, 1.0, y]
}

/// Creates a rotation matrix.
#[inline(always)]
pub fn rotate_radians(angle: f64) -> Matrix2d {
    let c = angle.cos();
    let s = angle.sin();
    [c, s, 0.0,
    -s, c, 0.0]
}

/// Create a scale matrix.
#[inline(always)]
pub fn scale(sx: f64, sy: f64) -> Matrix2d {
    [sx, 0.0, 0.0,
     0.0, sy, 0.0]
}

/// Create a shear matrix.
#[inline(always)]
pub fn shear(sx: f64, sy: f64) -> Matrix2d {
    [1.0, sx, 0.0,
     sy, 1.0, 0.0]
}

/// Compute the shortest vector from point to ray.
/// A ray stores starting point and directional vector.
#[inline(always)]
pub fn separation(ray: Ray, x: f64, y: f64) -> Vec2d {
    // Get the directional vector.
    let (dir_x, dir_y) = (ray[2], ray[3]);
    // Get displacement vector from point.
    let (dx, dy) = (ray[0] - x, ray[1] - y);
    // Compute the component of position in ray direction.
    let dot = dir_x * x + dir_y * y;
    // The directional vector multiplied with the dot gives us a parallel vector.
    // When we subtract this from the displacement we get a vector normal to the ray.
    // This is the shortest vector from the point to the ray.
    [dx - dot * dir_x, dy - dot * dir_y]
}

/// Returns the least separation out of four.
/// Each seperation can be computed using `separation` function.
/// The separation returned can be used to solve collision of rectangles.
#[inline(always)]
pub fn least_separation_4(sep1: Vec2d, sep2: Vec2d, sep3: Vec2d, sep4: Vec2d) -> Vec2d {
    let dot1 = sep1[0] * sep1[0] + sep1[1] * sep1[1];
    let dot2 = sep2[0] * sep2[0] + sep2[1] * sep2[1];
    let dot3 = sep3[0] * sep3[0] + sep3[1] * sep3[1];
    let dot4 = sep4[0] * sep4[0] + sep4[1] * sep4[1];
    // Search for the smallest dot product.
    if dot1 < dot2 {
        if dot3 < dot4 {
            if dot1 < dot3 { sep1 } else { sep3 }
        } else {
            if dot1 < dot4 { sep1 } else { sep4 }
        }
    } else {
        if dot3 < dot4 {
            if dot2 < dot3 { sep2 } else { sep3 }
        } else {
            if dot2 < dot4 { sep2 } else { sep4 }
        }
    }
}

/// Shrinks a rectangle by a factor on all sides.
#[inline(always)]
pub fn margin_rectangle(rect: &Rectangle, m: f64) -> Rectangle {
    let w = rect[2] - 2.0 * m;
    let h = rect[3] - 2.0 * m;
    let (x, w) = if w < 0.0 { (rect[0] + 0.5 * rect[2], 0.0) } else { (rect[0] + m, w) };
    let (y, h) = if h < 0.0 { (rect[1] + 0.5 * rect[3], 0.0) } else { (rect[1] + m, h) };
    [x, y, w, h]
}

/// Shrinks a rectangle by a factor on all sides.
#[inline(always)]
pub fn margin_round_rectangle(rect: &RoundRectangle, m: f64) -> RoundRectangle {
    let w = rect[2] - 2.0 * m;
    let h = rect[3] - 2.0 * m;
    let (x, w) = if w < 0.0 { (rect[0] + 0.5 * rect[2], 0.0) } else { (rect[0] + m, w) };
    let (y, h) = if h < 0.0 { (rect[1] + 0.5 * rect[3], 0.0) } else { (rect[1] + m, h) };
    [x, y, w, h, rect[4]]
}

/// Computes a relative rectangle using the rectangle as a tile.
#[inline(always)]
pub fn relative_rectangle(rect: &Rectangle, x: f64, y: f64) -> Rectangle {
    [rect[0] + x * rect[2], rect[1] + y * rect[3], rect[2], rect[3]]
}

/// Computes a relative round rectangle using the round rectangle as a tile.
#[inline(always)]
pub fn relative_round_rectangle(rect: &RoundRectangle, x: f64, y: f64) -> RoundRectangle {
    [rect[0] + x * rect[2], rect[1] + y * rect[3], rect[2], rect[3], rect[4]]
}

<|endoftext|>


<commit_before>use std::ops;

///A 3D Vector with x, y, z coordinates: Vector3
#[derive(PartialEq, Debug)]
pub struct Vector3 {
    x: f32,
    y: f32,
    z: f32,
}

///A 3D Point with x, y and z coordinates: Point3
#[derive(PartialEq, Debug)]
pub struct Point3 {
    x: f32,
    y: f32,
    z: f32,
}

impl Vector3 {
    ///Instantiates a new vector with to be defined values of x, y, z;
    pub fn new(x: f32, y: f32, z: f32) -> Vector3 {
        Vector3 {x: x, y: y, z: z}
    }

    ///Instantiates a new Vector3 from 2 Point3 (initial position, final position).
    ///The new vector is created as final - initial (Points)
    pub fn diff(origin: Point3, destination: Point3) -> Vector3 {
        Vector3 {x: destination.x - origin.x, y: destination.y - origin.y, z: destination.z - origin.z}
    }

    ///Defines a Vector with UP direction (y=1, x=0, z=0)
    pub fn UP() -> Vector3 {
        Vector3 {x: 0f32, y: 1f32, z: 0f32}
    }

    ///Defines a Vector with DOWN direction (y=-1, x=0, z=0)
    pub fn DOWN() -> Vector3 {
        Vector3 {x: 0f32, y: -1f32, z: 0f32}
    }

    ///Defines a Vector with RIGHT direction (y=0, x=1, z=0)
    pub fn RIGHT() -> Vector3 {
        Vector3 {x: 1f32, y: 0f32, z: 0f32}
    }

    ///Defines a Vector with LEFT direction (y=0, x=-1, z=0)
    pub fn LEFT() -> Vector3 {
        Vector3 {x: -1f32, y: 0f32, z: 0f32}
    }

    ///Defines a 3D Vector with x=1, y=1, z=1
    pub fn ONE() -> Vector3 {
        Vector3 {x: 1f32, y: 1f32, z: 1f32}
    }

    ///Defines a Modulus ZERO Vector (x=0, y=0, z=0)
    pub fn ZERO() -> Vector3 {
        Vector3 {x: 0f32, y: 0f32, z: 0f32}
    }

    ///Vector magnitude: the square root of the sum of each vector part to the power of 2
    pub fn magnitude(self) -> f32 {
        f32::sqrt(self.x.powi(2) + self.y.powi(2) + self.z.powi(2))
    }
}

impl ops::Add for Vector3 {
    type Output = Vector3;

    ///Implements the Vector3 '+' trait
    fn add(self, new_vec: Vector3) -> Vector3 {
        Vector3 {x: self.x + new_vec.x, y: self.y + new_vec.y, z: self.z + new_vec.z}
    }
}

impl ops::Mul<f32> for Vector3 {
    type Output = Vector3;

    ///Implements the scalar multiplication of a Vector3 with a f32. Other numbers should
    ///be passed with 'i as f32'
    fn mul(self, value: f32) -> Vector3 {
        Vector3 {x: self.x * value, y: self.y * value, z: self.z * value}
    }
}

impl ops::Mul<Vector3> for Vector3 {
    type Output = f32;

    ///Implements the dot product of 2 Vector3 as '*'.
    fn mul(self, new_vec: Vector3) -> f32 {
        self.x * new_vec.x + self.y * new_vec.y + self.z * new_vec.z
    }
}

impl ops::Sub for Vector3 {
    type Output = Vector3;

    ///Implements the Vector3 '-' trait
    fn sub(self, new_vec: Vector3) -> Vector3 {
        Vector3 {x: self.x - new_vec.x, y: self.y - new_vec.y, z: self.z - new_vec.z}
    }
}

impl Point3 {
    ///Instantiates a new Point3 with x, y and z.
    pub fn new(x: f32, y: f32, z: f32) -> Point3 {
        Point3 {x: x, y: y, z: z}
    }

    ///Creates a new Vector3 relative to position (0, 0, 0)
    pub fn to_vec(self) -> Vector3 {
        Vector3::diff(Point3::origin(), self)
    }

    ///Instantiates a Point3 with (0, 0, 0)
    fn origin() -> Point3 {
        Point3::new(0f32, 0f32, 0f32)
    }
}

impl ops::Add<Vector3> for Point3 {
    type Output = Point3;

    ///Overloads + for Points and Vectors: P + PQ = Q
    fn add(self, new_vec: Vector3) -> Point3 {
        Point3 {x: self.x + new_vec.x, y: self.y + new_vec.y, z: self.z + new_vec.z}
    }
}

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

    #[test]
    fn creates_vector3_with_parameters() {
        let actual = Vector3::new(1f32, 1f32, 1f32);
        let expected = Vector3 {x: 1f32, y: 1f32, z: 1f32};
        assert!(expected.x == actual.x &&
            expected.y == actual.y &&
            expected.z == actual.z);
    }

    #[test]
    fn creates_vector3_up() {
        let actual = Vector3::UP();
        assert!(actual.x == 0f32 &&
            actual.y == 1f32 &&
            actual.z == 0f32);
    }

    #[test]
    fn adds_right_and_left_vectors() {
         let actual = Vector3::RIGHT() + Vector3::LEFT();
         assert_eq!(actual.x, 0f32);
    }

    #[test]
    fn adds_right_and_up() {
        let actual = Vector3::RIGHT() + Vector3::UP();
        assert_eq!(actual.x, 1f32);
        assert_eq!(actual.y, 1f32);
        assert_eq!(actual.z, 0f32);
    }

    #[test]
    fn mult_one_by_3() {
        let actual = Vector3::ONE() * 3f32;
        assert_eq!(actual.x, 3f32);
        assert_eq!(actual.y, 3f32);
        assert_eq!(actual.z, 3f32);
    }

    #[test]
    fn sub_right_from_one() {
        let actual = Vector3::ONE() - Vector3::RIGHT();
        assert_eq!(actual.x, 0f32);
        assert_eq!(actual.y, 1f32);
        assert_eq!(actual.z, 1f32);
    }

    #[test]
    fn magnitude_of_vector() {
        let vec = Vector3 {x: 1f32, y: 2f32, z: 3f32};
        assert_eq!(vec.magnitude(), 3.7416575f32);
    }

    #[test]
    fn magnitude_of_vector_is_positive() {
        let vec = Vector3 {x: -3f32, y: 4f32, z: 5f32};
        assert!(vec.magnitude() >= 0f32);
    }

    #[test]
    fn dot_product() {
        let vec1 = Vector3 {x: 2f32, y: 1f32, z: 2f32};
        let vec2 = Vector3 {x: 1f32, y: 2f32, z: 3f32};
        let actual = vec1 * vec2;
        let expected = 10f32;
        assert_eq!(actual, expected);
    }

    #[test]
    fn constructs_vector3_from_points3() {
        let vec = Vector3::diff(Point3::new(1f32, -1f32, 2f32),
            Point3::new(2f32, 3f32, 2f32));
        assert_eq!(vec.x, 1f32);
        assert_eq!(vec.y, 4f32);
        assert_eq!(vec.z, 0f32);
    }

    #[test]
    fn creates_vector_from_point3() {
        let point = Point3::new(1f32, 1f32, 1f32);
        let actual = point.to_vec();
        let expected = Vector3::ONE();
        assert!(expected.x == actual.x &&
            expected.y == actual.y &&
            expected.z == actual.z);
    }

    #[test]
    fn point_add_vector_result_new_point() {
        let point = Point3::origin();
        let vec = Vector3::ONE();
        let actual = point + vec;
        assert_eq!(actual.x, 1f32);
        assert_eq!(actual.y, 1f32);
        assert_eq!(actual.z, 1f32);
    }
}
<commit_msg>cross product for vecor 3<commit_after>use std::ops;

///A 3D Vector with x, y, z coordinates: Vector3
#[derive(PartialEq, Debug)]
pub struct Vector3 {
    x: f32,
    y: f32,
    z: f32,
}

///A 3D Point with x, y and z coordinates: Point3
#[derive(PartialEq, Debug)]
pub struct Point3 {
    x: f32,
    y: f32,
    z: f32,
}

impl Vector3 {
    ///Instantiates a new vector with to be defined values of x, y, z;
    pub fn new(x: f32, y: f32, z: f32) -> Vector3 {
        Vector3 {x: x, y: y, z: z}
    }

    ///Instantiates a new Vector3 from 2 Point3 (initial position, final position).
    ///The new vector is created as final - initial (Points)
    pub fn diff(origin: Point3, destination: Point3) -> Vector3 {
        Vector3 {x: destination.x - origin.x, y: destination.y - origin.y, z: destination.z - origin.z}
    }

    ///Defines a Vector with UP direction (y=1, x=0, z=0)
    pub fn UP() -> Vector3 {
        Vector3 {x: 0f32, y: 1f32, z: 0f32}
    }

    ///Defines a Vector with DOWN direction (y=-1, x=0, z=0)
    pub fn DOWN() -> Vector3 {
        Vector3 {x: 0f32, y: -1f32, z: 0f32}
    }

    ///Defines a Vector with RIGHT direction (y=0, x=1, z=0)
    pub fn RIGHT() -> Vector3 {
        Vector3 {x: 1f32, y: 0f32, z: 0f32}
    }

    ///Defines a Vector with LEFT direction (y=0, x=-1, z=0)
    pub fn LEFT() -> Vector3 {
        Vector3 {x: -1f32, y: 0f32, z: 0f32}
    }

    ///Defines a 3D Vector with x=1, y=1, z=1
    pub fn ONE() -> Vector3 {
        Vector3 {x: 1f32, y: 1f32, z: 1f32}
    }

    ///Defines a Modulus ZERO Vector (x=0, y=0, z=0)
    pub fn ZERO() -> Vector3 {
        Vector3 {x: 0f32, y: 0f32, z: 0f32}
    }

    ///Vector magnitude: the square root of the sum of each vector part to the power of 2
    pub fn magnitude(self) -> f32 {
        f32::sqrt(self.x.powi(2) + self.y.powi(2) + self.z.powi(2))
    }

    ///Crooss product between two vectors 3.
    pub fn x(self, vec: Vector3) -> Vector3 {
        Vector3 {x: self.y * vec.z - self.z * vec.y,
                y: self.z * vec.x - self.x * vec.z,
                z: self.x * vec.y - self.y * vec.x}
    }
}

impl ops::Add for Vector3 {
    type Output = Vector3;

    ///Implements the Vector3 '+' trait
    fn add(self, new_vec: Vector3) -> Vector3 {
        Vector3 {x: self.x + new_vec.x, y: self.y + new_vec.y, z: self.z + new_vec.z}
    }
}

impl ops::Mul<f32> for Vector3 {
    type Output = Vector3;

    ///Implements the scalar multiplication of a Vector3 with a f32. Other numbers should
    ///be passed with 'i as f32'
    fn mul(self, value: f32) -> Vector3 {
        Vector3 {x: self.x * value, y: self.y * value, z: self.z * value}
    }
}

impl ops::Mul<Vector3> for Vector3 {
    type Output = f32;

    ///Implements the dot product of 2 Vector3 as '*'.
    fn mul(self, new_vec: Vector3) -> f32 {
        self.x * new_vec.x + self.y * new_vec.y + self.z * new_vec.z
    }
}

impl ops::Sub for Vector3 {
    type Output = Vector3;

    ///Implements the Vector3 '-' trait
    fn sub(self, new_vec: Vector3) -> Vector3 {
        Vector3 {x: self.x - new_vec.x, y: self.y - new_vec.y, z: self.z - new_vec.z}
    }
}

impl Point3 {
    ///Instantiates a new Point3 with x, y and z.
    pub fn new(x: f32, y: f32, z: f32) -> Point3 {
        Point3 {x: x, y: y, z: z}
    }

    ///Creates a new Vector3 relative to position (0, 0, 0)
    pub fn to_vec(self) -> Vector3 {
        Vector3::diff(Point3::origin(), self)
    }

    ///Instantiates a Point3 with (0, 0, 0)
    fn origin() -> Point3 {
        Point3::new(0f32, 0f32, 0f32)
    }
}

impl ops::Add<Vector3> for Point3 {
    type Output = Point3;

    ///Overloads + for Points and Vectors: P + PQ = Q
    fn add(self, new_vec: Vector3) -> Point3 {
        Point3 {x: self.x + new_vec.x, y: self.y + new_vec.y, z: self.z + new_vec.z}
    }
}

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

    #[test]
    fn creates_vector3_with_parameters() {
        let actual = Vector3::new(1f32, 1f32, 1f32);
        let expected = Vector3 {x: 1f32, y: 1f32, z: 1f32};
        assert!(expected.x == actual.x &&
            expected.y == actual.y &&
            expected.z == actual.z);
    }

    #[test]
    fn creates_vector3_up() {
        let actual = Vector3::UP();
        assert!(actual.x == 0f32 &&
            actual.y == 1f32 &&
            actual.z == 0f32);
    }

    #[test]
    fn adds_right_and_left_vectors() {
         let actual = Vector3::RIGHT() + Vector3::LEFT();
         assert_eq!(actual.x, 0f32);
    }

    #[test]
    fn adds_right_and_up() {
        let actual = Vector3::RIGHT() + Vector3::UP();
        assert_eq!(actual.x, 1f32);
        assert_eq!(actual.y, 1f32);
        assert_eq!(actual.z, 0f32);
    }

    #[test]
    fn mult_one_by_3() {
        let actual = Vector3::ONE() * 3f32;
        assert_eq!(actual.x, 3f32);
        assert_eq!(actual.y, 3f32);
        assert_eq!(actual.z, 3f32);
    }

    #[test]
    fn sub_right_from_one() {
        let actual = Vector3::ONE() - Vector3::RIGHT();
        assert_eq!(actual.x, 0f32);
        assert_eq!(actual.y, 1f32);
        assert_eq!(actual.z, 1f32);
    }

    #[test]
    fn magnitude_of_vector() {
        let vec = Vector3 {x: 1f32, y: 2f32, z: 3f32};
        assert_eq!(vec.magnitude(), 3.7416575f32);
    }

    #[test]
    fn magnitude_of_vector_is_positive() {
        let vec = Vector3 {x: -3f32, y: 4f32, z: 5f32};
        assert!(vec.magnitude() >= 0f32);
    }

    #[test]
    fn dot_product() {
        let vec1 = Vector3 {x: 2f32, y: 1f32, z: 2f32};
        let vec2 = Vector3 {x: 1f32, y: 2f32, z: 3f32};
        let actual = vec1 * vec2;
        let expected = 10f32;
        assert_eq!(actual, expected);
    }

    #[test]
    fn constructs_vector3_from_points3() {
        let vec = Vector3::diff(Point3::new(1f32, -1f32, 2f32),
            Point3::new(2f32, 3f32, 2f32));
        assert_eq!(vec.x, 1f32);
        assert_eq!(vec.y, 4f32);
        assert_eq!(vec.z, 0f32);
    }

    #[test]
    fn creates_vector_from_point3() {
        let point = Point3::new(1f32, 1f32, 1f32);
        let actual = point.to_vec();
        let expected = Vector3::ONE();
        assert!(expected.x == actual.x &&
            expected.y == actual.y &&
            expected.z == actual.z);
    }

    #[test]
    fn point_add_vector_result_new_point() {
        let point = Point3::origin();
        let vec = Vector3::ONE();
        let actual = point + vec;
        assert_eq!(actual.x, 1f32);
        assert_eq!(actual.y, 1f32);
        assert_eq!(actual.z, 1f32);
    }

    #[test]
    fn cross_product_between_2_vectors() {
        let vec1 = Vector3::new(1f32, 2f32, 3f32);
        let actual = vec1.x(Vector3::new(2f32, 3f32, 4f32));
        let expected = Vector3::new(-1f32, 2f32, -1f32);
        assert_eq!(actual.x, expected.x);
        assert_eq!(actual.y, expected.y);
        assert_eq!(actual.z, expected.z);
    }
}
<|endoftext|>