<commit_before>#![feature(plugin_registrar, box_syntax)]
#![feature(rustc_private, collections)]
#![allow(unused_imports)]

#[macro_use]
extern crate syntax;
#[macro_use]
extern crate rustc;

// Only for the compile time checking of paths
extern crate collections;

use rustc::plugin::Registry;
use rustc::lint::LintPassObject;

#[macro_use]
pub mod utils;
pub mod types;
pub mod misc;
pub mod eq_op;
pub mod bit_mask;
pub mod ptr_arg;
pub mod needless_bool;
pub mod approx_const;
pub mod eta_reduction;
pub mod identity_op;
pub mod mut_mut;
pub mod len_zero;
pub mod attrs;
pub mod collapsible_if;
pub mod unicode;
pub mod strings;
pub mod methods;
pub mod returns;
pub mod lifetimes;
pub mod loops;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_lint_pass(box types::TypePass as LintPassObject);
    reg.register_lint_pass(box misc::MiscPass as LintPassObject);
    reg.register_lint_pass(box misc::TopLevelRefPass as LintPassObject);
    reg.register_lint_pass(box misc::CmpNan as LintPassObject);
    reg.register_lint_pass(box eq_op::EqOp as LintPassObject);
    reg.register_lint_pass(box bit_mask::BitMask as LintPassObject);
    reg.register_lint_pass(box ptr_arg::PtrArg as LintPassObject);
    reg.register_lint_pass(box needless_bool::NeedlessBool as LintPassObject);
    reg.register_lint_pass(box approx_const::ApproxConstant as LintPassObject);
    reg.register_lint_pass(box misc::FloatCmp as LintPassObject);
    reg.register_lint_pass(box misc::Precedence as LintPassObject);
    reg.register_lint_pass(box eta_reduction::EtaPass as LintPassObject);
    reg.register_lint_pass(box identity_op::IdentityOp as LintPassObject);
    reg.register_lint_pass(box mut_mut::MutMut as LintPassObject);
    reg.register_lint_pass(box len_zero::LenZero as LintPassObject);
    reg.register_lint_pass(box misc::CmpOwned as LintPassObject);
    reg.register_lint_pass(box attrs::AttrPass as LintPassObject);
    reg.register_lint_pass(box collapsible_if::CollapsibleIf as LintPassObject);
    reg.register_lint_pass(box misc::ModuloOne as LintPassObject);
    reg.register_lint_pass(box unicode::Unicode as LintPassObject);
    reg.register_lint_pass(box strings::StringAdd as LintPassObject);
    reg.register_lint_pass(box returns::ReturnPass as LintPassObject);
    reg.register_lint_pass(box methods::MethodsPass as LintPassObject);
    reg.register_lint_pass(box types::LetPass as LintPassObject);
    reg.register_lint_pass(box loops::LoopsPass as LintPassObject);
    reg.register_lint_pass(box lifetimes::LifetimePass as LintPassObject);

    reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST,
                                           misc::SINGLE_MATCH,
                                           misc::TOPLEVEL_REF_ARG, eq_op::EQ_OP,
                                           bit_mask::BAD_BIT_MASK,
                                           bit_mask::INEFFECTIVE_BIT_MASK,
                                           ptr_arg::PTR_ARG,
                                           needless_bool::NEEDLESS_BOOL,
                                           approx_const::APPROX_CONSTANT,
                                           misc::CMP_NAN, misc::FLOAT_CMP,
                                           misc::PRECEDENCE, misc::CMP_OWNED,
                                           eta_reduction::REDUNDANT_CLOSURE,
                                           identity_op::IDENTITY_OP,
                                           mut_mut::MUT_MUT,
                                           len_zero::LEN_ZERO,
                                           len_zero::LEN_WITHOUT_IS_EMPTY,
                                           attrs::INLINE_ALWAYS,
                                           collapsible_if::COLLAPSIBLE_IF,
                                           unicode::ZERO_WIDTH_SPACE,
                                           unicode::NON_ASCII_LITERAL,
                                           strings::STRING_ADD_ASSIGN,
                                           returns::NEEDLESS_RETURN,
                                           misc::MODULO_ONE,
                                           methods::OPTION_UNWRAP_USED,
                                           methods::RESULT_UNWRAP_USED,
                                           methods::STR_TO_STRING,
                                           methods::STRING_TO_STRING,
                                           types::LET_UNIT_VALUE,
                                           lifetimes::NEEDLESS_LIFETIMES,
                                           loops::NEEDLESS_RANGE_LOOP,
                                           ]);
}
<commit_msg>added `string_add` to `clippy` lint group<commit_after>#![feature(plugin_registrar, box_syntax)]
#![feature(rustc_private, collections)]
#![allow(unused_imports)]

#[macro_use]
extern crate syntax;
#[macro_use]
extern crate rustc;

// Only for the compile time checking of paths
extern crate collections;

use rustc::plugin::Registry;
use rustc::lint::LintPassObject;

#[macro_use]
pub mod utils;
pub mod types;
pub mod misc;
pub mod eq_op;
pub mod bit_mask;
pub mod ptr_arg;
pub mod needless_bool;
pub mod approx_const;
pub mod eta_reduction;
pub mod identity_op;
pub mod mut_mut;
pub mod len_zero;
pub mod attrs;
pub mod collapsible_if;
pub mod unicode;
pub mod strings;
pub mod methods;
pub mod returns;
pub mod lifetimes;
pub mod loops;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_lint_pass(box types::TypePass as LintPassObject);
    reg.register_lint_pass(box misc::MiscPass as LintPassObject);
    reg.register_lint_pass(box misc::TopLevelRefPass as LintPassObject);
    reg.register_lint_pass(box misc::CmpNan as LintPassObject);
    reg.register_lint_pass(box eq_op::EqOp as LintPassObject);
    reg.register_lint_pass(box bit_mask::BitMask as LintPassObject);
    reg.register_lint_pass(box ptr_arg::PtrArg as LintPassObject);
    reg.register_lint_pass(box needless_bool::NeedlessBool as LintPassObject);
    reg.register_lint_pass(box approx_const::ApproxConstant as LintPassObject);
    reg.register_lint_pass(box misc::FloatCmp as LintPassObject);
    reg.register_lint_pass(box misc::Precedence as LintPassObject);
    reg.register_lint_pass(box eta_reduction::EtaPass as LintPassObject);
    reg.register_lint_pass(box identity_op::IdentityOp as LintPassObject);
    reg.register_lint_pass(box mut_mut::MutMut as LintPassObject);
    reg.register_lint_pass(box len_zero::LenZero as LintPassObject);
    reg.register_lint_pass(box misc::CmpOwned as LintPassObject);
    reg.register_lint_pass(box attrs::AttrPass as LintPassObject);
    reg.register_lint_pass(box collapsible_if::CollapsibleIf as LintPassObject);
    reg.register_lint_pass(box misc::ModuloOne as LintPassObject);
    reg.register_lint_pass(box unicode::Unicode as LintPassObject);
    reg.register_lint_pass(box strings::StringAdd as LintPassObject);
    reg.register_lint_pass(box returns::ReturnPass as LintPassObject);
    reg.register_lint_pass(box methods::MethodsPass as LintPassObject);
    reg.register_lint_pass(box types::LetPass as LintPassObject);
    reg.register_lint_pass(box loops::LoopsPass as LintPassObject);
    reg.register_lint_pass(box lifetimes::LifetimePass as LintPassObject);

    reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST,
                                           misc::SINGLE_MATCH,
                                           misc::TOPLEVEL_REF_ARG, eq_op::EQ_OP,
                                           bit_mask::BAD_BIT_MASK,
                                           bit_mask::INEFFECTIVE_BIT_MASK,
                                           ptr_arg::PTR_ARG,
                                           needless_bool::NEEDLESS_BOOL,
                                           approx_const::APPROX_CONSTANT,
                                           misc::CMP_NAN, misc::FLOAT_CMP,
                                           misc::PRECEDENCE, misc::CMP_OWNED,
                                           eta_reduction::REDUNDANT_CLOSURE,
                                           identity_op::IDENTITY_OP,
                                           mut_mut::MUT_MUT,
                                           len_zero::LEN_ZERO,
                                           len_zero::LEN_WITHOUT_IS_EMPTY,
                                           attrs::INLINE_ALWAYS,
                                           collapsible_if::COLLAPSIBLE_IF,
                                           unicode::ZERO_WIDTH_SPACE,
                                           unicode::NON_ASCII_LITERAL,
                                           strings::STRING_ADD_ASSIGN,
                                           strings::STRING_ADD,
                                           returns::NEEDLESS_RETURN,
                                           misc::MODULO_ONE,
                                           methods::OPTION_UNWRAP_USED,
                                           methods::RESULT_UNWRAP_USED,
                                           methods::STR_TO_STRING,
                                           methods::STRING_TO_STRING,
                                           types::LET_UNIT_VALUE,
                                           lifetimes::NEEDLESS_LIFETIMES,
                                           loops::NEEDLESS_RANGE_LOOP,
                                           ]);
}
<|endoftext|>


<commit_before>extern crate num;

pub mod core;

use std::convert::{Into, From, AsRef};
use std::ops::{Add, Mul, Div};
use std::marker::PhantomData;
use num::{Float, FromPrimitive};

use core::BezCubePoly;

macro_rules! npoint_ops {
    ($lhs:ty; $rhs:ty = $output:ident<$g_name:ident: $g_ty:ident> {$($field:ident),*}) => {
        impl<$g_name: $g_ty> Add<$rhs> for $lhs {
            type Output = $output<$g_name>;

            fn add(self, rhs: $rhs) -> $output<$g_name> {
                $output {
                    $($field: self.$field + rhs.$field),*
                }
            }
        }
    }
}

macro_rules! impl_npoint {
    // auxiliary/entry point workaround made by durka42
    // read the last rule of the macro first
    (@go $dims: expr; $name:ident<$g_name:ident: $g_ty:ident> {$($field:ident: $f_ty:ty),*} $fields:tt $(,$sibling:ty)*) => {
                                                              // ^ match the first duplicate of the fields
                                                                                // ^ keep the second one as a tt
        #[derive(Debug, Clone, Copy)]
        pub struct $name<$g_name: $g_ty> {
            $(
                pub $field: $f_ty
            ),*
        }

        impl<$g_name: $g_ty> Into<[$g_name; $dims]> for $name<$g_name> {
            fn into(self) -> [$g_name; $dims] {
                [$(self.$field),*]
            }
        }

        impl<$g_name: $g_ty> Into<($($f_ty),*)> for $name<$g_name> {
            fn into(self) -> (F, F) {
                ($(self.$field),*)
            }
        }

        npoint_ops!($name<$g_name>; $name<$g_name> = $name<$g_name: $g_ty> {x, y});

        $(
            // pass the tt-wrapped fields to auxiliary macro
            impl_npoint!(@sib $name $g_name $g_ty $sibling $fields);
            npoint_ops!($name<$g_name>; $sibling = $name<$g_name: $g_ty> {x, y});
        )*
    };

    // auxiliary rule
    (@sib $name:ident $g_name:ident $g_ty:ident $sibling:ty {$($field:ident: $f_ty:ty),*}) => {
                                                // ^ finally destructure fields out of tt here
        impl<$g_name: $g_ty> From<$sibling> for $name<$g_name> {
            fn from(sib: $sibling) -> $name<$g_name> {
                $name {
                    $($field: sib.$field),*
                }
            }
        }
    };

    // entry point rule
    ($dims: expr; $name:ident<$g_name:ident: $g_ty:ident> $fields:tt $(,$sibling:ty)*) => {
                                                          // ^ match fields all together as a tt
        impl_npoint!(@go
            $dims;
            $name<$g_name: $g_ty>
            $fields // duplicate the fields
            $fields
            $(,$sibling)*
        );
    };
}

impl_npoint!{2; Point<F: Float> {
    x: F,
    y: F
}, Vector<F>}

impl_npoint!{2; Vector<F: Float> {
    x: F,
    y: F
}, Point<F>}

impl<F: Float> Vector<F> {
    pub fn len(self) -> F {
        (self.x.powi(2) + self.y.powi(2)).sqrt()
    }

    pub fn normalize(self) -> Vector<F> {
        self / self.len()
    }
}

impl<F: Float> Mul<F> for Vector<F> {
    type Output = Vector<F>;

    fn mul(self, rhs: F) -> Vector<F> {
        Vector {
            x: self.x * rhs,
            y: self.y * rhs
        }
    }
}

impl<F: Float> Div<F> for Vector<F> {
    type Output = Vector<F>;

    fn div(self, rhs: F) -> Vector<F> {
        Vector {
            x: self.x / rhs,
            y: self.y / rhs
        }
    }
}

#[derive(Debug, Clone, Copy)]
pub enum BezNode<F: Float> {
    Point {
        x: F,
        y: F
    },

    Control {
        x: F,
        y: F
    }
}

impl<F: Float> BezNode<F> {
    pub fn new_point(x: F, y: F) -> BezNode<F> {
        BezNode::Point {
            x: x,
            y: y
        }
    }

    pub fn new_control(x: F, y: F) -> BezNode<F> {
        BezNode::Control {
            x: x,
            y: y
        }
    }

    pub fn x(self) -> F {
        <BezNode<F> as Into<(F, F)>>::into(self).0
    }

    pub fn y(self) -> F {
        <BezNode<F> as Into<(F, F)>>::into(self).1
    }

    pub fn is_point(self) -> bool {
        use self::BezNode::*;
        match self {
            Point{..} => true,
            Control{..} => false
        }
    }

    pub fn is_control(self) -> bool {
        use self::BezNode::*;
        match self {
            Point{..} => false,
            Control{..} => true
        }
    }
}

impl<F: Float> Into<[F; 2]> for BezNode<F> {
    fn into(self) -> [F; 2] {
        use self::BezNode::*;

        match self {
            Point{x, y}    |
            Control{x, y} => [x, y]
        }
    }
}

impl<F: Float> Into<(F, F)> for BezNode<F> {
    fn into(self) -> (F, F) {
        use self::BezNode::*;

        match self {
            Point{x, y}    |
            Control{x, y} => (x, y)
        }
    }
}

#[derive(Debug, Clone)]
pub struct BezCube<F: Float + FromPrimitive> {
    pub x: BezCubePoly<F>,
    pub y: BezCubePoly<F>
}

impl<F: Float + FromPrimitive> BezCube<F> {
    pub fn interp(&self, t: F) -> Point<F> {
        Point {
            x: self.x.interp(t),
            y: self.y.interp_unbounded(t) // The interp is already checked when we call x.interp, so we don't have to do it here
        }
    }

    pub fn derivative(&self, t: F) -> Vector<F> {
        Vector {
            x: self.x.derivative(t),
            y: self.y.derivative_unbounded(t)
        }
    }
}

#[derive(Debug, Clone)]
pub struct BezCubeChain<C, F>
        where C: AsRef<[BezNode<F>]>,
              F: Float {
    container: C,
    float_type: PhantomData<F>
}

impl<C, F> BezCubeChain<C, F>
        where C: AsRef<[BezNode<F>]>,
              F: Float {
    pub fn from_container(c: C) -> Result<BezCubeChain<C, F>, BevError> {
        {
            let cslice = c.as_ref();
            if cslice.len() % 3 != 1 {
                return Err(BevError::InvalidLength)
            }

            for i in 0..cslice.len()/3 {
                let curve = &cslice[i*3..(i+1)*3+1];
                if !(curve[0].is_point()   &&
                     curve[1].is_control() &&
                     curve[2].is_control() &&
                     curve[3].is_point()) {
                    return Err(BevError::BadNodePattern)
                }
            }
        }

        Ok(BezCubeChain {
            container: c,
            float_type: PhantomData
        })
    }

    pub unsafe fn from_container_unchecked(c: C) -> BezCubeChain<C, F> {
        BezCubeChain {
            container: c,
            float_type: PhantomData
        }
    }

    pub fn unwrap(self) -> C {
        self.container
    }
}

impl<C, F> AsRef<C> for BezCubeChain<C, F>
        where C: AsRef<[BezNode<F>]>,
              F: Float {

    fn as_ref(&self) -> &C {
        &self.container
    }
}

#[derive(Debug)]
pub enum BevError {
    BadNodePattern,
    InvalidLength
}<commit_msg>Add vector negation<commit_after>extern crate num;

pub mod core;

use std::convert::{Into, From, AsRef};
use std::ops::{Add, Mul, Div};
use std::marker::PhantomData;
use num::{Float, FromPrimitive};

use core::BezCubePoly;

macro_rules! npoint_ops {
    ($lhs:ty; $rhs:ty = $output:ident<$g_name:ident: $g_ty:ident> {$($field:ident),*}) => {
        impl<$g_name: $g_ty> Add<$rhs> for $lhs {
            type Output = $output<$g_name>;

            fn add(self, rhs: $rhs) -> $output<$g_name> {
                $output {
                    $($field: self.$field + rhs.$field),*
                }
            }
        }
    }
}

macro_rules! impl_npoint {
    // auxiliary/entry point workaround made by durka42
    // read the last rule of the macro first
    (@go $dims: expr; $name:ident<$g_name:ident: $g_ty:ident> {$($field:ident: $f_ty:ty),*} $fields:tt $(,$sibling:ty)*) => {
                                                              // ^ match the first duplicate of the fields
                                                                                // ^ keep the second one as a tt
        #[derive(Debug, Clone, Copy)]
        pub struct $name<$g_name: $g_ty> {
            $(
                pub $field: $f_ty
            ),*
        }

        impl<$g_name: $g_ty> Into<[$g_name; $dims]> for $name<$g_name> {
            fn into(self) -> [$g_name; $dims] {
                [$(self.$field),*]
            }
        }

        impl<$g_name: $g_ty> Into<($($f_ty),*)> for $name<$g_name> {
            fn into(self) -> (F, F) {
                ($(self.$field),*)
            }
        }

        npoint_ops!($name<$g_name>; $name<$g_name> = $name<$g_name: $g_ty> {x, y});

        $(
            // pass the tt-wrapped fields to auxiliary macro
            impl_npoint!(@sib $name $g_name $g_ty $sibling $fields);
            npoint_ops!($name<$g_name>; $sibling = $name<$g_name: $g_ty> {x, y});
        )*
    };

    // auxiliary rule
    (@sib $name:ident $g_name:ident $g_ty:ident $sibling:ty {$($field:ident: $f_ty:ty),*}) => {
                                                // ^ finally destructure fields out of tt here
        impl<$g_name: $g_ty> From<$sibling> for $name<$g_name> {
            fn from(sib: $sibling) -> $name<$g_name> {
                $name {
                    $($field: sib.$field),*
                }
            }
        }
    };

    // entry point rule
    ($dims: expr; $name:ident<$g_name:ident: $g_ty:ident> $fields:tt $(,$sibling:ty)*) => {
                                                          // ^ match fields all together as a tt
        impl_npoint!(@go
            $dims;
            $name<$g_name: $g_ty>
            $fields // duplicate the fields
            $fields
            $(,$sibling)*
        );
    };
}

impl_npoint!{2; Point<F: Float> {
    x: F,
    y: F
}, Vector<F>}

impl_npoint!{2; Vector<F: Float> {
    x: F,
    y: F
}, Point<F>}

impl<F: Float> Vector<F> {
    pub fn len(self) -> F {
        (self.x.powi(2) + self.y.powi(2)).sqrt()
    }

    pub fn normalize(self) -> Vector<F> {
        self / self.len()
    }
}

impl<F: Float> Mul<F> for Vector<F> {
    type Output = Vector<F>;

    fn mul(self, rhs: F) -> Vector<F> {
        Vector {
            x: self.x * rhs,
            y: self.y * rhs
        }
    }
}

impl<F: Float> Div<F> for Vector<F> {
    type Output = Vector<F>;

    fn div(self, rhs: F) -> Vector<F> {
        Vector {
            x: self.x / rhs,
            y: self.y / rhs
        }
    }
}

impl<F: Float> Neg for Vector<F> {
    type Output = Vector<F>;

    fn neg(self) -> Vector<F> {
        Vector {
            x: -self.x,
            y: -self.y
        }
    }
}

#[derive(Debug, Clone, Copy)]
pub enum BezNode<F: Float> {
    Point {
        x: F,
        y: F
    },

    Control {
        x: F,
        y: F
    }
}

impl<F: Float> BezNode<F> {
    pub fn new_point(x: F, y: F) -> BezNode<F> {
        BezNode::Point {
            x: x,
            y: y
        }
    }

    pub fn new_control(x: F, y: F) -> BezNode<F> {
        BezNode::Control {
            x: x,
            y: y
        }
    }

    pub fn x(self) -> F {
        <BezNode<F> as Into<(F, F)>>::into(self).0
    }

    pub fn y(self) -> F {
        <BezNode<F> as Into<(F, F)>>::into(self).1
    }

    pub fn is_point(self) -> bool {
        use self::BezNode::*;
        match self {
            Point{..} => true,
            Control{..} => false
        }
    }

    pub fn is_control(self) -> bool {
        use self::BezNode::*;
        match self {
            Point{..} => false,
            Control{..} => true
        }
    }
}

impl<F: Float> Into<[F; 2]> for BezNode<F> {
    fn into(self) -> [F; 2] {
        use self::BezNode::*;

        match self {
            Point{x, y}    |
            Control{x, y} => [x, y]
        }
    }
}

impl<F: Float> Into<(F, F)> for BezNode<F> {
    fn into(self) -> (F, F) {
        use self::BezNode::*;

        match self {
            Point{x, y}    |
            Control{x, y} => (x, y)
        }
    }
}

#[derive(Debug, Clone)]
pub struct BezCube<F: Float + FromPrimitive> {
    pub x: BezCubePoly<F>,
    pub y: BezCubePoly<F>
}

impl<F: Float + FromPrimitive> BezCube<F> {
    pub fn interp(&self, t: F) -> Point<F> {
        Point {
            x: self.x.interp(t),
            y: self.y.interp_unbounded(t) // The interp is already checked when we call x.interp, so we don't have to do it here
        }
    }

    pub fn derivative(&self, t: F) -> Vector<F> {
        Vector {
            x: self.x.derivative(t),
            y: self.y.derivative_unbounded(t)
        }
    }
}

#[derive(Debug, Clone)]
pub struct BezCubeChain<C, F>
        where C: AsRef<[BezNode<F>]>,
              F: Float {
    container: C,
    float_type: PhantomData<F>
}

impl<C, F> BezCubeChain<C, F>
        where C: AsRef<[BezNode<F>]>,
              F: Float {
    pub fn from_container(c: C) -> Result<BezCubeChain<C, F>, BevError> {
        {
            let cslice = c.as_ref();
            if cslice.len() % 3 != 1 {
                return Err(BevError::InvalidLength)
            }

            for i in 0..cslice.len()/3 {
                let curve = &cslice[i*3..(i+1)*3+1];
                if !(curve[0].is_point()   &&
                     curve[1].is_control() &&
                     curve[2].is_control() &&
                     curve[3].is_point()) {
                    return Err(BevError::BadNodePattern)
                }
            }
        }

        Ok(BezCubeChain {
            container: c,
            float_type: PhantomData
        })
    }

    pub unsafe fn from_container_unchecked(c: C) -> BezCubeChain<C, F> {
        BezCubeChain {
            container: c,
            float_type: PhantomData
        }
    }

    pub fn unwrap(self) -> C {
        self.container
    }
}

impl<C, F> AsRef<C> for BezCubeChain<C, F>
        where C: AsRef<[BezNode<F>]>,
              F: Float {

    fn as_ref(&self) -> &C {
        &self.container
    }
}

#[derive(Debug)]
pub enum BevError {
    BadNodePattern,
    InvalidLength
}<|endoftext|>


<commit_before>#![deny(missing_docs)]
#![feature(macro_rules)]

//! Interpolation algorithms.
//!
//! Interpolation is used in animation,
//! to describe smooth shapes and to make transitions.
//! Any object that fullfill certain mathematical
//! properties can be interpolated.
//! A common technique is using one ore more 'numbers'
//! controlling the mixture of states.
//! The choice of interpolation algorithm depends often
//! on the circumstances where it used.

use std::ops::{ Add, Mul, Sub };

pub mod ease;

/// Performs linear interpolation.
/// A linear interpolation consists of two states 'a' and 'b'.
/// The 't' variable is a factor between 0 and 1 that
/// gives weight to 'a' or 'b'.
/// When 't' is zero then 'a' has full weight.
/// When 't' is one then 'b' has full weight.
#[inline(always)]
pub fn lerp<T: Copy + Add<T, T> + Sub<T, T> + Mul, U: Copy>(
    a: T,
    b: T,
    t: U
) -> T {
    a + (b - a) * t
}

/// Performs quadratic beziér interpolation.
/// This is done by nesting linear interpolations.
/// For more information, see:
///
/// Beziér Curve at Wikipedia
#[inline(always)]
pub fn quad_bez<T: Copy + Add<T, T> + Sub<T, T> + Mul, U: Copy>(
    x0: T,
    x1: T,
    x2: T,
    t: U
) -> T {
    let x_0_1 = lerp(x0, x1, t);
    let x_1_2 = lerp(x1, x2, t);
    lerp(x_0_1, x_1_2, t)
}

/// Performs cubic beziér interpolation.
/// This is done by interpolation between two quadratic beziér.
/// For more information, see:
///
/// Beziér Curve at Wikipedia
#[inline(always)]
pub fn cub_bez<T: Copy + Add<T, T> + Sub<T, T> + Mul, U: Copy>(
    x0: T,
    x1: T,
    x2: T,
    x3: T,
    t: U
) -> T {
    let x_0_2 = quad_bez(x0, x1, x2, t);
    let x_1_3 = quad_bez(x1, x2, x3, t);
    lerp(x_0_2, x_1_3, t)
}

<commit_msg>Use `Float` as constraint<commit_after>#![deny(missing_docs)]
#![feature(macro_rules)]
#![feature(default_type_params)]

//! Interpolation algorithms.
//!
//! Interpolation is used in animation,
//! to describe smooth shapes and to make transitions.
//! Any object that fullfill certain mathematical
//! properties can be interpolated.
//! A common technique is using one ore more 'numbers'
//! controlling the mixture of states.
//! The choice of interpolation algorithm depends often
//! on the circumstances where it used.

use std::num::Float;

pub mod ease;

/// Performs linear interpolation.
/// A linear interpolation consists of two states 'a' and 'b'.
/// The 't' variable is a factor between 0 and 1 that
/// gives weight to 'a' or 'b'.
/// When 't' is zero then 'a' has full weight.
/// When 't' is one then 'b' has full weight.
#[inline(always)]
pub fn lerp<T: Copy + Float>(a: T, b: T, t: T) -> T {
    a + (b - a) * t
}

/// Performs quadratic beziér interpolation.
/// This is done by nesting linear interpolations.
/// For more information, see:
///
/// Beziér Curve at Wikipedia
#[inline(always)]
pub fn quad_bez<T: Copy + Float>(
    x0: T,
    x1: T,
    x2: T,
    t: T
) -> T {
    let x_0_1 = lerp(x0, x1, t);
    let x_1_2 = lerp(x1, x2, t);
    lerp(x_0_1, x_1_2, t)
}

/// Performs cubic beziér interpolation.
/// This is done by interpolation between two quadratic beziér.
/// For more information, see:
///
/// Beziér Curve at Wikipedia
#[inline(always)]
pub fn cub_bez<T: Copy + Float>(
    x0: T,
    x1: T,
    x2: T,
    x3: T,
    t: T
) -> T {
    let x_0_2 = quad_bez(x0, x1, x2, t);
    let x_1_3 = quad_bez(x1, x2, x3, t);
    lerp(x_0_2, x_1_3, t)
}

<|endoftext|>


<commit_before>//! EventFD binding
//!
//! This crate implements a simple binding for Linux eventfd(). See
//! eventfd(2) for specific details of behaviour.

extern crate libc;

use libc::{c_int, c_uint, c_void};
use std::io::{IoResult, IoError};
use std::os::unix::{AsRawFd,Fd};
use std::thread::Thread;

pub struct EventFD {
    fd: uint,
    flags: uint,
}

unsafe impl Send for EventFD {}
unsafe impl Sync for EventFD {}

/// Construct a semaphore-style EventFD.
pub const EFD_SEMAPHORE: uint = 0x00001; // 00000001

/// In non-blocking mode, reads and writes will return IoError
/// containing EAGAIN rather than blocking.
pub const EFD_NONBLOCK: uint  = 0x00800; // 00004000

/// Set the close-on-exec flag on the eventfd.
pub const EFD_CLOEXEC: uint   = 0x80000; // 02000000

impl EventFD {
    /// Create a new EventFD. Flags is the bitwise OR of EFD_* constants, or 0 for no flags.
    /// The underlying file descriptor is closed when the EventFD instance's lifetime ends.
    ///
    /// TODO: work out how to integrate this FD into the wider world
    /// of fds. There's currently no way to poll/select on the fd.
    pub fn new(initval: uint, flags: uint) -> IoResult<EventFD> {
        let r = unsafe { eventfd(initval as u32, flags as u32) };

        if r < 0 {
            Err(IoError::last_error())
        } else {
            Ok(EventFD { fd: r as uint, flags: flags })
        }
    }

    /// Read the current value of the eventfd. This will block until
    /// the value is non-zero. In semaphore mode this will only ever
    /// decrement the count by 1 and return 1; otherwise it atomically
    /// returns the current value and sets it to zero.
    pub fn read(&self) -> IoResult<u64> {
        let mut ret : u64 = 0;
        let r = unsafe {
            let ptr : *mut u64 = &mut ret;
            ::libc::read(self.fd as c_int, ptr as *mut c_void, std::mem::size_of_val(&ret) as u64)
        };

        if r < 0 {
            Err(IoError::last_error())
        } else {
            Ok(ret)
        }
    }

    /// Add to the current value. Blocks if the value would wrap u64.
    pub fn write(&self, val: u64) -> IoResult<()> {
        let r = unsafe {
            let ptr : *const u64 = &val;
            ::libc::write(self.fd as c_int, ptr as *const c_void, std::mem::size_of_val(&val) as u64)
        };

        if r < 0 {
            Err(IoError::last_error())
        } else {
            Ok(())
        }
    }

    /// Return a stream of events. The channel has a synchronous
    /// sender because there's no point in building up a queue of
    /// events; if this task blocks on send, the event state will
    /// still update.
    ///
    /// The task will exit if the receiver end is shut down.
    ///
    /// This will be a CPU-spin loop if the EventFD is created
    /// non-blocking.
    ///
    /// XXX FIXME This has no way of terminating except if the other
    /// end closes the connection, and only then if we're not blocked
    /// in the read()...
    pub fn events(&self) -> std::comm::Receiver<u64> {
        let (tx, rx) = std::comm::sync_channel(1);
        let c = self.clone();

        Thread::spawn(move || {
            loop {
                match c.read() {
                    Ok(v) => match tx.send_opt(v) {
                        Ok(_) => (),
                        Err(_) => break,
                    },
                    Err(e) => panic!("read failed: {}", e),
                }
            }
        }).detach();

        rx
    }
}

impl AsRawFd for EventFD {
    /// Return the raw underlying fd. The caller must make sure self's
    /// lifetime is longer than any users of the fd.
    fn as_raw_fd(&self) -> Fd {
        self.fd as Fd
    }
}

impl Drop for EventFD {
    fn drop(&mut self) {
        let r = unsafe { ::libc::close(self.fd as c_int) };
        if r < 0 {
            panic!("eventfd close {} failed", self.fd)
        }
    }
}

/// Construct a linked clone of an existing EventFD. Once created, the
/// new instance interacts with the original in a way that's
/// indistinguishable from the original.
impl Clone for EventFD {
    fn clone(&self) -> EventFD {
        let r = unsafe { ::libc::dup(self.fd as c_int) };
        if r < 0 {
            panic!("EventFD clone dup failed: {}", IoError::last_error())
        }

        EventFD { fd: r as uint, flags: self.flags }
    }
}

#[link(name = "c")]
extern "C" {
    fn eventfd(initval: c_uint, flags: c_uint) -> c_int;
}

#[cfg(test)]
mod test {
    extern crate std;
    use super::{EventFD, EFD_SEMAPHORE, EFD_NONBLOCK};
    use std::thread::Thread;

    #[test]
    fn test_basic() {
        let (tx,rx) = std::comm::channel();
        let efd = match EventFD::new(10, 0) {
            Err(e) => panic!("new failed {}", e),
            Ok(fd) => fd,
        };
        let cefd = efd.clone();

        assert_eq!(efd.read(), Ok(10));

        Thread::spawn(move || {
            assert_eq!(cefd.read(), Ok(7));
            assert_eq!(cefd.write(1), Ok(()));
            assert_eq!(cefd.write(2), Ok(()));
            tx.send(());
        }).detach();

        assert_eq!(efd.write(7), Ok(()));
        rx.recv();
        assert_eq!(efd.read(), Ok(3));
    }

    #[test]
    fn test_sema() {
        let efd = match EventFD::new(0, EFD_SEMAPHORE | EFD_NONBLOCK) {
            Err(e) => panic!("new failed {}", e),
            Ok(fd) => fd,
        };

        match efd.read() {
            Err(ref e) if e.kind == std::io::ResourceUnavailable => (), // ok
            Err(e) => panic!("unexpected error {}", e),
            Ok(v) => panic!("unexpected success {}", v),
        }

        assert_eq!(efd.write(5), Ok(()));

        assert_eq!(efd.read(), Ok(1));
        assert_eq!(efd.read(), Ok(1));
        assert_eq!(efd.read(), Ok(1));
        assert_eq!(efd.read(), Ok(1));
        assert_eq!(efd.read(), Ok(1));
        match efd.read() {
            Err(ref e) if e.kind == std::io::ResourceUnavailable => (), // ok
            Err(e) => panic!("unexpected error {}", e),
            Ok(v) => panic!("unexpected success {}", v),
        }
    }

    #[test]
    fn test_stream() {
        let efd = match EventFD::new(11, EFD_SEMAPHORE) {
            Err(e) => panic!("new failed {}", e),
            Ok(fd) => fd,
        };
        let mut count = 0;

        // only take 10 of 11 so the stream task doesn't block in read and hang the test
        for v in efd.events().iter().take(10) {
            assert_eq!(v, 1);
            count += v;
        }

        assert_eq!(count, 10)
    }

    #[test]
    fn test_chan() {
        let (tx,rx) = std::comm::channel();
        let efd = match EventFD::new(10, 0) {
            Err(e) => panic!("new failed {}", e),
            Ok(fd) => fd,
        };

        assert_eq!(efd.write(1), Ok(()));
        tx.send(efd);

        let t = Thread::spawn(move || {
            let efd = rx.recv();
            assert_eq!(efd.read(), Ok(11))
        }).join();

        match t {
            Ok(_) => println!("ok"),
            Err(_) => panic!("failed"),
        }
    }
}
<commit_msg>Make Linux-specific<commit_after>#![cfg(target_os = "linux")]
//! EventFD binding
//!
//! This crate implements a simple binding for Linux eventfd(). See
//! eventfd(2) for specific details of behaviour.

extern crate libc;

use libc::{c_int, c_uint, c_void};
use std::io::{IoResult, IoError};
use std::os::unix::{AsRawFd,Fd};
use std::thread::Thread;

pub struct EventFD {
    fd: uint,
    flags: uint,
}

unsafe impl Send for EventFD {}
unsafe impl Sync for EventFD {}

/// Construct a semaphore-style EventFD.
pub const EFD_SEMAPHORE: uint = 0x00001; // 00000001

/// In non-blocking mode, reads and writes will return IoError
/// containing EAGAIN rather than blocking.
pub const EFD_NONBLOCK: uint  = 0x00800; // 00004000

/// Set the close-on-exec flag on the eventfd.
pub const EFD_CLOEXEC: uint   = 0x80000; // 02000000

impl EventFD {
    /// Create a new EventFD. Flags is the bitwise OR of EFD_* constants, or 0 for no flags.
    /// The underlying file descriptor is closed when the EventFD instance's lifetime ends.
    ///
    /// TODO: work out how to integrate this FD into the wider world
    /// of fds. There's currently no way to poll/select on the fd.
    pub fn new(initval: uint, flags: uint) -> IoResult<EventFD> {
        let r = unsafe { eventfd(initval as u32, flags as u32) };

        if r < 0 {
            Err(IoError::last_error())
        } else {
            Ok(EventFD { fd: r as uint, flags: flags })
        }
    }

    /// Read the current value of the eventfd. This will block until
    /// the value is non-zero. In semaphore mode this will only ever
    /// decrement the count by 1 and return 1; otherwise it atomically
    /// returns the current value and sets it to zero.
    pub fn read(&self) -> IoResult<u64> {
        let mut ret : u64 = 0;
        let r = unsafe {
            let ptr : *mut u64 = &mut ret;
            ::libc::read(self.fd as c_int, ptr as *mut c_void, std::mem::size_of_val(&ret) as u64)
        };

        if r < 0 {
            Err(IoError::last_error())
        } else {
            Ok(ret)
        }
    }

    /// Add to the current value. Blocks if the value would wrap u64.
    pub fn write(&self, val: u64) -> IoResult<()> {
        let r = unsafe {
            let ptr : *const u64 = &val;
            ::libc::write(self.fd as c_int, ptr as *const c_void, std::mem::size_of_val(&val) as u64)
        };

        if r < 0 {
            Err(IoError::last_error())
        } else {
            Ok(())
        }
    }

    /// Return a stream of events. The channel has a synchronous
    /// sender because there's no point in building up a queue of
    /// events; if this task blocks on send, the event state will
    /// still update.
    ///
    /// The task will exit if the receiver end is shut down.
    ///
    /// This will be a CPU-spin loop if the EventFD is created
    /// non-blocking.
    ///
    /// XXX FIXME This has no way of terminating except if the other
    /// end closes the connection, and only then if we're not blocked
    /// in the read()...
    pub fn events(&self) -> std::comm::Receiver<u64> {
        let (tx, rx) = std::comm::sync_channel(1);
        let c = self.clone();

        Thread::spawn(move || {
            loop {
                match c.read() {
                    Ok(v) => match tx.send_opt(v) {
                        Ok(_) => (),
                        Err(_) => break,
                    },
                    Err(e) => panic!("read failed: {}", e),
                }
            }
        }).detach();

        rx
    }
}

impl AsRawFd for EventFD {
    /// Return the raw underlying fd. The caller must make sure self's
    /// lifetime is longer than any users of the fd.
    fn as_raw_fd(&self) -> Fd {
        self.fd as Fd
    }
}

impl Drop for EventFD {
    fn drop(&mut self) {
        let r = unsafe { ::libc::close(self.fd as c_int) };
        if r < 0 {
            panic!("eventfd close {} failed", self.fd)
        }
    }
}

/// Construct a linked clone of an existing EventFD. Once created, the
/// new instance interacts with the original in a way that's
/// indistinguishable from the original.
impl Clone for EventFD {
    fn clone(&self) -> EventFD {
        let r = unsafe { ::libc::dup(self.fd as c_int) };
        if r < 0 {
            panic!("EventFD clone dup failed: {}", IoError::last_error())
        }

        EventFD { fd: r as uint, flags: self.flags }
    }
}

#[link(name = "c")]
extern "C" {
    fn eventfd(initval: c_uint, flags: c_uint) -> c_int;
}

#[cfg(test)]
mod test {
    extern crate std;
    use super::{EventFD, EFD_SEMAPHORE, EFD_NONBLOCK};
    use std::thread::Thread;

    #[test]
    fn test_basic() {
        let (tx,rx) = std::comm::channel();
        let efd = match EventFD::new(10, 0) {
            Err(e) => panic!("new failed {}", e),
            Ok(fd) => fd,
        };
        let cefd = efd.clone();

        assert_eq!(efd.read(), Ok(10));

        Thread::spawn(move || {
            assert_eq!(cefd.read(), Ok(7));
            assert_eq!(cefd.write(1), Ok(()));
            assert_eq!(cefd.write(2), Ok(()));
            tx.send(());
        }).detach();

        assert_eq!(efd.write(7), Ok(()));
        rx.recv();
        assert_eq!(efd.read(), Ok(3));
    }

    #[test]
    fn test_sema() {
        let efd = match EventFD::new(0, EFD_SEMAPHORE | EFD_NONBLOCK) {
            Err(e) => panic!("new failed {}", e),
            Ok(fd) => fd,
        };

        match efd.read() {
            Err(ref e) if e.kind == std::io::ResourceUnavailable => (), // ok
            Err(e) => panic!("unexpected error {}", e),
            Ok(v) => panic!("unexpected success {}", v),
        }

        assert_eq!(efd.write(5), Ok(()));

        assert_eq!(efd.read(), Ok(1));
        assert_eq!(efd.read(), Ok(1));
        assert_eq!(efd.read(), Ok(1));
        assert_eq!(efd.read(), Ok(1));
        assert_eq!(efd.read(), Ok(1));
        match efd.read() {
            Err(ref e) if e.kind == std::io::ResourceUnavailable => (), // ok
            Err(e) => panic!("unexpected error {}", e),
            Ok(v) => panic!("unexpected success {}", v),
        }
    }

    #[test]
    fn test_stream() {
        let efd = match EventFD::new(11, EFD_SEMAPHORE) {
            Err(e) => panic!("new failed {}", e),
            Ok(fd) => fd,
        };
        let mut count = 0;

        // only take 10 of 11 so the stream task doesn't block in read and hang the test
        for v in efd.events().iter().take(10) {
            assert_eq!(v, 1);
            count += v;
        }

        assert_eq!(count, 10)
    }

    #[test]
    fn test_chan() {
        let (tx,rx) = std::comm::channel();
        let efd = match EventFD::new(10, 0) {
            Err(e) => panic!("new failed {}", e),
            Ok(fd) => fd,
        };

        assert_eq!(efd.write(1), Ok(()));
        tx.send(efd);

        let t = Thread::spawn(move || {
            let efd = rx.recv();
            assert_eq!(efd.read(), Ok(11))
        }).join();

        match t {
            Ok(_) => println!("ok"),
            Err(_) => panic!("failed"),
        }
    }
}
<|endoftext|>


<commit_before>#[test]
fn hextranslation() {
	let vals = vec![0, 255, 128];
	let ans = md5::to_hex_string(&vals);
	println!("{0}", ans);
	assert!(ans == "00FF80");
}

#[test]
fn empty_test() {
	use md5::*;

	let trueans = "D41D8CD98F00B204E9800998ECF8427E";
	let vals = vec![];
	let try = md5::compute(&vals);
	println!("{0}", to_hex_string(&try));
	assert!(to_hex_string(&try) == trueans);
}

extern crate core;

mod md5 {

	pub fn to_hex_string(bytes: &[u8]) -> String {
	  let strs: Vec<String> = bytes.iter().map(|b| format!("{:02X}", b)).collect();
	  strs.join("")
	}

	pub fn compute(data : &Vec<u8>) -> [u8;16] {

		use core::ops::Not;

 		let k : [u32; 64] = [
	 		0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
			0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
			0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
			0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
			0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
			0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
			0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
			0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
			0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
			0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
			0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
			0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
			0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
			0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
			0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
			0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
		];

		let s : [u32; 64] =
		[
			7, 12, 17, 22, 7, 12, 17, 22, 7, 12,
			17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5,
			9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4,
			11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
			4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21,
			6, 10, 15, 21, 6, 10, 15, 21
		];

		let mut a0 : u32 = 0x67452301;   //a
		let mut b0 : u32 = 0xefcdab89;   //b
		let mut c0 : u32 = 0x98badcfe;   //c
		let mut d0 : u32 = 0x10325476;   //d

		let mut our_data = data.clone();

		our_data.push(0b10000000);
		let mod512 = our_data.len() % 64;
		let padding_length =
			if mod512 > 56
				{ 64-mod512+56 }
			else
				{ 56 - mod512 };

		for _ in 0..padding_length {
			our_data.push(0u8);
		}

		let size : u64 = 8*data.len() as u64;
		for i in (0..8).rev() {
			our_data.push((size.wrapping_shr(8*i) % 256) as u8);
		}

		assert!(our_data.len() % 64 == 0);
		println!("Size: {0}", size);

		let our_data = our_data;
		for q in our_data.chunks(16) {
			for c in q {
				print!("{0:3},", c);
			}
			println!("");
		}

		for chunk in our_data.chunks(64) {

			let mut m : [u32; 16] = [0;16];

			for (i, bits) in chunk.chunks(4).enumerate() {
				m[i] = from_le_bytes(bits[0], bits[1], bits[2], bits[3])
			}

			let m = m;

		    let mut a = a0;
		    let mut b = b0;
		    let mut c = c0;
		    let mut d = d0;
			let mut f : u32;
			let mut g : u32;
		//main loop:
		    for i in 0..64 {
			    match i {
			    	0 ... 15 => {
			    		f = (b & c) | (b.not() & d);
			    		g = i;
			    	}
			        16...31 => {
			            f = (d & b) | (d.not() & c);
			            g = (5*i + 1) % 16;
			        }
			        32...47 => {
			            f = b ^ c ^ d;
			            g = (3*i + 5) % 16;
			        }
			        48...63 => {
			            f = c ^ (b | d.not());
			            g = (7*i) % 16;
			        }
			        _ => panic!("Out of bounds")
			    }

		        let d_temp = d;
		        d = c;
		        c = b;
		        b = b.wrapping_add(leftrotate(a.wrapping_add(f).wrapping_add(k[i as usize]).wrapping_add(m[g as usize]), s[i as usize]));
		        a = d_temp;
		    }
		//add this chunk's hash to result so far:
		    a0 = a0.wrapping_add(a);
		    b0 = b0.wrapping_add(b);
		    c0 = c0.wrapping_add(c);
		    d0 = d0.wrapping_add(d);
		}

		let mut result = [0u8; 16];
		let mut index = 0;
		for v in [a0, b0, c0, d0].iter() {
			let bytes = to_le_bytes(v);
			result[index] = bytes.0;
			result[index+1] = bytes.1;
			result[index+2] = bytes.2;
			result[index+3] = bytes.3;
			index += 4;
		}

		return result;
	}

	fn to_le_bytes(i: &u32) -> (u8, u8, u8, u8) {
		let q1 = (i >> 24u32) % 256;
		let q2 = (i >> 16u32) % 256;
		let q3 = (i >> 8u32)  % 256;
		let q4 = (i >> 0u32)  % 256;
		return (q4 as u8, q3 as u8, q2 as u8, q1 as u8)
	}

	fn from_le_bytes(a: u8, b:u8, c:u8, d:u8) -> u32 {
		return (a as u32) + ((b as u32) << 8) + ((c as u32) << 16) + ((d as u32) << 24);
	}

	fn leftrotate (x : u32, c: u32) -> u32 {
		    return x.rotate_left(c);
	}

}<commit_msg>Fixed endian of the length encoding<commit_after>#[test]
fn hextranslation() {
	let vals = vec![0, 255, 128];
	let ans = md5::to_hex_string(&vals);
	println!("{0}", ans);
	assert!(ans == "00FF80");
}

#[test]
fn empty_test() {
	use md5::*;

	let trueans = "D41D8CD98F00B204E9800998ECF8427E";
	let vals = vec![];
	let try = md5::compute(&vals);
	println!("{0}", to_hex_string(&try));
	assert!(to_hex_string(&try) == trueans);
}

#[test]
fn SevenHundredAs()
{
	use md5::*;

	let expected = "C04C6D6896853D32B720D69A6027E6BE";
	let A = 'A' as u8;
	let vals = vec![A; 700];
	let try = md5::compute(&vals);
	println!("{0}", to_hex_string(&try));
	assert!(to_hex_string(&try) == expected);
}

extern crate core;

mod md5 {

	pub fn to_hex_string(bytes: &[u8]) -> String {
	  let strs: Vec<String> = bytes.iter().map(|b| format!("{:02X}", b)).collect();
	  strs.join("")
	}

	pub fn compute(data : &Vec<u8>) -> [u8;16] {

		use core::ops::Not;

 		let k : [u32; 64] = [
	 		0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
			0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
			0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
			0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
			0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
			0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
			0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
			0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
			0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
			0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
			0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
			0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
			0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
			0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
			0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
			0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
		];

		let s : [u32; 64] =
		[
			7, 12, 17, 22, 7, 12, 17, 22, 7, 12,
			17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5,
			9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4,
			11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
			4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21,
			6, 10, 15, 21, 6, 10, 15, 21
		];

		let mut a0 : u32 = 0x67452301;   //a
		let mut b0 : u32 = 0xefcdab89;   //b
		let mut c0 : u32 = 0x98badcfe;   //c
		let mut d0 : u32 = 0x10325476;   //d

		let mut our_data = data.clone();

		our_data.push(0b10000000);
		let mod512 = our_data.len() % 64;
		let padding_length =
			if mod512 > 56
				{ 64-mod512+56 }
			else
				{ 56 - mod512 };

		for _ in 0..padding_length {
			our_data.push(0u8);
		}

		let size : u64 = 8*data.len() as u64;
		for i in (0..8) {
			our_data.push((size.wrapping_shr(8*i) % 256) as u8);
		}

		assert!(our_data.len() % 64 == 0);
		println!("Size: {0}", size);

		let our_data = our_data;
		for q in our_data.chunks(16) {
			for c in q {
				print!("{0:3},", c);
			}
			println!("");
		}

		for chunk in our_data.chunks(64) {

			let mut m : [u32; 16] = [0;16];

			for (i, bits) in chunk.chunks(4).enumerate() {
				m[i] = from_le_bytes(bits[0], bits[1], bits[2], bits[3])
			}

			let m = m;

		    let mut a = a0;
		    let mut b = b0;
		    let mut c = c0;
		    let mut d = d0;
			let mut f : u32;
			let mut g : u32;
		//main loop:
		    for i in 0..64 {
			    match i {
			    	0 ... 15 => {
			    		f = (b & c) | (b.not() & d);
			    		g = i;
			    	}
			        16...31 => {
			            f = (d & b) | (d.not() & c);
			            g = (5*i + 1) % 16;
			        }
			        32...47 => {
			            f = b ^ c ^ d;
			            g = (3*i + 5) % 16;
			        }
			        48...63 => {
			            f = c ^ (b | d.not());
			            g = (7*i) % 16;
			        }
			        _ => panic!("Out of bounds")
			    }

		        let d_temp = d;
		        d = c;
		        c = b;
		        b = b.wrapping_add(leftrotate(a.wrapping_add(f).wrapping_add(k[i as usize]).wrapping_add(m[g as usize]), s[i as usize]));
		        a = d_temp;
		    }
		//add this chunk's hash to result so far:
		    a0 = a0.wrapping_add(a);
		    b0 = b0.wrapping_add(b);
		    c0 = c0.wrapping_add(c);
		    d0 = d0.wrapping_add(d);
		}

		let mut result = [0u8; 16];
		let mut index = 0;
		for v in [a0, b0, c0, d0].iter() {
			let bytes = to_le_bytes(v);
			result[index] = bytes.0;
			result[index+1] = bytes.1;
			result[index+2] = bytes.2;
			result[index+3] = bytes.3;
			index += 4;
		}

		return result;
	}

	fn to_le_bytes(i: &u32) -> (u8, u8, u8, u8) {
		let q1 = (i >> 24u32) % 256;
		let q2 = (i >> 16u32) % 256;
		let q3 = (i >> 8u32)  % 256;
		let q4 = (i >> 0u32)  % 256;
		return (q4 as u8, q3 as u8, q2 as u8, q1 as u8)
	}

	fn from_le_bytes(a: u8, b:u8, c:u8, d:u8) -> u32 {
		return (a as u32) + ((b as u32) << 8) + ((c as u32) << 16) + ((d as u32) << 24);
	}

	fn leftrotate (x : u32, c: u32) -> u32 {
		    return x.rotate_left(c);
	}

}<|endoftext|>


<commit_before>//! # Mime
//!
//! Mime is now Media Type, technically, but `Mime` is more immediately
//! understandable, so the main type here is `Mime`.
//!
//! ## What is Mime?
//!
//! Example mime string: `text/plain;charset=utf-8`
//!
//! ```rust
//! # use std::str::FromStr;
//! use mime::{Mime, Text, Plain, Charset, Utf8};
//! let mime: Mime = FromStr::from_str("text/plain;charset=utf-8").unwrap();
//! assert_eq!(mime, Mime(Text, Plain, vec![(Charset, Utf8)]));
//! ```

#![license = "MIT"]
#![doc(html_root_url = "http://seanmonstar.github.io/mime.rs")]
#![experimental]
#![feature(macro_rules, phase)]

#[phase(plugin, link)]
extern crate log;

#[cfg(test)]
extern crate test;

use std::ascii::AsciiExt;
use std::cmp::Equiv;
use std::fmt;
use std::str::FromStr;
use std::iter::Enumerate;
use std::str::Chars;

macro_rules! inspect(
    ($s:expr, $t:expr) => ({
        let t = $t;
        debug!("inspect {}: {}", $s, t);
        t
    })
)

/// Mime, or Media Type. Encapsulates common registers types.
///
/// Consider that a traditional mime type contains a "top level type",
/// a "sub level type", and 0-N "parameters". And they're all strings.
/// Strings everywhere. Strings mean typos. Rust has type safety. We should
/// use types!
///
/// So, Mime bundles together this data into types so the compiler can catch
/// your typos.
///
/// This improves things so you use match without Strings:
///
/// ```rust
/// use std::str::from_str;
/// use mime::{Mime, Application, Json};
///
/// let mime: mime::Mime = from_str("application/json").unwrap();
///
/// match mime {
///     Mime(Application, Json, _) => println!("matched json!"),
///     _ => ()
/// }
/// ```
#[deriving(Clone, PartialEq)]
pub struct Mime(pub TopLevel, pub SubLevel, pub Vec<Param>);

macro_rules! enoom (
    (pub enum $en:ident; $ext:ident; $($ty:ident, $text:expr;)*) => (

        #[deriving(Clone, PartialEq)]
        pub enum $en {
            $($ty),*,
            $ext(String)
        }

        impl fmt::Show for $en {
            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
                match *self {
                    $($ty => $text),*,
                    $ext(ref s) => return s.fmt(fmt)
                }.fmt(fmt)
            }
        }

        impl FromStr for $en {
            fn from_str(s: &str) -> Option<$en> {
                Some(match s {
                    $(_s if _s == $text => $ty),*,
                    s => $ext(inspect!(stringify!($ext), s).to_string())
                })
            }
        }
    )
)

enoom! {
    pub enum TopLevel;
    TopExt;
    TopStar, "*"; // remove Top prefix if enums gain namespaces
    Text, "text";
    Image, "image";
    Audio, "audio";
    Video, "video";
    Application, "application";
    Multipart, "multipart";
    Message, "message";
    Model, "model";
}

enoom! {
    pub enum SubLevel;
    SubExt;
    SubStar, "*"; // remove Sub prefix if enums gain namespaces

    // common text/*
    Plain, "plain";
    Html, "html";
    Xml, "xml";
    Javascript, "javascript";
    Css, "css";

    // common application/*
    Json, "json";
    WwwFormUrlEncoded, "x-www-form-urlencoded";

    // multipart/*
    FormData, "form-data";

    // common image/*
    Png, "png";
    Gif, "gif";
    Bmp, "bmp";
    Jpeg, "jpeg";
}

enoom! {
    pub enum Attr;
    AttrExt;
    Charset, "charset";
    Q, "q";
}

enoom! {
    pub enum Value;
    ValueExt;
    Utf8, "utf-8";
}

pub type Param = (Attr, Value);

impl Equiv<Mime> for Mime {
    fn equiv(&self, other: &Mime) -> bool {
        //im so sorry
        //TODO: be less sorry. dont to_string()
        self.to_string() == other.to_string()
    }
}

impl fmt::Show for Mime {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let Mime(ref top, ref sub, ref params) = *self;
        try!(write!(fmt, "{}/{}", top, sub));
        fmt_params(params.as_slice(), fmt)
    }
}

impl FromStr for Mime {
    fn from_str(raw: &str) -> Option<Mime> {
        let ascii = raw.to_ascii_lower(); // lifetimes :(
        let raw = ascii.as_slice();
        let len = raw.len();
        let mut iter = raw.chars().enumerate();
        let mut params = vec![];
        // toplevel
        let mut start;
        let mut top;
        loop {
            match inspect!("top iter", iter.next()) {
                Some((0, c)) if is_restricted_name_first_char(c) => (),
                Some((i, c)) if i > 0 && is_restricted_name_char(c) => (),
                Some((i, '/')) if i > 0 => match FromStr::from_str(raw.slice_to(i)) {
                    Some(t) => {
                        top = t;
                        start = i + 1;
                        break;
                    }
                    None => return None
                },
                _ => return None // EOF and no toplevel is no Mime
            };

        }

        // sublevel
        let mut sub;
        loop {
            match inspect!("sub iter", iter.next()) {
                Some((i, c)) if i == start && is_restricted_name_first_char(c) => (),
                Some((i, c)) if i > start && is_restricted_name_char(c) => (),
                Some((i, ';')) if i > start => match FromStr::from_str(raw.slice(start, i)) {
                    Some(s) => {
                        sub = s;
                        start = i + 1;
                        break;
                    }
                    None => return None
                },
                None => match FromStr::from_str(raw.slice_from(start)) {
                    Some(s) => return Some(Mime(top, s, params)),
                    None => return None
                },
                _ => return None
            };
        }

        // params
        debug!("starting params, len={}", len);
        loop {
            match inspect!("param", param_from_str(raw, &mut iter, start)) {
                Some((p, end)) => {
                    params.push(p);
                    start = end;
                    if start >= len {
                        break;
                    }
                }
                None => break
            }
        }

        Some(Mime(top, sub, params))
    }
}

fn param_from_str(raw: &str, iter: &mut Enumerate<Chars>, mut start: uint) -> Option<(Param, uint)> {
    let mut attr;
    debug!("param_from_str, start={}", start);
    loop {
        match inspect!("attr iter", iter.next()) {
            Some((i, ' ')) if i == start => start = i + 1,
            Some((i, c)) if i == start && is_restricted_name_first_char(c) => (),
            Some((i, c)) if i > start && is_restricted_name_char(c) => (),
            Some((i, '=')) if i > start => match FromStr::from_str(raw.slice(start, i)) {
                Some(a) => {
                    attr = inspect!("attr", a);
                    start = i + 1;
                    break;
                },
                None => return None
            },
            _ => return None
        }
    }
    let mut value;
    // values must be restrict-name-char or "anything goes"
    let mut is_quoted = false;
    loop {
        match inspect!("value iter", iter.next()) {
            Some((i, '"')) if i == start => {
                debug!("quoted");
                is_quoted = true;
                start = i + 1;
            },
            Some((i, c)) if i == start && is_restricted_name_first_char(c) => (),
            Some((i, '"')) if i > start && is_quoted => match FromStr::from_str(raw.slice(start, i)) {
                Some(v) => {
                    value = v;
                    start = i + 1;
                    break;
                },
                None => return None
            },
            Some((i, c)) if i > start && is_quoted || is_restricted_name_char(c) => (),
            Some((i, ';')) if i > start => match FromStr::from_str(raw.slice(start, i)) {
                Some(v) => {
                    value = v;
                    start = i + 1;
                    break;
                },
                None => return None
            },
            None => match FromStr::from_str(raw.slice_from(start)) {
                Some(v) => {
                    value = v;
                    start = raw.len();
                    break;
                },
                None => return None
            },

            _ => return None
        }
    }

    Some(((attr, value), start))
}

// From [RFC6838](http://tools.ietf.org/html/rfc6838#section-4.2):
//
// > All registered media types MUST be assigned top-level type and
// > subtype names.  The combination of these names serves to uniquely
// > identify the media type, and the subtype name facet (or the absence
// > of one) identifies the registration tree.  Both top-level type and
// > subtype names are case-insensitive.
// >
// > Type and subtype names MUST conform to the following ABNF:
// >
// >     type-name = restricted-name
// >     subtype-name = restricted-name
// >
// >     restricted-name = restricted-name-first *126restricted-name-chars
// >     restricted-name-first  = ALPHA / DIGIT
// >     restricted-name-chars  = ALPHA / DIGIT / "!" / "#" /
// >                              "$" / "&" / "-" / "^" / "_"
// >     restricted-name-chars =/ "." ; Characters before first dot always
// >                                  ; specify a facet name
// >     restricted-name-chars =/ "+" ; Characters after last plus always
// >                                  ; specify a structured syntax suffix
//
fn is_restricted_name_first_char(c: char) -> bool {
    match c {
        'a'...'z' |
        '0'...'9' => true,
        _ => false
    }
}

fn is_restricted_name_char(c: char) -> bool {
    if is_restricted_name_first_char(c) {
        true
    } else {
        match c {
            '!' |
            '#' |
            '$' |
            '&' |
            '-' |
            '^' |
            '.' |
            '+' |
            '_' => true,
            _ => false
        }
    }
}

#[inline]
fn fmt_params<T: AsSlice<Param>>(params: T, fmt: &mut fmt::Formatter) -> fmt::Result {
    for param in params.as_slice().iter() {
        try!(fmt_param(param, fmt));
    }
    Ok(())
}

#[inline]
fn fmt_param(param: &Param, fmt: &mut fmt::Formatter) -> fmt::Result {
    let (ref attr, ref value) = *param;
    write!(fmt, "; {}={}", attr, value)
}

#[cfg(test)]
mod tests {
    use std::str::{FromStr, from_str};
    use test::Bencher;
    use super::{Mime, Text, Plain, Charset, Utf8, AttrExt, ValueExt};

    #[test]
    fn test_mime_show() {
        let mime = Mime(Text, Plain, vec![]);
        assert_eq!(mime.to_string(), "text/plain".to_string());
        let mime = Mime(Text, Plain, vec![(Charset, Utf8)]);
        assert_eq!(mime.to_string(), "text/plain; charset=utf-8".to_string());
    }

    #[test]
    fn test_mime_from_str() {
        assert_eq!(FromStr::from_str("text/plain"), Some(Mime(Text, Plain, vec![])));
        assert_eq!(FromStr::from_str("TEXT/PLAIN"), Some(Mime(Text, Plain, vec![])));
        assert_eq!(FromStr::from_str("text/plain; charset=utf-8"), Some(Mime(Text, Plain, vec![(Charset, Utf8)])));
        assert_eq!(FromStr::from_str("text/plain;charset=\"utf-8\""), Some(Mime(Text, Plain, vec![(Charset, Utf8)])));
        assert_eq!(FromStr::from_str("text/plain; charset=utf-8; foo=bar"),
            Some(Mime(Text, Plain, vec![(Charset, Utf8),
                                        (AttrExt("foo".to_string()), ValueExt("bar".to_string())) ])));
    }

    #[bench]
    fn bench_show(b: &mut Bencher) {
        let mime = Mime(Text, Plain, vec![(Charset, Utf8), (AttrExt("foo".to_string()), ValueExt("bar".to_string()))]);
        b.bytes = mime.to_string().as_bytes().len() as u64;
        b.iter(|| mime.to_string())
    }

    #[bench]
    fn bench_from_str(b: &mut Bencher) {
        let s = "text/plain; charset=utf-8; foo=bar";
        b.bytes = s.as_bytes().len() as u64;
        b.iter(|| from_str::<Mime>(s))
    }
}
<commit_msg>namespaced enums<commit_after>//! # Mime
//!
//! Mime is now Media Type, technically, but `Mime` is more immediately
//! understandable, so the main type here is `Mime`.
//!
//! ## What is Mime?
//!
//! Example mime string: `text/plain;charset=utf-8`
//!
//! ```rust
//! # use std::str::FromStr;
//! use mime::{Mime, Text, Plain, Charset, Utf8};
//! let mime: Mime = FromStr::from_str("text/plain;charset=utf-8").unwrap();
//! assert_eq!(mime, Mime(Text, Plain, vec![(Charset, Utf8)]));
//! ```

#![license = "MIT"]
#![doc(html_root_url = "http://seanmonstar.github.io/mime.rs")]
#![experimental]
#![feature(macro_rules, phase)]

#[phase(plugin, link)]
extern crate log;

#[cfg(test)]
extern crate test;

use std::ascii::AsciiExt;
use std::cmp::Equiv;
use std::fmt;
use std::str::FromStr;
use std::iter::Enumerate;
use std::str::Chars;

macro_rules! inspect(
    ($s:expr, $t:expr) => ({
        let t = $t;
        debug!("inspect {}: {}", $s, t);
        t
    })
)

/// Mime, or Media Type. Encapsulates common registers types.
///
/// Consider that a traditional mime type contains a "top level type",
/// a "sub level type", and 0-N "parameters". And they're all strings.
/// Strings everywhere. Strings mean typos. Rust has type safety. We should
/// use types!
///
/// So, Mime bundles together this data into types so the compiler can catch
/// your typos.
///
/// This improves things so you use match without Strings:
///
/// ```rust
/// use std::str::from_str;
/// use mime::{Mime, Application, Json};
///
/// let mime: mime::Mime = from_str("application/json").unwrap();
///
/// match mime {
///     Mime(Application, Json, _) => println!("matched json!"),
///     _ => ()
/// }
/// ```
#[deriving(Clone, PartialEq)]
pub struct Mime(pub TopLevel, pub SubLevel, pub Vec<Param>);

macro_rules! enoom (
    (pub enum $en:ident; $ext:ident; $($ty:ident, $text:expr;)*) => (

        #[deriving(Clone, PartialEq)]
        pub enum $en {
            $($ty),*,
            $ext(String)
        }

        impl fmt::Show for $en {
            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
                match *self {
                    $($en::$ty => $text),*,
                    $en::$ext(ref s) => return s.fmt(fmt)
                }.fmt(fmt)
            }
        }

        impl FromStr for $en {
            fn from_str(s: &str) -> Option<$en> {
                Some(match s {
                    $(_s if _s == $text => $en::$ty),*,
                    s => $en::$ext(inspect!(stringify!($ext), s).to_string())
                })
            }
        }
    )
)

enoom! {
    pub enum TopLevel;
    Ext;
    Star, "*";
    Text, "text";
    Image, "image";
    Audio, "audio";
    Video, "video";
    Application, "application";
    Multipart, "multipart";
    Message, "message";
    Model, "model";
}

enoom! {
    pub enum SubLevel;
    Ext;
    Star, "*";

    // common text/*
    Plain, "plain";
    Html, "html";
    Xml, "xml";
    Javascript, "javascript";
    Css, "css";

    // common application/*
    Json, "json";
    WwwFormUrlEncoded, "x-www-form-urlencoded";

    // multipart/*
    FormData, "form-data";

    // common image/*
    Png, "png";
    Gif, "gif";
    Bmp, "bmp";
    Jpeg, "jpeg";
}

enoom! {
    pub enum Attr;
    Ext;
    Charset, "charset";
    Q, "q";
}

enoom! {
    pub enum Value;
    Ext;
    Utf8, "utf-8";
}

pub type Param = (Attr, Value);

impl Equiv<Mime> for Mime {
    fn equiv(&self, other: &Mime) -> bool {
        //im so sorry
        //TODO: be less sorry. dont to_string()
        self.to_string() == other.to_string()
    }
}

impl fmt::Show for Mime {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let Mime(ref top, ref sub, ref params) = *self;
        try!(write!(fmt, "{}/{}", top, sub));
        fmt_params(params.as_slice(), fmt)
    }
}

impl FromStr for Mime {
    fn from_str(raw: &str) -> Option<Mime> {
        let ascii = raw.to_ascii_lower(); // lifetimes :(
        let raw = ascii.as_slice();
        let len = raw.len();
        let mut iter = raw.chars().enumerate();
        let mut params = vec![];
        // toplevel
        let mut start;
        let mut top;
        loop {
            match inspect!("top iter", iter.next()) {
                Some((0, c)) if is_restricted_name_first_char(c) => (),
                Some((i, c)) if i > 0 && is_restricted_name_char(c) => (),
                Some((i, '/')) if i > 0 => match FromStr::from_str(raw.slice_to(i)) {
                    Some(t) => {
                        top = t;
                        start = i + 1;
                        break;
                    }
                    None => return None
                },
                _ => return None // EOF and no toplevel is no Mime
            };

        }

        // sublevel
        let mut sub;
        loop {
            match inspect!("sub iter", iter.next()) {
                Some((i, c)) if i == start && is_restricted_name_first_char(c) => (),
                Some((i, c)) if i > start && is_restricted_name_char(c) => (),
                Some((i, ';')) if i > start => match FromStr::from_str(raw.slice(start, i)) {
                    Some(s) => {
                        sub = s;
                        start = i + 1;
                        break;
                    }
                    None => return None
                },
                None => match FromStr::from_str(raw.slice_from(start)) {
                    Some(s) => return Some(Mime(top, s, params)),
                    None => return None
                },
                _ => return None
            };
        }

        // params
        debug!("starting params, len={}", len);
        loop {
            match inspect!("param", param_from_str(raw, &mut iter, start)) {
                Some((p, end)) => {
                    params.push(p);
                    start = end;
                    if start >= len {
                        break;
                    }
                }
                None => break
            }
        }

        Some(Mime(top, sub, params))
    }
}

fn param_from_str(raw: &str, iter: &mut Enumerate<Chars>, mut start: uint) -> Option<(Param, uint)> {
    let mut attr;
    debug!("param_from_str, start={}", start);
    loop {
        match inspect!("attr iter", iter.next()) {
            Some((i, ' ')) if i == start => start = i + 1,
            Some((i, c)) if i == start && is_restricted_name_first_char(c) => (),
            Some((i, c)) if i > start && is_restricted_name_char(c) => (),
            Some((i, '=')) if i > start => match FromStr::from_str(raw.slice(start, i)) {
                Some(a) => {
                    attr = inspect!("attr", a);
                    start = i + 1;
                    break;
                },
                None => return None
            },
            _ => return None
        }
    }
    let mut value;
    // values must be restrict-name-char or "anything goes"
    let mut is_quoted = false;
    loop {
        match inspect!("value iter", iter.next()) {
            Some((i, '"')) if i == start => {
                debug!("quoted");
                is_quoted = true;
                start = i + 1;
            },
            Some((i, c)) if i == start && is_restricted_name_first_char(c) => (),
            Some((i, '"')) if i > start && is_quoted => match FromStr::from_str(raw.slice(start, i)) {
                Some(v) => {
                    value = v;
                    start = i + 1;
                    break;
                },
                None => return None
            },
            Some((i, c)) if i > start && is_quoted || is_restricted_name_char(c) => (),
            Some((i, ';')) if i > start => match FromStr::from_str(raw.slice(start, i)) {
                Some(v) => {
                    value = v;
                    start = i + 1;
                    break;
                },
                None => return None
            },
            None => match FromStr::from_str(raw.slice_from(start)) {
                Some(v) => {
                    value = v;
                    start = raw.len();
                    break;
                },
                None => return None
            },

            _ => return None
        }
    }

    Some(((attr, value), start))
}

// From [RFC6838](http://tools.ietf.org/html/rfc6838#section-4.2):
//
// > All registered media types MUST be assigned top-level type and
// > subtype names.  The combination of these names serves to uniquely
// > identify the media type, and the subtype name facet (or the absence
// > of one) identifies the registration tree.  Both top-level type and
// > subtype names are case-insensitive.
// >
// > Type and subtype names MUST conform to the following ABNF:
// >
// >     type-name = restricted-name
// >     subtype-name = restricted-name
// >
// >     restricted-name = restricted-name-first *126restricted-name-chars
// >     restricted-name-first  = ALPHA / DIGIT
// >     restricted-name-chars  = ALPHA / DIGIT / "!" / "#" /
// >                              "$" / "&" / "-" / "^" / "_"
// >     restricted-name-chars =/ "." ; Characters before first dot always
// >                                  ; specify a facet name
// >     restricted-name-chars =/ "+" ; Characters after last plus always
// >                                  ; specify a structured syntax suffix
//
fn is_restricted_name_first_char(c: char) -> bool {
    match c {
        'a'...'z' |
        '0'...'9' => true,
        _ => false
    }
}

fn is_restricted_name_char(c: char) -> bool {
    if is_restricted_name_first_char(c) {
        true
    } else {
        match c {
            '!' |
            '#' |
            '$' |
            '&' |
            '-' |
            '^' |
            '.' |
            '+' |
            '_' => true,
            _ => false
        }
    }
}

#[inline]
fn fmt_params<T: AsSlice<Param>>(params: T, fmt: &mut fmt::Formatter) -> fmt::Result {
    for param in params.as_slice().iter() {
        try!(fmt_param(param, fmt));
    }
    Ok(())
}

#[inline]
fn fmt_param(param: &Param, fmt: &mut fmt::Formatter) -> fmt::Result {
    let (ref attr, ref value) = *param;
    write!(fmt, "; {}={}", attr, value)
}

#[cfg(test)]
mod tests {
    use std::str::{FromStr, from_str};
    use test::Bencher;
    use super::{TopLevel, SubLevel, Attr, Value, Mime};

    #[test]
    fn test_mime_show() {
        let mime = Mime(TopLevel::Text, SubLevel::Plain, vec![]);
        assert_eq!(mime.to_string(), "text/plain".to_string());
        let mime = Mime(TopLevel::Text, SubLevel::Plain, vec![(Attr::Charset, Value::Utf8)]);
        assert_eq!(mime.to_string(), "text/plain; charset=utf-8".to_string());
    }

    #[test]
    fn test_mime_from_str() {
        assert_eq!(FromStr::from_str("text/plain"), Some(Mime(TopLevel::Text, SubLevel::Plain, vec![])));
        assert_eq!(FromStr::from_str("TEXT/PLAIN"), Some(Mime(TopLevel::Text, SubLevel::Plain, vec![])));
        assert_eq!(FromStr::from_str("text/plain; charset=utf-8"), Some(Mime(TopLevel::Text, SubLevel::Plain, vec![(Attr::Charset, Value::Utf8)])));
        assert_eq!(FromStr::from_str("text/plain;charset=\"utf-8\""), Some(Mime(TopLevel::Text, SubLevel::Plain, vec![(Attr::Charset, Value::Utf8)])));
        assert_eq!(FromStr::from_str("text/plain; charset=utf-8; foo=bar"),
            Some(Mime(TopLevel::Text, SubLevel::Plain, vec![(Attr::Charset, Value::Utf8),
                                        (Attr::Ext("foo".to_string()), Value::Ext("bar".to_string())) ])));
    }

    #[bench]
    fn bench_show(b: &mut Bencher) {
        let mime = Mime(TopLevel::Text, SubLevel::Plain, vec![(Attr::Charset, Value::Utf8), (Attr::Ext("foo".to_string()), Value::Ext("bar".to_string()))]);
        b.bytes = mime.to_string().as_bytes().len() as u64;
        b.iter(|| mime.to_string())
    }

    #[bench]
    fn bench_from_str(b: &mut Bencher) {
        let s = "text/plain; charset=utf-8; foo=bar";
        b.bytes = s.as_bytes().len() as u64;
        b.iter(|| from_str::<Mime>(s))
    }
}
<|endoftext|>


<commit_before>extern crate libc;
extern crate c_vec;

use libc::c_void;

macro_rules! caller {
    ($func:expr, $size:expr, $list:expr) => (
        if let Some(el) = $list.pop() {
            caller!($func, $list, $size, el)
        } else {
            call_func($func, $size)
        }
    );
    ($func:expr, $size:expr, $list:expr, $arg:expr) => (
        if let Some(el) = $list.pop() {
            caller!($func, $list, $size, el, $arg)
        } else {
            call_func($func, $size)
        }
    );
    ($func:expr, $size:expr, $list:expr, $($args:expr),*) => (
        if let Some(el) = $list.pop() {
            caller!($func, $list, el, $($args),*)
        } else {
            call_func($func, $size, $($args),*)
        }
    )
}

pub struct VaList {
    args: Vec<*mut c_void>,
}

impl VaList {
    pub fn new() -> VaList {
        VaList {
            args: vec!(),
        }
    }

    pub fn add_arg<T>(&mut self, arg: &T) {
        self.push(arg as *mut _ as *mut c_void);
    }

    pub fn to_c_va_list<F: Fn(*mut va_list)>(self, func: F) {
        let f = transmute(func);
        caller!(func, self.args.len(), self.args);
    }
}

// part to call in C directly
extern "C" fn call_func(f: *mut c_void, num_args: u32, ...) {
    let f: &Box_<Fn(*mut va_list) + 'static> = transmute(f);
    va_list ap;
    va_start(ap, num_args);
    f(ap);
    va_end(ap);
}
<commit_msg>Go full macro, missing the C part<commit_after>extern crate libc;

use libc::c_void;

#[macro_export]
macro_rules! caller {
    ($func:expr, $nb_args:expr, $($args:expr),*) => {{
        c_func(convert_closure($func), $nb_args, $($args:expr),*);
    }}
}

fn convert_closure<F: Fn(*mut va_list)>(f: F) -> *mut c_void {
    let f: Box<Box<F>> = Box::new(Box::new(f));
    Box::into_raw(f) as *mut _
}

pub struct va_list;

// part to call in C directly
/*extern "C" fn call_func(f: *mut c_void, num_args: u32, ...) {
    let f: &Box_<Fn(*mut va_list) + 'static> = transmute(f);
    va_list ap;
    va_start(ap, num_args);
    f(ap);
    va_end(ap);
}*/
<|endoftext|>


<commit_before>#![feature(no_std)]
#![feature(core)]
#![no_std]

#![crate_name = "multiboot"]
#![crate_type = "lib"]

extern crate core;

use core::mem::{transmute};

/// Value that is in rax after multiboot jumps to our entry point
pub const SIGNATURE_RAX: u64 = 0x2BADB002;

#[derive(Debug)]
pub enum MemType {
    RAM = 1,
    Unusable = 2,
}

/// Multiboot struct clients mainly interact with
/// To create this use Multiboot::new()
pub struct Multiboot<'a> {
    header: &'a MultibootHeader,
    paddr_to_vaddr: fn(u64) -> u64,
}

/// Representation of Multiboot header according to specification.
#[derive(Debug)]
#[repr(packed)]
struct MultibootHeader {
    flags: u32,

    mem_lower: u32,
    mem_upper: u32,

    boot_device: u32,
    cmdline: u32,

    mods_count: u32,
    mods_addr: u32,

    elf_symbols: ElfSymbols,

    mmap_length: u32,
    mmap_addr: u32,
}

/// Multiboot format of the MMAP buffer.
/// Note that size is defined to be at -4 bytes.
#[derive(Debug)]
#[repr(packed)]
struct MemEntry {
    size: u32,
    base_addr: u64,
    length: u64,
    mtype: u32
}

#[derive(Debug)]
#[repr(packed)]
struct ElfSymbols {
    num: u32,
    size: u32,
    addr: u32,
    shndx: u32,
}

impl<'a> Multiboot<'a> {

    /// Initializes the multiboot structure.
    ///
    /// # Arguments
    ///
    ///  * `mboot_ptr` - The physical address of the multiboot header. On qemu for example
    ///                  this is typically at 0x9500.
    ///  * `paddr_to_vaddr` - Translation of the physical addresses into kernel addresses.
    ///
    ///  `paddr_to_vaddr` translates physical it into a kernel accessible address.
    ///  The simplest paddr_to_vaddr function would for example be just the identity
    ///  function. But this may vary depending on how your page table layout looks like.
    ///
    pub fn new(mboot_ptr: u64, paddr_to_vaddr: fn(paddr: u64) -> u64) -> Multiboot<'a> {
        let header = paddr_to_vaddr(mboot_ptr);
        let mb: &MultibootHeader = unsafe { transmute::<u64, &MultibootHeader>(header) };

        Multiboot { header: mb, paddr_to_vaddr: paddr_to_vaddr }
    }

    /// Discover all memory regions in the multiboot memory map.
    ///
    /// # Arguments
    ///
    ///  * `discovery_callback` - Function to notify your memory system about regions.
    ///
    pub fn find_memory(&'a self, discovery_callback: fn(base: u64, length: u64, MemType))
    {
        let paddr_to_vaddr = self.paddr_to_vaddr;

        let mut current = self.header.mmap_addr;
        let end = self.header.mmap_addr + self.header.mmap_length;
        while current < end
        {
            let memory_region: &MemEntry = unsafe { transmute::<u64, &MemEntry>(paddr_to_vaddr(current as u64)) };

            let mtype = match memory_region.mtype {
                1 => MemType::RAM,
                2 => MemType::Unusable,
                _ => MemType::Unusable
            };

            discovery_callback(memory_region.base_addr, memory_region.length, mtype);
            current += memory_region.size + 4;
        }
    }

}
<commit_msg>Make sure cargo test runs.<commit_after>#![feature(no_std)]
#![feature(core)]
#![no_std]

#![crate_name = "multiboot"]
#![crate_type = "lib"]

extern crate core;

#[cfg(test)]
#[macro_use]
extern crate std;

use core::mem::{transmute};

/// Value that is in rax after multiboot jumps to our entry point
pub const SIGNATURE_RAX: u64 = 0x2BADB002;

#[derive(Debug)]
pub enum MemType {
    RAM = 1,
    Unusable = 2,
}

/// Multiboot struct clients mainly interact with
/// To create this use Multiboot::new()
pub struct Multiboot<'a> {
    header: &'a MultibootHeader,
    paddr_to_vaddr: fn(u64) -> u64,
}

/// Representation of Multiboot header according to specification.
#[derive(Debug)]
#[repr(packed)]
struct MultibootHeader {
    flags: u32,

    mem_lower: u32,
    mem_upper: u32,

    boot_device: u32,
    cmdline: u32,

    mods_count: u32,
    mods_addr: u32,

    elf_symbols: ElfSymbols,

    mmap_length: u32,
    mmap_addr: u32,
}

/// Multiboot format of the MMAP buffer.
/// Note that size is defined to be at -4 bytes.
#[derive(Debug)]
#[repr(packed)]
struct MemEntry {
    size: u32,
    base_addr: u64,
    length: u64,
    mtype: u32
}

#[derive(Debug)]
#[repr(packed)]
struct ElfSymbols {
    num: u32,
    size: u32,
    addr: u32,
    shndx: u32,
}

impl<'a> Multiboot<'a> {

    /// Initializes the multiboot structure.
    ///
    /// # Arguments
    ///
    ///  * `mboot_ptr` - The physical address of the multiboot header. On qemu for example
    ///                  this is typically at 0x9500.
    ///  * `paddr_to_vaddr` - Translation of the physical addresses into kernel addresses.
    ///
    ///  `paddr_to_vaddr` translates physical it into a kernel accessible address.
    ///  The simplest paddr_to_vaddr function would for example be just the identity
    ///  function. But this may vary depending on how your page table layout looks like.
    ///
    pub fn new(mboot_ptr: u64, paddr_to_vaddr: fn(paddr: u64) -> u64) -> Multiboot<'a> {
        let header = paddr_to_vaddr(mboot_ptr);
        let mb: &MultibootHeader = unsafe { transmute::<u64, &MultibootHeader>(header) };

        Multiboot { header: mb, paddr_to_vaddr: paddr_to_vaddr }
    }

    /// Discover all memory regions in the multiboot memory map.
    ///
    /// # Arguments
    ///
    ///  * `discovery_callback` - Function to notify your memory system about regions.
    ///
    pub fn find_memory(&'a self, discovery_callback: fn(base: u64, length: u64, MemType))
    {
        let paddr_to_vaddr = self.paddr_to_vaddr;

        let mut current = self.header.mmap_addr;
        let end = self.header.mmap_addr + self.header.mmap_length;
        while current < end
        {
            let memory_region: &MemEntry = unsafe { transmute::<u64, &MemEntry>(paddr_to_vaddr(current as u64)) };

            let mtype = match memory_region.mtype {
                1 => MemType::RAM,
                2 => MemType::Unusable,
                _ => MemType::Unusable
            };

            discovery_callback(memory_region.base_addr, memory_region.length, mtype);
            current += memory_region.size + 4;
        }
    }

}
<|endoftext|>


<commit_before>
extern crate python3_sys as py_ffi;
extern crate numpy_sys as np_ffi;
extern crate cpython;

use cpython::PyObject;

pub struct PyArray(PyObject);

impl PyArray {
    pub fn as_ptr(&self) -> *mut np_ffi::PyArrayObject {
        self.0.as_ptr() as *mut np_ffi::PyArrayObject
    }
    pub fn steal_ptr(self) -> *mut np_ffi::PyArrayObject {
        self.0.steal_ptr() as *mut np_ffi::PyArrayObject
    }
}
<commit_msg>implement cpython traits for PyArray<commit_after>
extern crate python3_sys as py_ffi;
extern crate numpy_sys as np_ffi;
extern crate cpython;

use cpython::*;

pub struct PyArray(PyObject);

impl PyArray {
    pub fn as_ptr(&self) -> *mut np_ffi::PyArrayObject {
        self.0.as_ptr() as *mut np_ffi::PyArrayObject
    }

    pub fn steal_ptr(self) -> *mut np_ffi::PyArrayObject {
        self.0.steal_ptr() as *mut np_ffi::PyArrayObject
    }

    pub unsafe fn from_owned_ptr(py: Python, ptr: *mut np_ffi::PyArrayObject) -> Self {
        let obj = PyObject::from_owned_ptr(py, ptr as *mut py_ffi::PyObject);
        PyArray(obj)
    }

    pub unsafe fn from_borrowed_ptr(py: Python, ptr: *mut np_ffi::PyArrayObject) -> Self {
        let obj = PyObject::from_borrowed_ptr(py, ptr as *mut py_ffi::PyObject);
        PyArray(obj)
    }
}

impl ToPyObject for PyArray {
    type ObjectType = Self;

    fn to_py_object(&self, py: Python) -> Self {
        PyClone::clone_ref(self, py)
    }
}

impl PythonObject for PyArray {
    #[inline]
    fn as_object(&self) -> &PyObject {
        &self.0
    }

    #[inline]
    fn into_object(self) -> PyObject {
        self.0
    }

    #[inline]
    unsafe fn unchecked_downcast_from(obj: PyObject) -> Self {
        PyArray(obj)
    }

    #[inline]
    unsafe fn unchecked_downcast_borrow_from<'a>(obj: &'a PyObject) -> &'a Self {
        ::std::mem::transmute(obj)
    }
}

impl PythonObjectWithCheckedDowncast for PyArray {
    fn downcast_from<'p>(py: Python<'p>,
                         obj: PyObject)
                         -> Result<PyArray, PythonObjectDowncastError<'p>> {
        unsafe {
            if np_ffi::PyArray_Check(obj.as_ptr()) != 0 {
                Ok(PyArray(obj))
            } else {
                Err(PythonObjectDowncastError(py))
            }
        }
    }

    fn downcast_borrow_from<'a, 'p>(py: Python<'p>,
                                    obj: &'a PyObject)
                                    -> Result<&'a PyArray, PythonObjectDowncastError<'p>> {
        unsafe {
            if np_ffi::PyArray_Check(obj.as_ptr()) != 0 {
                Ok(::std::mem::transmute(obj))
            } else {
                Err(PythonObjectDowncastError(py))
            }
        }
    }
}
<|endoftext|>