<commit_before>use approx::{AbsDiffEq, RelativeEq, UlpsEq};
use std::fmt;
use std::hash;
#[cfg(feature = "abomonation-serialize")]
use std::io::{Result as IOResult, Write};
use std::marker::PhantomData;

#[cfg(feature = "serde-serialize")]
use serde::{Deserialize, Serialize};

#[cfg(feature = "abomonation-serialize")]
use abomonation::Abomonation;

use alga::general::{Real, SubsetOf};
use alga::linear::Rotation;

use base::allocator::Allocator;
use base::dimension::{DimName, DimNameAdd, DimNameSum, U1};
use base::storage::Owned;
use base::{DefaultAllocator, MatrixN};
use geometry::{Point, Translation};

/// A direct isometry, i.e., a rotation followed by a translation, aka. a rigid-body motion, aka. an element of a Special Euclidean (SE) group.
#[repr(C)]
#[derive(Debug)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
#[cfg_attr(
    feature = "serde-serialize",
    serde(bound(
        serialize = "R: Serialize,
                     DefaultAllocator: Allocator<N, D>,
                     Owned<N, D>: Serialize"
    ))
)]
#[cfg_attr(
    feature = "serde-serialize",
    serde(bound(
        deserialize = "R: Deserialize<'de>,
                       DefaultAllocator: Allocator<N, D>,
                       Owned<N, D>: Deserialize<'de>"
    ))
)]
pub struct Isometry<N: Real, D: DimName, R>
where DefaultAllocator: Allocator<N, D>
{
    /// The pure rotational part of this isometry.
    pub rotation: R,
    /// The pure translational part of this isometry.
    pub translation: Translation<N, D>,

    // One dummy private field just to prevent explicit construction.
    #[cfg_attr(
        feature = "serde-serialize",
        serde(skip_serializing, skip_deserializing)
    )]
    _noconstruct: PhantomData<N>,
}

#[cfg(feature = "abomonation-serialize")]
impl<N, D, R> Abomonation for Isometry<N, D, R>
where
    N: Real,
    D: DimName,
    R: Abomonation,
    Translation<N, D>: Abomonation,
    DefaultAllocator: Allocator<N, D>,
{
    unsafe fn entomb<W: Write>(&self, writer: &mut W) -> IOResult<()> {
        self.rotation.entomb(writer)?;
        self.translation.entomb(writer)
    }

    fn extent(&self) -> usize {
        self.rotation.extent() + self.translation.extent()
    }

    unsafe fn exhume<'a, 'b>(&'a mut self, bytes: &'b mut [u8]) -> Option<&'b mut [u8]> {
        self.rotation
            .exhume(bytes)
            .and_then(|bytes| self.translation.exhume(bytes))
    }
}

impl<N: Real + hash::Hash, D: DimName + hash::Hash, R: hash::Hash> hash::Hash for Isometry<N, D, R>
where
    DefaultAllocator: Allocator<N, D>,
    Owned<N, D>: hash::Hash,
{
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        self.translation.hash(state);
        self.rotation.hash(state);
    }
}

impl<N: Real, D: DimName + Copy, R: Rotation<Point<N, D>> + Copy> Copy for Isometry<N, D, R>
where
    DefaultAllocator: Allocator<N, D>,
    Owned<N, D>: Copy,
{}

impl<N: Real, D: DimName, R: Rotation<Point<N, D>> + Clone> Clone for Isometry<N, D, R>
where DefaultAllocator: Allocator<N, D>
{
    #[inline]
    fn clone(&self) -> Self {
        Isometry::from_parts(self.translation.clone(), self.rotation.clone())
    }
}

impl<N: Real, D: DimName, R: Rotation<Point<N, D>>> Isometry<N, D, R>
where DefaultAllocator: Allocator<N, D>
{
    /// Creates a new isometry from its rotational and translational parts.
    #[inline]
    pub fn from_parts(translation: Translation<N, D>, rotation: R) -> Isometry<N, D, R> {
        Isometry {
            rotation: rotation,
            translation: translation,
            _noconstruct: PhantomData,
        }
    }

    /// Inverts `self`.
    #[inline]
    pub fn inverse(&self) -> Isometry<N, D, R> {
        let mut res = self.clone();
        res.inverse_mut();
        res
    }

    /// Inverts `self`.
    #[inline]
    pub fn inverse_mut(&mut self) {
        self.rotation.inverse_mut();
        self.translation.inverse_mut();
        self.translation.vector = self.rotation.transform_vector(&self.translation.vector);
    }

    /// Appends to `self` the given translation in-place.
    #[inline]
    pub fn append_translation_mut(&mut self, t: &Translation<N, D>) {
        self.translation.vector += &t.vector
    }

    /// Appends to `self` the given rotation in-place.
    #[inline]
    pub fn append_rotation_mut(&mut self, r: &R) {
        self.rotation = self.rotation.append_rotation(&r);
        self.translation.vector = r.transform_vector(&self.translation.vector);
    }

    /// Appends in-place to `self` a rotation centered at the point `p`, i.e., the rotation that
    /// lets `p` invariant.
    #[inline]
    pub fn append_rotation_wrt_point_mut(&mut self, r: &R, p: &Point<N, D>) {
        self.translation.vector -= &p.coords;
        self.append_rotation_mut(r);
        self.translation.vector += &p.coords;
    }

    /// Appends in-place to `self` a rotation centered at the point with coordinates
    /// `self.translation`.
    #[inline]
    pub fn append_rotation_wrt_center_mut(&mut self, r: &R) {
        let center = Point::from_coordinates(self.translation.vector.clone());
        self.append_rotation_wrt_point_mut(r, &center)
    }
}

// NOTE: we don't require `R: Rotation<...>` here because this is not useful for the implementation
// and makes it hard to use it, e.g., for Transform × Isometry implementation.
// This is OK since all constructors of the isometry enforce the Rotation bound already (and
// explicit struct construction is prevented by the dummy ZST field).
impl<N: Real, D: DimName, R> Isometry<N, D, R>
where DefaultAllocator: Allocator<N, D>
{
    /// Converts this isometry into its equivalent homogeneous transformation matrix.
    #[inline]
    pub fn to_homogeneous(&self) -> MatrixN<N, DimNameSum<D, U1>>
    where
        D: DimNameAdd<U1>,
        R: SubsetOf<MatrixN<N, DimNameSum<D, U1>>>,
        DefaultAllocator: Allocator<N, DimNameSum<D, U1>, DimNameSum<D, U1>>,
    {
        let mut res: MatrixN<N, _> = ::convert_ref(&self.rotation);
        res.fixed_slice_mut::<D, U1>(0, D::dim())
            .copy_from(&self.translation.vector);

        res
    }
}

impl<N: Real, D: DimName, R> Eq for Isometry<N, D, R>
where
    R: Rotation<Point<N, D>> + Eq,
    DefaultAllocator: Allocator<N, D>,
{}

impl<N: Real, D: DimName, R> PartialEq for Isometry<N, D, R>
where
    R: Rotation<Point<N, D>> + PartialEq,
    DefaultAllocator: Allocator<N, D>,
{
    #[inline]
    fn eq(&self, right: &Isometry<N, D, R>) -> bool {
        self.translation == right.translation && self.rotation == right.rotation
    }
}

impl<N: Real, D: DimName, R> AbsDiffEq for Isometry<N, D, R>
where
    R: Rotation<Point<N, D>> + AbsDiffEq<Epsilon = N::Epsilon>,
    DefaultAllocator: Allocator<N, D>,
    N::Epsilon: Copy,
{
    type Epsilon = N::Epsilon;

    #[inline]
    fn default_epsilon() -> Self::Epsilon {
        N::default_epsilon()
    }

    #[inline]
    fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
        self.translation.abs_diff_eq(&other.translation, epsilon)
            && self.rotation.abs_diff_eq(&other.rotation, epsilon)
    }
}

impl<N: Real, D: DimName, R> RelativeEq for Isometry<N, D, R>
where
    R: Rotation<Point<N, D>> + RelativeEq<Epsilon = N::Epsilon>,
    DefaultAllocator: Allocator<N, D>,
    N::Epsilon: Copy,
{
    #[inline]
    fn default_max_relative() -> Self::Epsilon {
        N::default_max_relative()
    }

    #[inline]
    fn relative_eq(
        &self,
        other: &Self,
        epsilon: Self::Epsilon,
        max_relative: Self::Epsilon,
    ) -> bool
    {
        self.translation
            .relative_eq(&other.translation, epsilon, max_relative)
            && self
                .rotation
                .relative_eq(&other.rotation, epsilon, max_relative)
    }
}

impl<N: Real, D: DimName, R> UlpsEq for Isometry<N, D, R>
where
    R: Rotation<Point<N, D>> + UlpsEq<Epsilon = N::Epsilon>,
    DefaultAllocator: Allocator<N, D>,
    N::Epsilon: Copy,
{
    #[inline]
    fn default_max_ulps() -> u32 {
        N::default_max_ulps()
    }

    #[inline]
    fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
        self.translation
            .ulps_eq(&other.translation, epsilon, max_ulps)
            && self.rotation.ulps_eq(&other.rotation, epsilon, max_ulps)
    }
}

/*
 *
 * Display
 *
 */
impl<N: Real + fmt::Display, D: DimName, R> fmt::Display for Isometry<N, D, R>
where
    R: fmt::Display,
    DefaultAllocator: Allocator<N, D> + Allocator<usize, D>,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let precision = f.precision().unwrap_or(3);

        try!(writeln!(f, "Isometry {{"));
        try!(write!(f, "{:.*}", precision, self.translation));
        try!(write!(f, "{:.*}", precision, self.rotation));
        writeln!(f, "}}")
    }
}
<commit_msg>Add doc-tests to isometry.rs.<commit_after>use approx::{AbsDiffEq, RelativeEq, UlpsEq};
use std::fmt;
use std::hash;
#[cfg(feature = "abomonation-serialize")]
use std::io::{Result as IOResult, Write};
use std::marker::PhantomData;

#[cfg(feature = "serde-serialize")]
use serde::{Deserialize, Serialize};

#[cfg(feature = "abomonation-serialize")]
use abomonation::Abomonation;

use alga::general::{Real, SubsetOf};
use alga::linear::Rotation;

use base::allocator::Allocator;
use base::dimension::{DimName, DimNameAdd, DimNameSum, U1};
use base::storage::Owned;
use base::{DefaultAllocator, MatrixN};
use geometry::{Point, Translation};

/// A direct isometry, i.e., a rotation followed by a translation, aka. a rigid-body motion, aka. an element of a Special Euclidean (SE) group.
#[repr(C)]
#[derive(Debug)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
#[cfg_attr(
    feature = "serde-serialize",
    serde(bound(
        serialize = "R: Serialize,
                     DefaultAllocator: Allocator<N, D>,
                     Owned<N, D>: Serialize"
    ))
)]
#[cfg_attr(
    feature = "serde-serialize",
    serde(bound(
        deserialize = "R: Deserialize<'de>,
                       DefaultAllocator: Allocator<N, D>,
                       Owned<N, D>: Deserialize<'de>"
    ))
)]
pub struct Isometry<N: Real, D: DimName, R>
where DefaultAllocator: Allocator<N, D>
{
    /// The pure rotational part of this isometry.
    pub rotation: R,
    /// The pure translational part of this isometry.
    pub translation: Translation<N, D>,

    // One dummy private field just to prevent explicit construction.
    #[cfg_attr(
        feature = "serde-serialize",
        serde(skip_serializing, skip_deserializing)
    )]
    _noconstruct: PhantomData<N>,
}

#[cfg(feature = "abomonation-serialize")]
impl<N, D, R> Abomonation for Isometry<N, D, R>
where
    N: Real,
    D: DimName,
    R: Abomonation,
    Translation<N, D>: Abomonation,
    DefaultAllocator: Allocator<N, D>,
{
    unsafe fn entomb<W: Write>(&self, writer: &mut W) -> IOResult<()> {
        self.rotation.entomb(writer)?;
        self.translation.entomb(writer)
    }

    fn extent(&self) -> usize {
        self.rotation.extent() + self.translation.extent()
    }

    unsafe fn exhume<'a, 'b>(&'a mut self, bytes: &'b mut [u8]) -> Option<&'b mut [u8]> {
        self.rotation
            .exhume(bytes)
            .and_then(|bytes| self.translation.exhume(bytes))
    }
}

impl<N: Real + hash::Hash, D: DimName + hash::Hash, R: hash::Hash> hash::Hash for Isometry<N, D, R>
where
    DefaultAllocator: Allocator<N, D>,
    Owned<N, D>: hash::Hash,
{
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        self.translation.hash(state);
        self.rotation.hash(state);
    }
}

impl<N: Real, D: DimName + Copy, R: Rotation<Point<N, D>> + Copy> Copy for Isometry<N, D, R>
where
    DefaultAllocator: Allocator<N, D>,
    Owned<N, D>: Copy,
{}

impl<N: Real, D: DimName, R: Rotation<Point<N, D>> + Clone> Clone for Isometry<N, D, R>
where DefaultAllocator: Allocator<N, D>
{
    #[inline]
    fn clone(&self) -> Self {
        Isometry::from_parts(self.translation.clone(), self.rotation.clone())
    }
}

impl<N: Real, D: DimName, R: Rotation<Point<N, D>>> Isometry<N, D, R>
where DefaultAllocator: Allocator<N, D>
{
    /// Creates a new isometry from its rotational and translational parts.
    ///
    /// # Example
    ///
    /// ```
    /// # #[macro_use] extern crate approx;
    /// # extern crate nalgebra;
    /// # use std::f32;
    /// # use nalgebra::{Isometry3, Translation3, UnitQuaternion, Vector3, Point3};
    /// let tra = Translation3::new(0.0, 0.0, 3.0);
    /// let rot = UnitQuaternion::from_scaled_axis(Vector3::y() * f32::consts::PI);
    /// let iso = Isometry3::from_parts(tra, rot);
    ///
    /// assert_relative_eq!(iso * Point3::new(1.0, 2.0, 3.0), Point3::new(-1.0, 2.0, 0.0), epsilon = 1.0e-6);
    /// ```
    #[inline]
    pub fn from_parts(translation: Translation<N, D>, rotation: R) -> Isometry<N, D, R> {
        Isometry {
            rotation: rotation,
            translation: translation,
            _noconstruct: PhantomData,
        }
    }

    /// Inverts `self`.
    ///
    /// # Example
    ///
    /// ```
    /// # use std::f32;
    /// # use nalgebra::{Isometry2, Point2, Vector2};
    /// let iso = Isometry2::new(Vector2::new(1.0, 2.0), f32::consts::FRAC_PI_2);
    /// let inv = iso.inverse();
    /// let pt = Point2::new(1.0, 2.0);
    ///
    /// assert_eq!(inv * (iso * pt), pt);
    /// ```
    #[inline]
    pub fn inverse(&self) -> Isometry<N, D, R> {
        let mut res = self.clone();
        res.inverse_mut();
        res
    }

    /// Inverts `self` in-place.
    ///
    /// # Example
    ///
    /// ```
    /// # use std::f32;
    /// # use nalgebra::{Isometry2, Point2, Vector2};
    /// let mut iso = Isometry2::new(Vector2::new(1.0, 2.0), f32::consts::FRAC_PI_2);
    /// let pt = Point2::new(1.0, 2.0);
    /// let transformed_pt = iso * pt;
    /// iso.inverse_mut();
    ///
    /// assert_eq!(iso * transformed_pt, pt);
    /// ```
    #[inline]
    pub fn inverse_mut(&mut self) {
        self.rotation.inverse_mut();
        self.translation.inverse_mut();
        self.translation.vector = self.rotation.transform_vector(&self.translation.vector);
    }

    /// Appends to `self` the given translation in-place.
    ///
    /// # Example
    ///
    /// ```
    /// # use std::f32;
    /// # use nalgebra::{Isometry2, Translation2, Vector2};
    /// let mut iso = Isometry2::new(Vector2::new(1.0, 2.0), f32::consts::FRAC_PI_2);
    /// let tra = Translation2::new(3.0, 4.0);
    /// // Same as `iso = tra * iso`.
    /// iso.append_translation_mut(&tra);
    ///
    /// assert_eq!(iso.translation, Translation2::new(4.0, 6.0));
    /// ```
    #[inline]
    pub fn append_translation_mut(&mut self, t: &Translation<N, D>) {
        self.translation.vector += &t.vector
    }

    /// Appends to `self` the given rotation in-place.
    ///
    /// # Example
    ///
    /// ```
    /// # #[macro_use] extern crate approx;
    /// # extern crate nalgebra;
    /// # use std::f32;
    /// # use nalgebra::{Isometry2, Translation2, UnitComplex, Vector2};
    /// let mut iso = Isometry2::new(Vector2::new(1.0, 2.0), f32::consts::PI / 6.0);
    /// let rot = UnitComplex::new(f32::consts::PI / 2.0);
    /// // Same as `iso = rot * iso`.
    /// iso.append_rotation_mut(&rot);
    ///
    /// assert_relative_eq!(iso, Isometry2::new(Vector2::new(-2.0, 1.0), f32::consts::PI * 2.0 / 3.0), epsilon = 1.0e-6);
    /// ```
    #[inline]
    pub fn append_rotation_mut(&mut self, r: &R) {
        self.rotation = self.rotation.append_rotation(&r);
        self.translation.vector = r.transform_vector(&self.translation.vector);
    }

    /// Appends in-place to `self` a rotation centered at the point `p`, i.e., the rotation that
    /// lets `p` invariant.
    ///
    /// # Example
    ///
    /// ```
    /// # #[macro_use] extern crate approx;
    /// # extern crate nalgebra;
    /// # use std::f32;
    /// # use nalgebra::{Isometry2, Translation2, UnitComplex, Vector2, Point2};
    /// let mut iso = Isometry2::new(Vector2::new(1.0, 2.0), f32::consts::FRAC_PI_2);
    /// let rot = UnitComplex::new(f32::consts::FRAC_PI_2);
    /// let pt = Point2::new(1.0, 0.0);
    /// iso.append_rotation_wrt_point_mut(&rot, &pt);
    ///
    /// assert_relative_eq!(iso * pt, Point2::new(-2.0, 0.0), epsilon = 1.0e-6);
    /// ```
    #[inline]
    pub fn append_rotation_wrt_point_mut(&mut self, r: &R, p: &Point<N, D>) {
        self.translation.vector -= &p.coords;
        self.append_rotation_mut(r);
        self.translation.vector += &p.coords;
    }

    /// Appends in-place to `self` a rotation centered at the point with coordinates
    /// `self.translation`.
    ///
    /// # Example
    ///
    /// ```
    /// # use std::f32;
    /// # use nalgebra::{Isometry2, Translation2, UnitComplex, Vector2, Point2};
    /// let mut iso = Isometry2::new(Vector2::new(1.0, 2.0), f32::consts::FRAC_PI_2);
    /// let rot = UnitComplex::new(f32::consts::FRAC_PI_2);
    /// iso.append_rotation_wrt_center_mut(&rot);
    ///
    /// // The translation part should not have changed.
    /// assert_eq!(iso.translation.vector, Vector2::new(1.0, 2.0));
    /// assert_eq!(iso.rotation, UnitComplex::new(f32::consts::PI));
    /// ```
    #[inline]
    pub fn append_rotation_wrt_center_mut(&mut self, r: &R) {
        self.rotation = self.rotation.append_rotation(r);
    }
}

// NOTE: we don't require `R: Rotation<...>` here because this is not useful for the implementation
// and makes it hard to use it, e.g., for Transform × Isometry implementation.
// This is OK since all constructors of the isometry enforce the Rotation bound already (and
// explicit struct construction is prevented by the dummy ZST field).
impl<N: Real, D: DimName, R> Isometry<N, D, R>
where DefaultAllocator: Allocator<N, D>
{
    /// Converts this isometry into its equivalent homogeneous transformation matrix.
    ///
    /// # Example
    ///
    /// ```
    /// # #[macro_use] extern crate approx;
    /// # extern crate nalgebra;
    /// # use std::f32;
    /// # use nalgebra::{Isometry2, Vector2, Matrix3};
    /// let iso = Isometry2::new(Vector2::new(10.0, 20.0), f32::consts::FRAC_PI_6);
    /// let expected = Matrix3::new(0.8660254, -0.5,      10.0,
    ///                             0.5,       0.8660254, 20.0,
    ///                             0.0,       0.0,       1.0);
    ///
    /// // The translation part should not have changed.
    /// assert_relative_eq!(iso.to_homogeneous(), expected, epsilon = 1.0e-6);
    /// ```
    #[inline]
    pub fn to_homogeneous(&self) -> MatrixN<N, DimNameSum<D, U1>>
    where
        D: DimNameAdd<U1>,
        R: SubsetOf<MatrixN<N, DimNameSum<D, U1>>>,
        DefaultAllocator: Allocator<N, DimNameSum<D, U1>, DimNameSum<D, U1>>,
    {
        let mut res: MatrixN<N, _> = ::convert_ref(&self.rotation);
        res.fixed_slice_mut::<D, U1>(0, D::dim())
            .copy_from(&self.translation.vector);

        res
    }
}

impl<N: Real, D: DimName, R> Eq for Isometry<N, D, R>
where
    R: Rotation<Point<N, D>> + Eq,
    DefaultAllocator: Allocator<N, D>,
{}

impl<N: Real, D: DimName, R> PartialEq for Isometry<N, D, R>
where
    R: Rotation<Point<N, D>> + PartialEq,
    DefaultAllocator: Allocator<N, D>,
{
    #[inline]
    fn eq(&self, right: &Isometry<N, D, R>) -> bool {
        self.translation == right.translation && self.rotation == right.rotation
    }
}

impl<N: Real, D: DimName, R> AbsDiffEq for Isometry<N, D, R>
where
    R: Rotation<Point<N, D>> + AbsDiffEq<Epsilon = N::Epsilon>,
    DefaultAllocator: Allocator<N, D>,
    N::Epsilon: Copy,
{
    type Epsilon = N::Epsilon;

    #[inline]
    fn default_epsilon() -> Self::Epsilon {
        N::default_epsilon()
    }

    #[inline]
    fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
        self.translation.abs_diff_eq(&other.translation, epsilon)
            && self.rotation.abs_diff_eq(&other.rotation, epsilon)
    }
}

impl<N: Real, D: DimName, R> RelativeEq for Isometry<N, D, R>
where
    R: Rotation<Point<N, D>> + RelativeEq<Epsilon = N::Epsilon>,
    DefaultAllocator: Allocator<N, D>,
    N::Epsilon: Copy,
{
    #[inline]
    fn default_max_relative() -> Self::Epsilon {
        N::default_max_relative()
    }

    #[inline]
    fn relative_eq(
        &self,
        other: &Self,
        epsilon: Self::Epsilon,
        max_relative: Self::Epsilon,
    ) -> bool
    {
        self.translation
            .relative_eq(&other.translation, epsilon, max_relative)
            && self
                .rotation
                .relative_eq(&other.rotation, epsilon, max_relative)
    }
}

impl<N: Real, D: DimName, R> UlpsEq for Isometry<N, D, R>
where
    R: Rotation<Point<N, D>> + UlpsEq<Epsilon = N::Epsilon>,
    DefaultAllocator: Allocator<N, D>,
    N::Epsilon: Copy,
{
    #[inline]
    fn default_max_ulps() -> u32 {
        N::default_max_ulps()
    }

    #[inline]
    fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
        self.translation
            .ulps_eq(&other.translation, epsilon, max_ulps)
            && self.rotation.ulps_eq(&other.rotation, epsilon, max_ulps)
    }
}

/*
 *
 * Display
 *
 */
impl<N: Real + fmt::Display, D: DimName, R> fmt::Display for Isometry<N, D, R>
where
    R: fmt::Display,
    DefaultAllocator: Allocator<N, D> + Allocator<usize, D>,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let precision = f.precision().unwrap_or(3);

        try!(writeln!(f, "Isometry {{"));
        try!(write!(f, "{:.*}", precision, self.translation));
        try!(write!(f, "{:.*}", precision, self.rotation));
        writeln!(f, "}}")
    }
}
<|endoftext|>


<commit_before>//! A Collection of Header implementations for common HTTP Headers.
//!
//! ## Mime
//!
//! Several header fields use MIME values for their contents. Keeping with the
//! strongly-typed theme, the [mime](http://seanmonstar.github.io/mime.rs) crate
//! is used, such as `ContentType(pub Mime)`.

pub use self::access_control::*;
pub use self::accept::Accept;
pub use self::accept_encoding::AcceptEncoding;
pub use self::allow::Allow;
pub use self::authorization::Authorization;
pub use self::cache_control::CacheControl;
pub use self::connection::Connection;
pub use self::content_length::ContentLength;
pub use self::content_type::ContentType;
pub use self::cookie::Cookies;
pub use self::date::Date;
pub use self::etag::Etag;
pub use self::expires::Expires;
pub use self::host::Host;
pub use self::if_modified_since::IfModifiedSince;
pub use self::last_modified::LastModified;
pub use self::location::Location;
pub use self::referer::Referer;
pub use self::server::Server;
pub use self::set_cookie::SetCookie;
pub use self::transfer_encoding::TransferEncoding;
pub use self::upgrade::Upgrade;
pub use self::user_agent::UserAgent;
pub use self::vary::Vary;

pub use self::connection::ConnectionOption;

#[macro_export]
macro_rules! bench_header(
    ($name:ident, $ty:ty, $value:expr) => {
        #[cfg(test)]
        mod $name {
            use test::Bencher;
            use super::*;

            use header::{Header, HeaderFormatter};

            #[bench]
            fn bench_parse(b: &mut Bencher) {
                let val = $value;
                b.iter(|| {
                    let _: $ty = Header::parse_header(&val[]).unwrap();
                });
            }

            #[bench]
            fn bench_format(b: &mut Bencher) {
                let val: $ty = Header::parse_header(&$value[]).unwrap();
                let fmt = HeaderFormatter(&val);
                b.iter(|| {
                    format!("{}", fmt);
                });
            }
        }
    }
);

#[macro_export]
macro_rules! deref(
    ($from:ty => $to:ty) => {
        impl ::std::ops::Deref for $from {
            type Target = $to;

            fn deref<'a>(&'a self) -> &'a $to {
                &self.0
            }
        }

        impl ::std::ops::DerefMut for $from {
            fn deref_mut<'a>(&'a mut self) -> &'a mut $to {
                &mut self.0
            }
        }
    }
);

#[macro_export]
macro_rules! impl_list_header(
    ($from:ident, $name:expr, $item:ty) => {
        deref!($from => $item);

        impl header::Header for $from {
            fn header_name(_: Option<$from>) -> &'static str {
                $name
            }

            fn parse_header(raw: &[Vec<u8>]) -> Option<$from> {
                $crate::header::parsing::from_comma_delimited(raw).map($from)
            }
        }

        impl header::HeaderFormat for $from {
            fn fmt_header(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                $crate::header::parsing::fmt_comma_delimited(fmt, &self[])
            }
        }

        impl ::std::fmt::String for $from {
            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                use header::HeaderFormat;
                self.fmt_header(f)
            }
        }
    }
);

#[macro_export]
macro_rules! impl_header(
    ($from:ident, $name:expr, $item:ty) => {
        deref!($from => $item);

        impl header::Header for $from {
            fn header_name(_: Option<$from>) -> &'static str {
                $name
            }

            fn parse_header(raw: &[Vec<u8>]) -> Option<$from> {
                $crate::header::parsing::from_one_raw_str(raw).map($from)
            }
        }

        impl header::HeaderFormat for $from {
            fn fmt_header(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                ::std::fmt::String::fmt(&**self, f)
            }
        }

        impl ::std::fmt::String for $from {
            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                use header::HeaderFormat;
                self.fmt_header(f)
            }
        }
    }
);

mod access_control;
mod accept;
mod accept_encoding;
mod allow;
mod authorization;
mod cache_control;
mod cookie;
mod connection;
mod content_length;
mod content_type;
mod date;
mod etag;
mod expires;
mod host;
mod last_modified;
mod if_modified_since;
mod location;
mod referer;
mod server;
mod set_cookie;
mod transfer_encoding;
mod upgrade;
mod user_agent;
mod vary;

<commit_msg>refactor(headers): make CacheDirective public<commit_after>//! A Collection of Header implementations for common HTTP Headers.
//!
//! ## Mime
//!
//! Several header fields use MIME values for their contents. Keeping with the
//! strongly-typed theme, the [mime](http://seanmonstar.github.io/mime.rs) crate
//! is used, such as `ContentType(pub Mime)`.

pub use self::access_control::*;
pub use self::accept::Accept;
pub use self::accept_encoding::AcceptEncoding;
pub use self::allow::Allow;
pub use self::authorization::Authorization;
pub use self::cache_control::{CacheControl, CacheDirective};
pub use self::connection::Connection;
pub use self::content_length::ContentLength;
pub use self::content_type::ContentType;
pub use self::cookie::Cookies;
pub use self::date::Date;
pub use self::etag::Etag;
pub use self::expires::Expires;
pub use self::host::Host;
pub use self::if_modified_since::IfModifiedSince;
pub use self::last_modified::LastModified;
pub use self::location::Location;
pub use self::referer::Referer;
pub use self::server::Server;
pub use self::set_cookie::SetCookie;
pub use self::transfer_encoding::TransferEncoding;
pub use self::upgrade::Upgrade;
pub use self::user_agent::UserAgent;
pub use self::vary::Vary;

pub use self::connection::ConnectionOption;

#[macro_export]
macro_rules! bench_header(
    ($name:ident, $ty:ty, $value:expr) => {
        #[cfg(test)]
        mod $name {
            use test::Bencher;
            use super::*;

            use header::{Header, HeaderFormatter};

            #[bench]
            fn bench_parse(b: &mut Bencher) {
                let val = $value;
                b.iter(|| {
                    let _: $ty = Header::parse_header(&val[]).unwrap();
                });
            }

            #[bench]
            fn bench_format(b: &mut Bencher) {
                let val: $ty = Header::parse_header(&$value[]).unwrap();
                let fmt = HeaderFormatter(&val);
                b.iter(|| {
                    format!("{}", fmt);
                });
            }
        }
    }
);

#[macro_export]
macro_rules! deref(
    ($from:ty => $to:ty) => {
        impl ::std::ops::Deref for $from {
            type Target = $to;

            fn deref<'a>(&'a self) -> &'a $to {
                &self.0
            }
        }

        impl ::std::ops::DerefMut for $from {
            fn deref_mut<'a>(&'a mut self) -> &'a mut $to {
                &mut self.0
            }
        }
    }
);

#[macro_export]
macro_rules! impl_list_header(
    ($from:ident, $name:expr, $item:ty) => {
        deref!($from => $item);

        impl header::Header for $from {
            fn header_name(_: Option<$from>) -> &'static str {
                $name
            }

            fn parse_header(raw: &[Vec<u8>]) -> Option<$from> {
                $crate::header::parsing::from_comma_delimited(raw).map($from)
            }
        }

        impl header::HeaderFormat for $from {
            fn fmt_header(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                $crate::header::parsing::fmt_comma_delimited(fmt, &self[])
            }
        }

        impl ::std::fmt::String for $from {
            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                use header::HeaderFormat;
                self.fmt_header(f)
            }
        }
    }
);

#[macro_export]
macro_rules! impl_header(
    ($from:ident, $name:expr, $item:ty) => {
        deref!($from => $item);

        impl header::Header for $from {
            fn header_name(_: Option<$from>) -> &'static str {
                $name
            }

            fn parse_header(raw: &[Vec<u8>]) -> Option<$from> {
                $crate::header::parsing::from_one_raw_str(raw).map($from)
            }
        }

        impl header::HeaderFormat for $from {
            fn fmt_header(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                ::std::fmt::String::fmt(&**self, f)
            }
        }

        impl ::std::fmt::String for $from {
            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                use header::HeaderFormat;
                self.fmt_header(f)
            }
        }
    }
);

mod access_control;
mod accept;
mod accept_encoding;
mod allow;
mod authorization;
mod cache_control;
mod cookie;
mod connection;
mod content_length;
mod content_type;
mod date;
mod etag;
mod expires;
mod host;
mod last_modified;
mod if_modified_since;
mod location;
mod referer;
mod server;
mod set_cookie;
mod transfer_encoding;
mod upgrade;
mod user_agent;
mod vary;

<|endoftext|>


<commit_before>extern crate fuse;

use std::os;
use fuse::Filesystem;

struct JsonFilesystem;

impl Filesystem for JsonFilesystem {
}

fn main() {
    println!("24 days of Rust - fuse (day N)");
    let mountpoint = Path::new(os::args()[1].as_slice());
    fuse::mount(JsonFilesystem, &mountpoint, &[]);
}
<commit_msg>First attempt at getattr.<commit_after>extern crate fuse;
extern crate libc;

use std::os;
use libc::{ENOENT, ENOSYS};
use fuse::{FileAttr, Filesystem, Request, ReplyAttr, ReplyEntry, ReplyDirectory};

struct JsonFilesystem;

impl Filesystem for JsonFilesystem {
    fn getattr(&mut self, _req: &Request, ino: u64, reply: ReplyAttr) {
        println!("getattr(): ino {}", ino);
        reply.error(ENOSYS);
    }
}

fn main() {
    println!("24 days of Rust - fuse (day N)");
    let mountpoint = Path::new(os::args()[1].as_slice());
    fuse::mount(JsonFilesystem, &mountpoint, &[]);
}
<|endoftext|>


<commit_before>pub enum ErrorLevel {
    Info,
    Warning,
    Error,
}

// Use a hashmap which contains an error level and a string
type ErrorStack = Vec<(ErrorLevel, String)>;<commit_msg>Make the error stack type public<commit_after>pub enum ErrorLevel {
    Info,
    Warning,
    Error,
}

// Use a hashmap which contains an error level and a string
pub type ErrorStack = Vec<(ErrorLevel, String)>;<|endoftext|>


<commit_before>use std::io::File;
use std::io::fs::PathExtensions;
use std::collections::HashMap;
use calx::color;
use calx::Context;
use calx::Event;
use calx::Key;
use calx::{Fonter, V2};
use world;
use world::action;
use world::action::{Step, Melee};
use world::Dir6;
use world::Dir6::*;
use world::{Entity};
use worldview;
use sprite::{WorldSprites, GibSprite};

pub struct GameState {
    world_spr: WorldSprites,
    /// Counters for entities with flashing damage animation.
    damage_timers: HashMap<Entity, uint>,

    // TODO: Probably going to need a general "ongoing activity" system at
    // some point.
    exploring: bool,
}

impl GameState {
    pub fn new(seed: Option<u32>) -> GameState {
        world::init_world(seed);
        GameState {
            world_spr: WorldSprites::new(),
            damage_timers: HashMap::new(),
            exploring: false,
        }
    }

    /// Repaint view, update game world if needed.
    pub fn update(&mut self, ctx: &mut Context) {
        ctx.clear(&color::BLACK);
        let camera = world::camera();

        // Process events
        loop {
            match world::pop_msg() {
                Some(world::Gib(loc)) => {
                    self.world_spr.add(box GibSprite::new(loc));
                }
                Some(world::Damage(entity)) => {
                    self.damage_timers.insert(entity, 2);
                }
                Some(x) => {
                    println!("Unhandled Msg type {}", x);
                }
                None => break
            }
        }

        worldview::draw_world(&camera, ctx, &self.damage_timers);

        // TODO use FOV for sprite draw.
        self.world_spr.draw(|x| (camera + x).fov_status() == Some(world::Seen), &camera, ctx);
        self.world_spr.update();

        let fps = 1.0 / ctx.render_duration;
        let _ = write!(&mut ctx.text_writer(V2(0, 8), 0.1, color::LIGHTGREEN)
                       .set_border(color::BLACK),
                       "FPS {:.0}", fps);

        if action::control_state() == action::ReadyToUpdate {
            action::update();
        }

        if self.exploring {
            if action::control_state() == action::AwaitingInput {
                self.exploring = self.autoexplore();
            }
        }

        self.damage_timers = self.damage_timers.clone().into_iter()
            .filter(|&(_, t)| t > 0u)
            .map(|(e, t)| (e, t - 1))
            .collect();
    }

    pub fn save_game(&self) {
        let save_data = world::save();
        let mut file = File::create(&Path::new("/tmp/magog_save.json"));
        file.write_str(save_data.as_slice()).unwrap();
    }

    pub fn load_game(&mut self) {
        let path = Path::new("/tmp/magog_save.json");
        if !path.exists() { return; }
        let save_data = File::open(&path).read_to_string().unwrap();
        // TODO: Handle failed load nicely.
        world::load(save_data.as_slice()).unwrap();
    }

    fn smart_move(&mut self, dir: Dir6) {
        let player = action::player().unwrap();
        let target_loc = player.location().unwrap() + dir.to_v2();
        if target_loc.has_mobs() {
            action::input(Melee(dir));
        } else {
            action::input(Step(dir));
        }
    }

    fn autoexplore(&mut self) -> bool {
        let player = action::player().unwrap();
        if player.is_threatened() {
            return false;
        }
        if let Some(pathing) = action::autoexplore_map() {
            let loc = player.location().unwrap();
            let steps = pathing.sorted_neighbors(&loc);
            if steps.len() == 0 {
                return false;
            }

            action::input(Step(loc.dir6_towards(steps[0]).unwrap()));
            return true;
        }

        false
    }

    /// Process a player control keypress.
    pub fn process_key(&mut self, key: Key) -> bool {
        if action::control_state() != action::AwaitingInput {
            return false;
        }

        if self.exploring {
            self.exploring = false;
        }

        match key {
            Key::Q | Key::Pad7 => { self.smart_move(NorthWest); }
            Key::W | Key::Pad8 | Key::Up => { self.smart_move(North); }
            Key::E | Key::Pad9 => { self.smart_move(NorthEast); }
            Key::A | Key::Pad1 => { self.smart_move(SouthWest); }
            Key::S | Key::Pad2 | Key::Down => { self.smart_move(South); }
            Key::D | Key::Pad3 => { self.smart_move(SouthEast); }
            Key::F5 => { self.save_game(); }
            Key::F9 => { self.load_game(); }
            Key::X => { self.exploring = true; }
            _ => { return false; }
        }
        return true;
    }

    pub fn process(&mut self, event: Event) -> bool {
        match event {
            Event::Render(ctx) => {
                self.update(ctx);
            }
            Event::KeyPressed(Key::Escape) => {
                return false;
            }
            Event::KeyPressed(k) => {
                self.process_key(k);
            }
            _ => ()
        }
        true
    }
}
<commit_msg>Health display<commit_after>use std::io::File;
use std::io::fs::PathExtensions;
use std::collections::HashMap;
use calx::color;
use calx::Context;
use calx::Event;
use calx::Key;
use calx::{Fonter, V2};
use world;
use world::action;
use world::action::{Step, Melee};
use world::Dir6;
use world::Dir6::*;
use world::{Entity};
use worldview;
use sprite::{WorldSprites, GibSprite};
use tilecache;
use tilecache::icon;

pub struct GameState {
    world_spr: WorldSprites,
    /// Counters for entities with flashing damage animation.
    damage_timers: HashMap<Entity, uint>,

    // TODO: Probably going to need a general "ongoing activity" system at
    // some point.
    exploring: bool,
}

impl GameState {
    pub fn new(seed: Option<u32>) -> GameState {
        world::init_world(seed);
        GameState {
            world_spr: WorldSprites::new(),
            damage_timers: HashMap::new(),
            exploring: false,
        }
    }

    fn draw_player_ui(&mut self, ctx: &mut Context, player: Entity) {
        let hp = player.hp();
        let max_hp = player.max_hp();

        // Draw heart containers.
        for i in range(0, (max_hp + 1) / 2) {
            let pos = V2(i * 8, 8);
            let idx = if hp >= (i + 1) * 2 { icon::HEART }
                else if hp == i * 2 + 1 { icon::HALF_HEART }
                else { icon::NO_HEART };
            ctx.draw_image(pos, 0.0, tilecache::get(idx), &color::FIREBRICK);
        }
    }

    /// Repaint view, update game world if needed.
    pub fn update(&mut self, ctx: &mut Context) {
        ctx.clear(&color::BLACK);
        let camera = world::camera();

        // Process events
        loop {
            match world::pop_msg() {
                Some(world::Gib(loc)) => {
                    self.world_spr.add(box GibSprite::new(loc));
                }
                Some(world::Damage(entity)) => {
                    self.damage_timers.insert(entity, 2);
                }
                Some(x) => {
                    println!("Unhandled Msg type {}", x);
                }
                None => break
            }
        }

        worldview::draw_world(&camera, ctx, &self.damage_timers);

        // TODO use FOV for sprite draw.
        self.world_spr.draw(|x| (camera + x).fov_status() == Some(world::Seen), &camera, ctx);
        self.world_spr.update();

        if let Some(player) = action::player() {
            self.draw_player_ui(ctx, player);
        }

        let fps = 1.0 / ctx.render_duration;
        let _ = write!(&mut ctx.text_writer(V2(0, 16), 0.1, color::LIGHTGREEN)
                       .set_border(color::BLACK),
                       "FPS {:.0}", fps);

        if action::control_state() == action::ReadyToUpdate {
            action::update();
        }

        if self.exploring {
            if action::control_state() == action::AwaitingInput {
                self.exploring = self.autoexplore();
            }
        }

        self.damage_timers = self.damage_timers.clone().into_iter()
            .filter(|&(_, t)| t > 0u)
            .map(|(e, t)| (e, t - 1))
            .collect();
    }

    pub fn save_game(&self) {
        let save_data = world::save();
        let mut file = File::create(&Path::new("/tmp/magog_save.json"));
        file.write_str(save_data.as_slice()).unwrap();
    }

    pub fn load_game(&mut self) {
        let path = Path::new("/tmp/magog_save.json");
        if !path.exists() { return; }
        let save_data = File::open(&path).read_to_string().unwrap();
        // TODO: Handle failed load nicely.
        world::load(save_data.as_slice()).unwrap();
    }

    fn smart_move(&mut self, dir: Dir6) {
        let player = action::player().unwrap();
        let target_loc = player.location().unwrap() + dir.to_v2();
        if target_loc.has_mobs() {
            action::input(Melee(dir));
        } else {
            action::input(Step(dir));
        }
    }

    fn autoexplore(&mut self) -> bool {
        let player = action::player().unwrap();
        if player.is_threatened() {
            return false;
        }
        if let Some(pathing) = action::autoexplore_map() {
            let loc = player.location().unwrap();
            let steps = pathing.sorted_neighbors(&loc);
            if steps.len() == 0 {
                return false;
            }

            action::input(Step(loc.dir6_towards(steps[0]).unwrap()));
            return true;
        }

        false
    }

    /// Process a player control keypress.
    pub fn process_key(&mut self, key: Key) -> bool {
        if action::control_state() != action::AwaitingInput {
            return false;
        }

        if self.exploring {
            self.exploring = false;
        }

        match key {
            Key::Q | Key::Pad7 => { self.smart_move(NorthWest); }
            Key::W | Key::Pad8 | Key::Up => { self.smart_move(North); }
            Key::E | Key::Pad9 => { self.smart_move(NorthEast); }
            Key::A | Key::Pad1 => { self.smart_move(SouthWest); }
            Key::S | Key::Pad2 | Key::Down => { self.smart_move(South); }
            Key::D | Key::Pad3 => { self.smart_move(SouthEast); }
            Key::F5 => { self.save_game(); }
            Key::F9 => { self.load_game(); }
            Key::X => { self.exploring = true; }
            _ => { return false; }
        }
        return true;
    }

    pub fn process(&mut self, event: Event) -> bool {
        match event {
            Event::Render(ctx) => {
                self.update(ctx);
            }
            Event::KeyPressed(Key::Escape) => {
                return false;
            }
            Event::KeyPressed(k) => {
                self.process_key(k);
            }
            _ => ()
        }
        true
    }
}
<|endoftext|>


<commit_before>use lib::*;

pub fn from_bounds<I>(iter: &I) -> Option<usize>
where
    I: Iterator,
{
    helper(iter.size_hint())
}

#[inline]
pub fn cautious(hint: Option<usize>) -> usize {
    cmp::min(hint.unwrap_or(0), 4096)
}

fn helper(bounds: (usize, Option<usize>)) -> Option<usize> {
    match bounds {
        (lower, Some(upper)) if lower == upper => Some(upper),
        _ => None,
    }
}
<commit_msg>Omit size_hint::cautious when not allocating<commit_after>use lib::*;

pub fn from_bounds<I>(iter: &I) -> Option<usize>
where
    I: Iterator,
{
    helper(iter.size_hint())
}

#[cfg(any(feature = "std", feature = "alloc"))]
#[inline]
pub fn cautious(hint: Option<usize>) -> usize {
    cmp::min(hint.unwrap_or(0), 4096)
}

fn helper(bounds: (usize, Option<usize>)) -> Option<usize> {
    match bounds {
        (lower, Some(upper)) if lower == upper => Some(upper),
        _ => None,
    }
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate json;
extern crate requests;

use requests::{delete, get, head, post, put};

#[test]
fn simple_get() {
    const URL: &'static str = "http://httpbin.org/get";
    let res = get(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
    let data = res.json().unwrap();
    println!("{:?}", data);
    assert_eq!(data["url"], URL);
    assert_eq!(data["headers"]["Host"], "httpbin.org");
    assert_eq!(data["headers"]["User-Agent"],
               concat!("requests-rs/", env!("CARGO_PKG_VERSION")));
}

#[test]
fn simple_post() {
    const URL: &'static str = "http://httpbin.org/post";
    let res = post(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn simple_put() {
    const URL: &'static str = "http://httpbin.org/put";
    let res = put(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn simple_head() {
    const URL: &'static str = "http://httpbin.org/get";
    let res = head(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn simple_delete() {
    const URL: &'static str = "http://httpbin.org/delete";
    let res = delete(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn user_agent() {
    let useragent = concat!("{\n  \"user-agent\": \"requests-rs/",
                            env!("CARGO_PKG_VERSION"),
                            "\"\n}\n");
    const URL: &'static str = "http://httpbin.org/user-agent";
    let res = get(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
    assert_eq!(res.text(), Some(useragent));
}

#[test]
fn user_agent_json() {

    const URL: &'static str = "http://httpbin.org/user-agent";
    let res = get(URL).unwrap();
    assert!(res.is_json());

    let ua = res.json().unwrap();
    assert_eq!(ua["user-agent"],
               concat!("requests-rs/", env!("CARGO_PKG_VERSION")));
}

macro_rules! status_code_test {
    ($($name:ident: $numeric:expr,)+) => {
        $(#[test]
        fn $name() {
            let res = get(&format!("http://httpbin.org/status/{}", $numeric)).unwrap();
            assert_eq!(res.status_code(), hyper::status::StatusCode::from_u16($numeric));
        })+
    }
}

status_code_test! {
    status_code_100: 100,
    status_code_101: 101,
    status_code_102: 102,
    status_code_200: 200,
    status_code_201: 201,
    status_code_202: 202,
    status_code_203: 203,
    status_code_400: 400,
    status_code_401: 401,
    status_code_402: 402,
    status_code_403: 403,
    status_code_404: 404,
    status_code_500: 500,
}
<commit_msg>Add content test<commit_after>extern crate hyper;
extern crate json;
extern crate requests;

use requests::{delete, get, head, post, put};

#[test]
fn simple_get() {
    const URL: &'static str = "http://httpbin.org/get";
    let res = get(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
    let data = res.json().unwrap();
    println!("{:?}", data);
    assert_eq!(data["url"], URL);
    assert_eq!(data["headers"]["Host"], "httpbin.org");
    assert_eq!(data["headers"]["User-Agent"],
               concat!("requests-rs/", env!("CARGO_PKG_VERSION")));
}

#[test]
fn simple_post() {
    const URL: &'static str = "http://httpbin.org/post";
    let res = post(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn simple_put() {
    const URL: &'static str = "http://httpbin.org/put";
    let res = put(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn simple_head() {
    const URL: &'static str = "http://httpbin.org/get";
    let res = head(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn simple_delete() {
    const URL: &'static str = "http://httpbin.org/delete";
    let res = delete(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn user_agent() {
    let useragent = concat!("{\n  \"user-agent\": \"requests-rs/",
                            env!("CARGO_PKG_VERSION"),
                            "\"\n}\n");
    const URL: &'static str = "http://httpbin.org/user-agent";
    let res = get(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
    assert_eq!(res.text(), Some(useragent));
}

#[test]
fn user_agent_json() {

    const URL: &'static str = "http://httpbin.org/user-agent";
    let res = get(URL).unwrap();
    assert!(res.is_json());

    let ua = res.json().unwrap();
    assert_eq!(ua["user-agent"],
               concat!("requests-rs/", env!("CARGO_PKG_VERSION")));
}

#[test]
fn content() {
    const URL: &'static str = "http://httpbin.org/get";
    let res = get(URL).unwrap();
    let content =
        vec![123, 10, 32, 32, 34, 97, 114, 103, 115, 34, 58, 32, 123, 125, 44, 32, 10, 32, 32, 34,
             104, 101, 97, 100, 101, 114, 115, 34, 58, 32, 123, 10, 32, 32, 32, 32, 34, 72, 111,
             115, 116, 34, 58, 32, 34, 104, 116, 116, 112, 98, 105, 110, 46, 111, 114, 103, 34,
             44, 32, 10, 32, 32, 32, 32, 34, 85, 115, 101, 114, 45, 65, 103, 101, 110, 116, 34,
             58, 32, 34, 114, 101, 113, 117, 101, 115, 116, 115, 45, 114, 115, 47, 48, 46, 48, 46,
             49, 55, 34, 10, 32, 32, 125, 44, 32, 10, 32, 32, 34, 111, 114, 105, 103, 105, 110,
             34, 58, 32, 34, 56, 49, 46, 50, 49, 56, 46, 50, 57, 46, 50, 54, 34, 44, 32, 10, 32,
             32, 34, 117, 114, 108, 34, 58, 32, 34, 104, 116, 116, 112, 58, 47, 47, 104, 116, 116,
             112, 98, 105, 110, 46, 111, 114, 103, 47, 103, 101, 116, 34, 10, 125, 10];
    assert_eq!(res.content(), &content);
}

macro_rules! status_code_test {
    ($($name:ident: $numeric:expr,)+) => {
        $(#[test]
        fn $name() {
            let res = get(&format!("http://httpbin.org/status/{}", $numeric)).unwrap();
            assert_eq!(res.status_code(), hyper::status::StatusCode::from_u16($numeric));
        })+
    }
}

status_code_test! {
    status_code_100: 100,
    status_code_101: 101,
    status_code_102: 102,
    status_code_200: 200,
    status_code_201: 201,
    status_code_202: 202,
    status_code_203: 203,
    status_code_400: 400,
    status_code_401: 401,
    status_code_402: 402,
    status_code_403: 403,
    status_code_404: 404,
    status_code_500: 500,
}
<|endoftext|>


<commit_before>extern crate odbc_sys;
extern crate odbc_safe;

use odbc_safe::*;

#[test]
fn allocate_environment() {
    Environment::new().unwrap();
}

#[test]
fn allocate_connection() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    Connection::with_parent(&env).unwrap();
}

#[test]
#[should_panic]
fn wrong_datasource() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    let dbc = Connection::with_parent(&env).unwrap();
    dbc.connect("DoesntExist", "", "").unwrap();
}

#[test]
fn diagnostics() {

    let expected = if cfg!(target_os = "windows") {
        "[Microsoft][ODBC Driver Manager] Data source name not found and no default driver \
         specified"
    } else {
        "[unixODBC][Driver Manager]Data source name not found, and no default driver specified"
    };

    use std::str;

    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();

    let dbc = Connection::with_parent(&env).unwrap();
    let dbc = dbc.connect("DoesntExist", "", "");
    if let Error(d) = dbc {
        let mut message = [0; 512];
        match d.diagnostics(1, &mut message) {
            DiagReturn::Success(rec) => {
                let message = str::from_utf8(&mut message[..(rec.text_length as usize)]).unwrap();
                assert_eq!(expected, message);
            }
            _ => panic!("Error retriving diagnostics"),
        }
    }
}

#[cfg_attr(not(feature = "travis"), ignore)]
#[test]
fn connect_to_postgres() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    let dbc = Connection::with_parent(&env).unwrap();
    let dbc = dbc.connect("PostgreSQL", "postgres", "");
    match dbc {
        Success(c) => assert_no_diagnostic(&c.disconnect()),
        Info(c) => assert_no_diagnostic(&c),
        Error(c) => assert_no_diagnostic(&c),
    };
}

#[cfg_attr(not(feature = "travis"), ignore)]
#[test]
fn query_result() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    let dbc = Connection::with_parent(&env).unwrap();
    let dbc = dbc.connect("PostgreSQL", "postgres", "").unwrap();
    {
        let stmt = Statement::with_parent(&dbc).unwrap();
        let mut stmt = match stmt.exec_direct("SELECT titel FROM Movies WHERE year=1968") {
            ReturnNoData::Success(s) | ReturnNoData::Info(s) => {
                assert_no_diagnostic(&s);
                s
            }
            ReturnNoData::NoData(_) => panic!("No Data"),
            ReturnNoData::Error(s) => panic!("{}", get_last_error(&s)),
        };
        assert_eq!(1, stmt.num_result_cols().unwrap());
        loop {
            stmt = match stmt.fetch() {
                ReturnNoData::Success(s) => s,
                ReturnNoData::Info(s) => s,
                ReturnNoData::Error(s) => {
                    panic!("Error during fetching row: {}", get_last_error(&s))
                }
                ReturnNoData::NoData(_) => break,
            };
            let mut buffer = [0u8; 256];
            if let ReturnNoData::Success(Indicator::Length(i)) =
                stmt.get_data(1, &mut buffer as &mut [u8])
            {
                assert_eq!("2001: A Space Odyssey".as_bytes(), &buffer[..(i as usize)]);
            } else {
                panic!("No field found!");
            }
        }
    }
    dbc.disconnect().unwrap();
}

/// Checks for a diagnstic record. Should one be present this function panics printing the contents
/// of said record.
fn assert_no_diagnostic(diag: &Diagnostics) {
    use std::str;
    let mut buffer = [0; 512];
    match diag.diagnostics(1, &mut buffer) {
        DiagReturn::Success(dr) | DiagReturn::Info(dr) => panic!(
            "{}",
            str::from_utf8(&buffer[0..(dr.text_length as usize)]).unwrap()
        ),
        DiagReturn::Error => panic!("Error during fetching diagnostic record"),
        DiagReturn::NoData => (),
    }
}

fn get_last_error(diag: &Diagnostics) -> String {
    use std::str;
    let mut buffer = [0; 512];
    match diag.diagnostics(1, &mut buffer) {
        DiagReturn::Success(dr) | DiagReturn::Info(dr) => str::from_utf8(
            &buffer[0..(dr.text_length as usize)],
        ).unwrap()
            .to_owned(),
        DiagReturn::Error => panic!("Error during fetching diagnostic record"),
        DiagReturn::NoData => panic!("No diagnostic available"),
    }
}
<commit_msg>fix typo in test<commit_after>extern crate odbc_sys;
extern crate odbc_safe;

use odbc_safe::*;

#[test]
fn allocate_environment() {
    Environment::new().unwrap();
}

#[test]
fn allocate_connection() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    Connection::with_parent(&env).unwrap();
}

#[test]
#[should_panic]
fn wrong_datasource() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    let dbc = Connection::with_parent(&env).unwrap();
    dbc.connect("DoesntExist", "", "").unwrap();
}

#[test]
fn diagnostics() {

    let expected = if cfg!(target_os = "windows") {
        "[Microsoft][ODBC Driver Manager] Data source name not found and no default driver \
         specified"
    } else {
        "[unixODBC][Driver Manager]Data source name not found, and no default driver specified"
    };

    use std::str;

    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();

    let dbc = Connection::with_parent(&env).unwrap();
    let dbc = dbc.connect("DoesntExist", "", "");
    if let Error(d) = dbc {
        let mut message = [0; 512];
        match d.diagnostics(1, &mut message) {
            DiagReturn::Success(rec) => {
                let message = str::from_utf8(&mut message[..(rec.text_length as usize)]).unwrap();
                assert_eq!(expected, message);
            }
            _ => panic!("Error retriving diagnostics"),
        }
    }
}

#[cfg_attr(not(feature = "travis"), ignore)]
#[test]
fn connect_to_postgres() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    let dbc = Connection::with_parent(&env).unwrap();
    let dbc = dbc.connect("PostgreSQL", "postgres", "");
    match dbc {
        Success(c) => assert_no_diagnostic(&c.disconnect()),
        Info(c) => assert_no_diagnostic(&c),
        Error(c) => assert_no_diagnostic(&c),
    };
}

#[cfg_attr(not(feature = "travis"), ignore)]
#[test]
fn query_result() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    let dbc = Connection::with_parent(&env).unwrap();
    let dbc = dbc.connect("PostgreSQL", "postgres", "").unwrap();
    {
        let stmt = Statement::with_parent(&dbc).unwrap();
        let mut stmt = match stmt.exec_direct("SELECT title FROM Movies WHERE year=1968") {
            ReturnNoData::Success(s) | ReturnNoData::Info(s) => {
                assert_no_diagnostic(&s);
                s
            }
            ReturnNoData::NoData(_) => panic!("No Data"),
            ReturnNoData::Error(s) => panic!("{}", get_last_error(&s)),
        };
        assert_eq!(1, stmt.num_result_cols().unwrap());
        loop {
            stmt = match stmt.fetch() {
                ReturnNoData::Success(s) => s,
                ReturnNoData::Info(s) => s,
                ReturnNoData::Error(s) => {
                    panic!("Error during fetching row: {}", get_last_error(&s))
                }
                ReturnNoData::NoData(_) => break,
            };
            let mut buffer = [0u8; 256];
            if let ReturnNoData::Success(Indicator::Length(i)) =
                stmt.get_data(1, &mut buffer as &mut [u8])
            {
                assert_eq!("2001: A Space Odyssey".as_bytes(), &buffer[..(i as usize)]);
            } else {
                panic!("No field found!");
            }
        }
    }
    dbc.disconnect().unwrap();
}

/// Checks for a diagnstic record. Should one be present this function panics printing the contents
/// of said record.
fn assert_no_diagnostic(diag: &Diagnostics) {
    use std::str;
    let mut buffer = [0; 512];
    match diag.diagnostics(1, &mut buffer) {
        DiagReturn::Success(dr) | DiagReturn::Info(dr) => panic!(
            "{}",
            str::from_utf8(&buffer[0..(dr.text_length as usize)]).unwrap()
        ),
        DiagReturn::Error => panic!("Error during fetching diagnostic record"),
        DiagReturn::NoData => (),
    }
}

fn get_last_error(diag: &Diagnostics) -> String {
    use std::str;
    let mut buffer = [0; 512];
    match diag.diagnostics(1, &mut buffer) {
        DiagReturn::Success(dr) | DiagReturn::Info(dr) => str::from_utf8(
            &buffer[0..(dr.text_length as usize)],
        ).unwrap()
            .to_owned(),
        DiagReturn::Error => panic!("Error during fetching diagnostic record"),
        DiagReturn::NoData => panic!("No diagnostic available"),
    }
}
<|endoftext|>


<commit_before>extern crate array_tool;

#[test]
fn it_implements_individual_uniq_on_vec() {
    use array_tool::vec::Uniq;
    assert_eq!(
        vec![1, 2, 3, 4, 5, 6].uniq(vec![1, 2, 5, 7, 9]),
        vec![3, 4, 6]
    );
    assert_eq!(
        vec![
            1, 2, 3, 1, 3, 2, 1, 3, 1, 2, 3, 1, 2, 3, 3, 1, 2, 3, 3, 1, 2, 3, 1, 2, 3, 3, 4, 1, 5,
            4, 6
        ]
        .uniq(vec![3, 5]),
        vec![1, 2, 4, 6]
    );
}

#[test]
fn it_can_return_its_own_unique() {
    use array_tool::vec::Uniq;
    assert_eq!(
        vec![1, 2, 1, 3, 4, 3, 4, 5, 6].unique(),
        vec![1, 2, 3, 4, 5, 6]
    );
    assert_eq!(
        vec![
            1, 2, 3, 1, 3, 2, 1, 3, 1, 2, 3, 1, 2, 3, 3, 1, 2, 3, 3, 1, 2, 3, 1, 2, 3, 3, 4, 1, 5,
            4, 6
        ]
        .unique(),
        vec![1, 2, 3, 4, 5, 6]
    );
}

#[test]
fn it_answers_about_uniqueness() {
    use array_tool::vec::Uniq;
    assert_eq!(vec![1, 2, 1, 3, 4, 3, 4, 5, 6].is_unique(), false);
    assert_eq!(vec![1, 2, 3, 4, 5, 6].is_unique(), true);
}

#[test]
fn it_implements_individual_uniq_on_vec_via() {
    use array_tool::vec::Uniq;
    assert_eq!(
        vec![1.1, 2.6, 3.7, 4.7, 5.4, 6.6]
            .uniq_via(vec![1.5, 2.7, 5.0, 7.1, 9.4], |l: &f64, r: &f64| l.floor()
                == r.floor()),
        vec![3.7, 4.7, 6.6]
    );
    assert_eq!(
        vec![
            1.2, 2.5, 3.4, 1.2, 3.8, 2.9, 1.0, 3.2, 1.2, 2.5, 3.7, 1.7, 2.9, 3.1, 3.5, 1.6, 2.7,
            3.9, 3.1, 1.5, 2.6, 3.8, 1.2, 2.6, 3.7, 3.8, 4.9, 1.0, 5.1, 4.4, 6.6
        ]
        .uniq_via(vec![3.5, 5.1], |l: &f64, r: &f64| l.floor() == r.floor()),
        vec![1.2, 2.5, 2.9, 1.0, 1.7, 1.6, 2.7, 1.5, 2.6, 4.9, 4.4, 6.6]
    );
}

#[test]
fn it_can_return_its_own_unique_via() {
    use array_tool::vec::Uniq;
    assert_eq!(
        vec![1.2, 2.5, 1.4, 3.2, 4.8, 3.9, 4.0, 5.2, 6.2]
            .unique_via(|l: &f64, r: &f64| l.floor() == r.floor()),
        vec![1.2, 2.5, 3.2, 4.8, 5.2, 6.2]
    );
    assert_eq!(
        vec![
            1.2, 2.5, 3.4, 1.2, 3.8, 2.9, 1.0, 3.2, 1.2, 2.5, 3.7, 1.7, 2.9, 3.1, 3.5, 1.6, 2.7,
            3.9, 3.1, 1.5, 2.6, 3.8, 1.2, 2.6, 3.7, 3.8, 4.9, 1.0, 5.1, 4.4, 6.6
        ]
        .unique_via(|l: &f64, r: &f64| l.floor() == r.floor()),
        vec![1.2, 2.5, 3.4, 4.9, 5.1, 6.6]
    );
}

#[test]
fn it_answers_about_uniqueness_via() {
    use array_tool::vec::Uniq;
    assert_eq!(
        vec![1.2, 2.4, 1.5, 3.6, 4.1, 3.5, 4.7, 5.9, 6.5]
            .is_unique_via(|l: &f64, r: &f64| l.floor() == r.floor()),
        false
    );
    assert_eq!(
        vec![1.2, 2.4, 3.5, 4.6, 5.1, 6.5].is_unique_via(|l: &f64, r: &f64| l.floor() == r.floor()),
        true
    );
}

#[test]
fn it_shifts() {
    use array_tool::vec::Shift;
    let mut x = vec![1, 2, 3];
    x.unshift(0);
    assert_eq!(x, vec![0, 1, 2, 3]);
    assert_eq!(x.shift(), Some(0));
    assert_eq!(x, vec![1, 2, 3]);
}

#[test]
fn it_handles_empty_shift() {
    use array_tool::vec::Shift;
    let mut x: Vec<u8> = vec![];
    assert_eq!(x.shift(), None);
}

#[test]
fn it_intersects() {
    use array_tool::vec::Intersect;
    assert_eq!(vec![1, 1, 3, 5].intersect(vec![1, 2, 3]), vec![1, 3])
}

#[allow(unused_imports)]
#[test]
fn it_intersects_if() {
    use array_tool::vec::Intersect;
    assert_eq!(
        vec!['a', 'a', 'c', 'e']
            .intersect_if(vec!['A', 'B', 'C'], |l, r| l.eq_ignore_ascii_case(r)),
        vec!['a', 'c']
    );
}

#[test]
fn it_multiplies() {
    use array_tool::vec::Times;
    assert_eq!(vec![1, 2, 3].times(3), vec![1, 2, 3, 1, 2, 3, 1, 2, 3]);

    // Empty collection
    let vec1: Vec<i32> = Vec::new();
    let vec2: Vec<i32> = Vec::new();
    assert_eq!(vec1.times(4), vec2)
}

#[test]
fn it_joins() {
    use array_tool::vec::Join;
    assert_eq!(vec![1, 2, 3].join(","), "1,2,3")
}

#[test]
fn it_creates_union() {
    use array_tool::vec::Union;
    assert_eq!(
        vec!["a", "b", "c"].union(vec!["c", "d", "a"]),
        vec!["a", "b", "c", "d"]
    );
    assert_eq!(
        vec![
            1, 2, 3, 1, 3, 2, 1, 3, 1, 2, 3, 1, 2, 3, 3, 1, 2, 3, 3, 1, 2, 3, 1, 2, 3, 3, 4, 1, 4,
            6
        ]
        .union(vec![3, 5, 7, 8, 0]),
        vec![1, 2, 3, 4, 6, 5, 7, 8, 0]
    );
}
<commit_msg>Add mutation test<commit_after>extern crate array_tool;

#[test]
fn it_implements_individual_uniq_on_vec() {
    use array_tool::vec::Uniq;
    assert_eq!(
        vec![1, 2, 3, 4, 5, 6].uniq(vec![1, 2, 5, 7, 9]),
        vec![3, 4, 6]
    );
    assert_eq!(
        vec![
            1, 2, 3, 1, 3, 2, 1, 3, 1, 2, 3, 1, 2, 3, 3, 1, 2, 3, 3, 1, 2, 3, 1, 2, 3, 3, 4, 1, 5,
            4, 6
        ]
        .uniq(vec![3, 5]),
        vec![1, 2, 4, 6]
    );
}

#[test]
fn it_doesnt_mutate_on_individual_uniq() {
    use array_tool::vec::Uniq;
    let a = vec![1, 2, 3, 4, 5, 6];
    a.uniq(vec![1, 2, 5, 7, 9]);
    assert_eq!(a, vec![1, 2, 3, 4, 5, 6]);
}

#[test]
fn it_can_return_its_own_unique() {
    use array_tool::vec::Uniq;
    assert_eq!(
        vec![1, 2, 1, 3, 4, 3, 4, 5, 6].unique(),
        vec![1, 2, 3, 4, 5, 6]
    );
    assert_eq!(
        vec![
            1, 2, 3, 1, 3, 2, 1, 3, 1, 2, 3, 1, 2, 3, 3, 1, 2, 3, 3, 1, 2, 3, 1, 2, 3, 3, 4, 1, 5,
            4, 6
        ]
        .unique(),
        vec![1, 2, 3, 4, 5, 6]
    );
}

#[test]
fn it_answers_about_uniqueness() {
    use array_tool::vec::Uniq;
    assert_eq!(vec![1, 2, 1, 3, 4, 3, 4, 5, 6].is_unique(), false);
    assert_eq!(vec![1, 2, 3, 4, 5, 6].is_unique(), true);
}

#[test]
fn it_implements_individual_uniq_on_vec_via() {
    use array_tool::vec::Uniq;
    assert_eq!(
        vec![1.1, 2.6, 3.7, 4.7, 5.4, 6.6]
            .uniq_via(vec![1.5, 2.7, 5.0, 7.1, 9.4], |l: &f64, r: &f64| l.floor()
                == r.floor()),
        vec![3.7, 4.7, 6.6]
    );
    assert_eq!(
        vec![
            1.2, 2.5, 3.4, 1.2, 3.8, 2.9, 1.0, 3.2, 1.2, 2.5, 3.7, 1.7, 2.9, 3.1, 3.5, 1.6, 2.7,
            3.9, 3.1, 1.5, 2.6, 3.8, 1.2, 2.6, 3.7, 3.8, 4.9, 1.0, 5.1, 4.4, 6.6
        ]
        .uniq_via(vec![3.5, 5.1], |l: &f64, r: &f64| l.floor() == r.floor()),
        vec![1.2, 2.5, 2.9, 1.0, 1.7, 1.6, 2.7, 1.5, 2.6, 4.9, 4.4, 6.6]
    );
}

#[test]
fn it_can_return_its_own_unique_via() {
    use array_tool::vec::Uniq;
    assert_eq!(
        vec![1.2, 2.5, 1.4, 3.2, 4.8, 3.9, 4.0, 5.2, 6.2]
            .unique_via(|l: &f64, r: &f64| l.floor() == r.floor()),
        vec![1.2, 2.5, 3.2, 4.8, 5.2, 6.2]
    );
    assert_eq!(
        vec![
            1.2, 2.5, 3.4, 1.2, 3.8, 2.9, 1.0, 3.2, 1.2, 2.5, 3.7, 1.7, 2.9, 3.1, 3.5, 1.6, 2.7,
            3.9, 3.1, 1.5, 2.6, 3.8, 1.2, 2.6, 3.7, 3.8, 4.9, 1.0, 5.1, 4.4, 6.6
        ]
        .unique_via(|l: &f64, r: &f64| l.floor() == r.floor()),
        vec![1.2, 2.5, 3.4, 4.9, 5.1, 6.6]
    );
}

#[test]
fn it_answers_about_uniqueness_via() {
    use array_tool::vec::Uniq;
    assert_eq!(
        vec![1.2, 2.4, 1.5, 3.6, 4.1, 3.5, 4.7, 5.9, 6.5]
            .is_unique_via(|l: &f64, r: &f64| l.floor() == r.floor()),
        false
    );
    assert_eq!(
        vec![1.2, 2.4, 3.5, 4.6, 5.1, 6.5].is_unique_via(|l: &f64, r: &f64| l.floor() == r.floor()),
        true
    );
}

#[test]
fn it_shifts() {
    use array_tool::vec::Shift;
    let mut x = vec![1, 2, 3];
    x.unshift(0);
    assert_eq!(x, vec![0, 1, 2, 3]);
    assert_eq!(x.shift(), Some(0));
    assert_eq!(x, vec![1, 2, 3]);
}

#[test]
fn it_handles_empty_shift() {
    use array_tool::vec::Shift;
    let mut x: Vec<u8> = vec![];
    assert_eq!(x.shift(), None);
}

#[test]
fn it_intersects() {
    use array_tool::vec::Intersect;
    assert_eq!(vec![1, 1, 3, 5].intersect(vec![1, 2, 3]), vec![1, 3])
}

#[allow(unused_imports)]
#[test]
fn it_intersects_if() {
    use array_tool::vec::Intersect;
    assert_eq!(
        vec!['a', 'a', 'c', 'e']
            .intersect_if(vec!['A', 'B', 'C'], |l, r| l.eq_ignore_ascii_case(r)),
        vec!['a', 'c']
    );
}

#[test]
fn it_multiplies() {
    use array_tool::vec::Times;
    assert_eq!(vec![1, 2, 3].times(3), vec![1, 2, 3, 1, 2, 3, 1, 2, 3]);

    // Empty collection
    let vec1: Vec<i32> = Vec::new();
    let vec2: Vec<i32> = Vec::new();
    assert_eq!(vec1.times(4), vec2)
}

#[test]
fn it_joins() {
    use array_tool::vec::Join;
    assert_eq!(vec![1, 2, 3].join(","), "1,2,3")
}

#[test]
fn it_creates_union() {
    use array_tool::vec::Union;
    assert_eq!(
        vec!["a", "b", "c"].union(vec!["c", "d", "a"]),
        vec!["a", "b", "c", "d"]
    );
    assert_eq!(
        vec![
            1, 2, 3, 1, 3, 2, 1, 3, 1, 2, 3, 1, 2, 3, 3, 1, 2, 3, 3, 1, 2, 3, 1, 2, 3, 3, 4, 1, 4,
            6
        ]
        .union(vec![3, 5, 7, 8, 0]),
        vec![1, 2, 3, 4, 6, 5, 7, 8, 0]
    );
}
<|endoftext|>


<commit_before>// http://dev.w3.org/csswg/css3-syntax/#tokenization
//
// The output of the tokenization step is a series of zero or more
// of the following tokens:
// ident, function, at-keyword, hash, string, bad-string, url, bad-url,
// delim, number, percentage, dimension, unicode-range, whitespace, comment,
// cdo, cdc, colon, semicolon, [, ], (, ), {, }.
//
// ident, function, at-keyword, hash, string, and url tokens
// have a value composed of zero or more characters.
// Delim tokens have a value composed of a single character.
// Number, percentage, and dimension tokens have a representation
// composed of 1 or more character, a numeric value,
// and a type flag set to either "integer" or "number".
// The type flag defaults to "integer" if not otherwise set.
// Dimension tokens additionally have a unit
// composed of one or more characters.
// Unicode-range tokens have a range of characters.

use cssparser;

#[deriving_eq]
enum NumericValue {
    Integer(int),
    // The spec calls this "number".
    // Use "float" instead to reduce term overloading with "number token".
    Float(float),
}
// TODO: add a NumberValue.as_float() method.

#[deriving_eq]
enum Token {
    Ident(~str),
    Function(~str),
    AtKeyword(~str),
    Hash(~str),
    String(~str),
    BadString,
    URL(~str),
    BadURL,
    Delim(char),
    Number(NumericValue, ~str),  // value, representation
    Percentage(NumericValue, ~str),  // value, representation
    Dimension(NumericValue, ~str, ~str),  // value, representation, unit
    UnicodeRange(char, char),  // start, end. XXX what about empty ranges?
    WhiteSpace,
    Comment,
    CDO,  // <!--
    CDC,  // -->
    Colon,  // ,
    Semicolon,  // ;
    OpenBraket, // [
    OpenParen, // (
    OpenBrace, // {
    CloseBraket, // ]
    CloseParen, // (
    CloseBrace, // }
}

struct State {
    input: ~str,
    mut position: uint,
    errors: ~[~str]
}

fn is_eof(state: &State) -> bool {
    state.input[state.position] == 0
}

fn consume_char(state: &State) -> char {
    let range = str::char_range_at(state.input, state.position);
    state.position = range.next;
    range.ch
}

// http://dev.w3.org/csswg/css3-syntax/#tokenization
fn tokenize(input: &str//, transform_function_whitespace: bool,
//            quirks_mode: bool
            ) -> ~[Token] {
    let state = &State {
        input: cssparser::preprocess(input) + "\x00",
        position: 0, errors: ~[] };
    let mut tokens: ~[Token] = ~[];

    // 3.3.4. Data state
    while !is_eof(state) {
        tokens.push(match consume_char(state) {
            c => Delim(c),
        })
    }
    tokens
}

#[test]
fn test_tokenizer() {
    fn assert_tokens(input: &str, expected: &[Token]) {
        let result: &[Token] = tokenize(input//, false, false
        );
        if result != expected {
            fail fmt!("%? != %?", result, expected);
        }
    }
    assert_tokens("", []);
    assert_tokens(",", [Delim(',')]);
}
<commit_msg>Add comments.<commit_after>// http://dev.w3.org/csswg/css3-syntax/#tokenization
//
// The output of the tokenization step is a series of zero or more
// of the following tokens:
// ident, function, at-keyword, hash, string, bad-string, url, bad-url,
// delim, number, percentage, dimension, unicode-range, whitespace, comment,
// cdo, cdc, colon, semicolon, [, ], (, ), {, }.
//
// ident, function, at-keyword, hash, string, and url tokens
// have a value composed of zero or more characters.
// Delim tokens have a value composed of a single character.
// Number, percentage, and dimension tokens have a representation
// composed of 1 or more character, a numeric value,
// and a type flag set to either "integer" or "number".
// The type flag defaults to "integer" if not otherwise set.
// Dimension tokens additionally have a unit
// composed of one or more characters.
// Unicode-range tokens have a range of characters.

use cssparser;

#[deriving_eq]
enum NumericValue {
    Integer(int),
    // The spec calls this "number".
    // Use "float" instead to reduce term overloading with "number token".
    Float(float),
}
// TODO: add a NumberValue.as_float() method.

#[deriving_eq]
enum Token {
    Ident(~str),
    Function(~str),
    AtKeyword(~str),
    Hash(~str),
    String(~str),
    BadString,
    URL(~str),
    BadURL,
    Delim(char),
    Number(NumericValue, ~str),  // value, representation
    Percentage(NumericValue, ~str),  // value, representation
    Dimension(NumericValue, ~str, ~str),  // value, representation, unit
    UnicodeRange(char, char),  // start, end. XXX what about empty ranges?
    WhiteSpace,
    Comment,
    CDO,  // <!--
    CDC,  // -->
    Colon,  // ,
    Semicolon,  // ;
    OpenBraket, // [
    OpenParen, // (
    OpenBrace, // {
    CloseBraket, // ]
    CloseParen, // (
    CloseBrace, // }
}

struct State {
    input: ~str,
    mut position: uint,
    mut errors: ~[~str]
}

fn is_eof(state: &State) -> bool {
    state.input[state.position] == 0
}

fn current_char(state: &State) -> char {
    str::char_at(state.input, state.position)
}

fn consume_char(state: &State) -> char {
    let range = str::char_range_at(state.input, state.position);
    state.position = range.next;
    range.ch
}

// 3.3.9. Comment state
fn consume_comment(state: &State) -> Token {
    state.position += 1;  // consume the * in /*
    match str::find_str_from(state.input, "*/", state.position) {
        Some(end_position) => state.position = end_position + 2,
        None => {
            state.errors.push(~"EOF in comment");
            state.position = state.input.len() - 1;
        }
    }
    Comment
}

// http://dev.w3.org/csswg/css3-syntax/#tokenization
fn tokenize(input: &str//, transform_function_whitespace: bool,
//            quirks_mode: bool
            ) -> {tokens: ~[Token], parse_errors: ~[~str]} {
    // preprocess() ensures there is no NULL byte, so we can use that
    // as an EOF marker.
    let state = &State {
        input: cssparser::preprocess(input) + "\x00",
        position: 0, errors: ~[] };
    let mut tokens: ~[Token] = ~[];

    // 3.3.4. Data state
    while !is_eof(state) {
        tokens.push(match consume_char(state) {
            '/' if current_char(state) == '*' => consume_comment(state),
            c => Delim(c),
        })
    }

    // Work around `error: moving out of mutable field`
    // TODO: find a cleaner way.
    let mut errors: ~[~str] = ~[];
    errors <-> state.errors;
    {tokens: tokens, parse_errors: errors}
}

#[test]
fn test_tokenizer() {
    fn assert_tokens(input: &str, expected_tokens: &[Token],
                     expected_errors: &[~str]) {
        let result = tokenize(input//, false, false
        );
        let tokens: &[Token] = result.tokens;
        let parse_errors: &[~str] = result.parse_errors;
        if tokens != expected_tokens {
            fail fmt!("%? != %?", tokens, expected_tokens);
        }
        if parse_errors != expected_errors {
            fail fmt!("%? != %?", tokens, expected_errors);
        }
    }
    assert_tokens("", [], []);
    assert_tokens(",/", [Delim(','), Delim('/')], []);
    assert_tokens(",/* Li/*psum… */", [Delim(','), Comment], []);
    assert_tokens(",/* Li/*psum… *//", [Delim(','), Comment, Delim('/')], []);
    assert_tokens(",/* Lipsum", [Delim(','), Comment], [~"EOF in comment"]);
    assert_tokens(",/*", [Delim(','), Comment], [~"EOF in comment"]);
}
<|endoftext|>


<commit_before>use std::fmt;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};

// A network
#[derive(Debug)]
pub enum IpNetwork {
    V4(Ipv4Network),
    V6(Ipv6Network),
}

pub struct Ipv4Network {
    addr: Ipv4Addr,
    prefix: u8,
}

pub struct Ipv6Network {
    addr: Ipv6Addr,
    prefix: u8,
}

impl Ipv4Network {
    fn new(addr: Ipv4Addr, prefix: u8) -> Ipv4Network {
        Ipv4Network { addr: addr, prefix: prefix }
    }

    fn ip(&self) -> &Ipv4Addr {
        &(self.addr)
    }

    fn prefix(&self) -> u8 {
        self.prefix
    }

    fn mask(&self) -> u32 {
        let prefix = self.prefix;
        !(0xffffffff >> prefix)
    }

    fn mask_to_string(&self) -> String {
        let mask = self.mask();
        Ipv4Network::int_to_ip(mask).to_string()
    }

    fn ip_to_int(addr: Ipv4Addr) -> u32 {
        let ip = addr.octets();
        (ip[0] as u32) << 24 + (ip[1] as u32) << 16 + (ip[2] as u32) << 8 + (ip[3] as u32)
    }

    fn int_to_ip(ip: u32) -> Ipv4Addr {
        Ipv4Addr::new(((ip >> 24) & 0xff) as u8, ((ip >> 16) & 0xff) as u8,
                     ((ip >> 8) & 0xff) as u8, (ip & 0xff) as u8)
    }
}

impl Ipv6Network {
    fn new(addr: Ipv6Addr, prefix: u8) -> Ipv6Network {
        Ipv6Network { addr: addr, prefix: prefix }
    }

    fn ip(&self) -> &Ipv6Addr {
        &(self.addr)
    }

    fn prefix(&self) -> u8 {
        self.prefix
    }
}

impl IpNetwork {
    pub fn new(ip: IpAddr, prefix: u8) -> IpNetwork {
        match ip {
            IpAddr::V4(a) => IpNetwork::V4(Ipv4Network::new(a, prefix)),
            IpAddr::V6(a) => IpNetwork::V6(Ipv6Network::new(a, prefix)),
        }
    }

    pub fn ip(&self) -> IpAddr {
        match *self {
            IpNetwork::V4(ref a) => IpAddr::V4(*a.ip()),
            IpNetwork::V6(ref a) => IpAddr::V6(*a.ip()),
        }
    }

    pub fn prefix(&self) -> u8 {
        match *self {
            IpNetwork::V4(ref a) => a.prefix(),
            IpNetwork::V6(ref a) => a.prefix(),
        }
    }
}

impl fmt::Debug for Ipv4Network {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}/{}", self.ip(), self.prefix())
    }
}

impl fmt::Debug for Ipv6Network {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}/{}", self.ip(), self.prefix())
    }
}

#[cfg(test)]
mod test {
    use std::net::{Ipv4Addr, Ipv6Addr};
    use super::*;

    #[test]
    fn create_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(77, 88, 21, 11), 24);
        assert_eq!(cidr.prefix(), 24);
    }

    #[test]
    fn create_v6() {
        let cidr = Ipv6Network::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 24);
        assert_eq!(cidr.prefix(), 24);
    }

    #[test]
    fn mask_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(74, 125, 227, 0), 29);
        assert_eq!(cidr.mask(), 4294967288);
    }

    #[test]
    fn mask_string_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(74, 125, 227, 0), 29);
        assert_eq!(cidr.mask_to_string(), "255.255.255.248");
    }
}
<commit_msg>Add a method to get network address as an int<commit_after>use std::fmt;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};

// A network
#[derive(Debug)]
pub enum IpNetwork {
    V4(Ipv4Network),
    V6(Ipv6Network),
}

pub struct Ipv4Network {
    addr: Ipv4Addr,
    prefix: u8,
}

pub struct Ipv6Network {
    addr: Ipv6Addr,
    prefix: u8,
}

impl Ipv4Network {
    fn new(addr: Ipv4Addr, prefix: u8) -> Ipv4Network {
        Ipv4Network { addr: addr, prefix: prefix }
    }

    fn ip(&self) -> &Ipv4Addr {
        &(self.addr)
    }

    fn prefix(&self) -> u8 {
        self.prefix
    }

    fn mask(&self) -> u32 {
        let prefix = self.prefix;
        !(0xffffffff >> prefix)
    }

    fn mask_to_string(&self) -> String {
        let mask = self.mask();
        Ipv4Network::int_to_ip(mask).to_string()
    }

    fn network_int(&self) -> u32 {
        Ipv4Network::ip_to_int(*(self.ip())) & self.mask()
    }

    fn ip_to_int(addr: Ipv4Addr) -> u32 {
        let ip = addr.octets();
        ((ip[0] as u32) << 24) + ((ip[1] as u32) << 16) + ((ip[2] as u32) << 8) + (ip[3] as u32)
    }

    fn int_to_ip(ip: u32) -> Ipv4Addr {
        Ipv4Addr::new(((ip >> 24) & 0xff) as u8, ((ip >> 16) & 0xff) as u8,
                     ((ip >> 8) & 0xff) as u8, (ip & 0xff) as u8)
    }
}

impl Ipv6Network {
    fn new(addr: Ipv6Addr, prefix: u8) -> Ipv6Network {
        Ipv6Network { addr: addr, prefix: prefix }
    }

    fn ip(&self) -> &Ipv6Addr {
        &(self.addr)
    }

    fn prefix(&self) -> u8 {
        self.prefix
    }
}

impl IpNetwork {
    pub fn new(ip: IpAddr, prefix: u8) -> IpNetwork {
        match ip {
            IpAddr::V4(a) => IpNetwork::V4(Ipv4Network::new(a, prefix)),
            IpAddr::V6(a) => IpNetwork::V6(Ipv6Network::new(a, prefix)),
        }
    }

    pub fn ip(&self) -> IpAddr {
        match *self {
            IpNetwork::V4(ref a) => IpAddr::V4(*a.ip()),
            IpNetwork::V6(ref a) => IpAddr::V6(*a.ip()),
        }
    }

    pub fn prefix(&self) -> u8 {
        match *self {
            IpNetwork::V4(ref a) => a.prefix(),
            IpNetwork::V6(ref a) => a.prefix(),
        }
    }
}

impl fmt::Debug for Ipv4Network {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}/{}", self.ip(), self.prefix())
    }
}

impl fmt::Debug for Ipv6Network {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}/{}", self.ip(), self.prefix())
    }
}

#[cfg(test)]
mod test {
    use std::net::{Ipv4Addr, Ipv6Addr};
    use super::*;

    #[test]
    fn create_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(77, 88, 21, 11), 24);
        assert_eq!(cidr.prefix(), 24);
    }

    #[test]
    fn create_v6() {
        let cidr = Ipv6Network::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 24);
        assert_eq!(cidr.prefix(), 24);
    }

    #[test]
    fn mask_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(74, 125, 227, 0), 29);
        assert_eq!(cidr.mask(), 4294967288);
    }

    #[test]
    fn mask_string_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(74, 125, 227, 0), 29);
        assert_eq!(cidr.mask_to_string(), "255.255.255.248");
    }

    #[test]
    fn network_as_int() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(74, 125, 227, 0), 25);
        assert_eq!(cidr.network_int(), 1249764096);
    }
}
<|endoftext|>


<commit_before>use super::plumbing::*;
use super::*;
use std::cmp::min;

/// `Take` is an iterator that iterates over the first `n` elements.
/// This struct is created by the [`take()`] method on [`ParallelIterator`]
///
/// [`take()`]: trait.ParallelIterator.html#method.take
/// [`ParallelIterator`]: trait.ParallelIterator.html
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Debug, Clone)]
pub struct Take<I> {
    base: I,
    n: usize,
}

/// Create a new `Take` iterator.
///
/// NB: a free fn because it is NOT part of the end-user API.
pub fn new<I>(mut base: I, n: usize) -> Take<I>
    where I: IndexedParallelIterator
{
    let n = min(base.len(), n);
    Take { base: base, n: n }
}

impl<I> ParallelIterator for Take<I>
    where I: IndexedParallelIterator
{
    type Item = I::Item;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        bridge(self, consumer)
    }

    fn opt_len(&mut self) -> Option<usize> {
        Some(self.len())
    }
}

impl<I> IndexedParallelIterator for Take<I>
    where I: IndexedParallelIterator
{
    fn len(&mut self) -> usize {
        self.n
    }

    fn drive<C: Consumer<Self::Item>>(self, consumer: C) -> C::Result {
        bridge(self, consumer)
    }

    fn with_producer<CB>(self, callback: CB) -> CB::Output
        where CB: ProducerCallback<Self::Item>
    {
        return self.base.with_producer(Callback {
                                           callback: callback,
                                           n: self.n,
                                       });

        struct Callback<CB> {
            callback: CB,
            n: usize,
        }

        impl<T, CB> ProducerCallback<T> for Callback<CB>
            where CB: ProducerCallback<T>
        {
            type Output = CB::Output;
            fn callback<P>(self, base: P) -> CB::Output
                where P: Producer<Item = T>
            {
                let (producer, _) = base.split_at(self.n);
                self.callback.callback(producer)
            }
        }
    }
}
<commit_msg>take is a function on IndexedParallelIterator<commit_after>use super::plumbing::*;
use super::*;
use std::cmp::min;

/// `Take` is an iterator that iterates over the first `n` elements.
/// This struct is created by the [`take()`] method on [`IndexedParallelIterator`]
///
/// [`take()`]: trait.IndexedParallelIterator.html#method.take
/// [`IndexedParallelIterator`]: trait.IndexedParallelIterator.html
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Debug, Clone)]
pub struct Take<I> {
    base: I,
    n: usize,
}

/// Create a new `Take` iterator.
///
/// NB: a free fn because it is NOT part of the end-user API.
pub fn new<I>(mut base: I, n: usize) -> Take<I>
    where I: IndexedParallelIterator
{
    let n = min(base.len(), n);
    Take { base: base, n: n }
}

impl<I> ParallelIterator for Take<I>
    where I: IndexedParallelIterator
{
    type Item = I::Item;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        bridge(self, consumer)
    }

    fn opt_len(&mut self) -> Option<usize> {
        Some(self.len())
    }
}

impl<I> IndexedParallelIterator for Take<I>
    where I: IndexedParallelIterator
{
    fn len(&mut self) -> usize {
        self.n
    }

    fn drive<C: Consumer<Self::Item>>(self, consumer: C) -> C::Result {
        bridge(self, consumer)
    }

    fn with_producer<CB>(self, callback: CB) -> CB::Output
        where CB: ProducerCallback<Self::Item>
    {
        return self.base.with_producer(Callback {
                                           callback: callback,
                                           n: self.n,
                                       });

        struct Callback<CB> {
            callback: CB,
            n: usize,
        }

        impl<T, CB> ProducerCallback<T> for Callback<CB>
            where CB: ProducerCallback<T>
        {
            type Output = CB::Output;
            fn callback<P>(self, base: P) -> CB::Output
                where P: Producer<Item = T>
            {
                let (producer, _) = base.split_at(self.n);
                self.callback.callback(producer)
            }
        }
    }
}
<|endoftext|>


<commit_before>use asm_ops::*;
use asm_ops::AsmOp::*;
use asm_ops::AsmOperand::*;

fn optimize_stmt(op: AsmOp, previous: AsmOp) -> (AsmOp, AsmOp){
    //fn remains() -> (AsmOp, AsmOp)
    match (&previous, &op){
        //From push rax; pop rbx
        //To mov rbx, rax
        (&Push(ref l), &Pop(ref r)) => {
            match (l , r) {
                (&Memory(_), &Memory(_)) | (&MemoryRegister(_), &MemoryRegister(_)) |
                 (&Memory(_), &MemoryRegister(_)) | (&MemoryRegister(_), &Memory(_)) =>
                    (previous.clone(), op.clone()), //can't mov [], [] -- skip it on
                _ if l == r => (Nop, Nop), // push rax; pop rax
                _ => (Mov(r.clone(), l.clone()), Nop),
            }
        },
        //From mov rax, ... ; push rax
        //To push ...
        (&Mov(ref before, ref needed), &Push(ref after)) if before == after => match before {
            &Memory(_) => (previous.clone(), op.clone()),
            _ => (Push(needed.clone()), Nop)
        },
        (_,_) => (previous.clone(), op.clone())
    }
}

pub fn optimize(mut _ops: Vec<AsmOp>, iters: u8) -> Vec<AsmOp>{
    let mut changed = true;
    let mut iterations = 0;
    while changed && iterations < iters {
        iterations += 1;
        changed = false;
        let mut ops: Vec<AsmOp> = Vec::new();
        let mut previous = _ops.remove(0);
        for op in _ops{
            let (optimized, pre) = optimize_stmt(op.clone(), previous);
            ops.push(optimized);
            previous = pre;
            if previous == Nop{
                changed = true;
            }
        }
        ops.push(previous);
        ops.retain(|ref i|**i != Nop);
        _ops = ops;
    }

    println!("It took {} iterations to optimize IR code.", iterations);
    _ops
}
<commit_msg>Introduced a fancy macro<commit_after>use asm_ops::*;
use asm_ops::AsmOp::*;
use asm_ops::AsmOperand::*;
macro_rules! enum_shuffle(
    (($l:expr, $r:expr) when ($sp1:pat , $sp2:pat) -> ($success:expr) $(or when ($sp_or:pat) $(if ($cond:expr))* -> ($failure:expr))*) =>(
        match ($l, $r) {
            ($sp1, $sp1) | ($sp1, $sp2) | ($sp2, $sp1) | ($sp2, $sp2) => $success,
            $($sp_or $(if $cond)* => $failure,)*
        }
    )
);

fn optimize_stmt(op: AsmOp, previous: AsmOp) -> (AsmOp, AsmOp){
    //fn remains() -> (AsmOp, AsmOp)
    match (&previous, &op){
        //From push rax; pop rbx
        //To mov rbx, rax
        (&Push(ref l), &Pop(ref r)) => {
            enum_shuffle!((l, r)
                when (&Memory(_), &MemoryRegister(_)) -> ((previous.clone(), op.clone())) or //can't mov [], [] -- skip it on
                when (_) if (l == r) -> ((Nop, Nop)) or                                      //push rax; pop rax
                when (_) -> ((Mov(r.clone(), l.clone()), Nop))                               //finally, if it fits, transform into mov r, l
            )
        },
        //From mov rax, ... ; push rax
        //To push ...
        (&Mov(ref before, ref needed), &Push(ref after)) if before == after => match before {
            &Memory(_) => (previous.clone(), op.clone()),
            _ => (Push(needed.clone()), Nop)
        },
        (_,_) => (previous.clone(), op.clone())
    }
}

pub fn optimize(mut _ops: Vec<AsmOp>, iters: u8) -> Vec<AsmOp>{
    let mut changed = true;
    let mut iterations = 0;
    while changed && iterations < iters {
        iterations += 1;
        changed = false;
        let mut ops: Vec<AsmOp> = Vec::new();
        let mut previous = _ops.remove(0);
        for op in _ops{
            let (optimized, pre) = optimize_stmt(op.clone(), previous);
            ops.push(optimized);
            previous = pre;
            if previous == Nop{
                changed = true;
            }
        }
        ops.push(previous);
        ops.retain(|ref i|**i != Nop);
        _ops = ops;
    }

    println!("It took {} iterations to optimize IR code.", iterations);
    _ops
}
<|endoftext|>


<commit_before>use errors;

// see OSC Type Tag String: http://opensoundcontrol.org/spec-1_0
// padding: zero bytes (n*4)
pub enum OscType {
    OscInt(i32),
    OscFloat(f32),
    OscString(String),
    OscBlob(Vec<u8>),
    OscTime(u32, u32),
    // nonstandard argument types
    // ignore them if not implemented
    OscLong(i64),
    OscDouble(f64),
    OscChar(u8),
    OscColor(u32),  // byte-order: RGBA
    OscMidi(OscMidiType),
    OscTrue,
    OscFalse,
    OscNil,
    OscInf,
    OscArray(Vec<OscType>),
}

pub struct OscMidiType {
    port: u8,
    status: u8,
    data1: u8, // maybe use an enum for data?
    data2: u8,
}

/// An *osc packet* can contain an *osc message* or a bundle of nested messages
/// which is called *osc bundle*.
pub enum OscPacket {
    Message(OscMessage),
    Bundle(OscBundle),
}

pub struct OscMessage;
pub struct OscBundle;

pub type OscResult<T> = Result<T, errors::OscError>;<commit_msg>Define `OscMessage` and `OscBundle` structs<commit_after>use errors;

// see OSC Type Tag String: http://opensoundcontrol.org/spec-1_0
// padding: zero bytes (n*4)
pub enum OscType {
    OscInt(i32),
    OscFloat(f32),
    OscString(String),
    OscBlob(Vec<u8>),
    OscTime(u32, u32),
    // nonstandard argument types
    // ignore them if not implemented
    OscLong(i64),
    OscDouble(f64),
    OscChar(u8),
    OscColor(u32),  // byte-order: RGBA
    OscMidi(OscMidiType),
    OscTrue,
    OscFalse,
    OscNil,
    OscInf,
    OscArray(Vec<OscType>),
}

pub struct OscMidiType {
    port: u8,
    status: u8,
    data1: u8, // maybe use an enum for data?
    data2: u8,
}

/// An *osc packet* can contain an *osc message* or a bundle of nested messages
/// which is called *osc bundle*.
pub enum OscPacket {
    Message(OscMessage),
    Bundle(OscBundle),
}

pub struct OscMessage {
    pub addr: String,
    pub args: Option<Vec<OscType>>,
}

pub struct OscBundle {
    pub timetag: OscType,
    pub content: Vec<OscPacket>,
}

pub type OscResult<T> = Result<T, errors::OscError>;<|endoftext|>